linux/drivers/video/fbdev/sis/sis_main.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * SiS 300/540/630[S]/730[S],
   4 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
   5 * XGI V3XT/V5/V8, Z7
   6 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
   7 *
   8 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
   9 *
  10 * Author:      Thomas Winischhofer <thomas@winischhofer.net>
  11 *
  12 * Author of (practically wiped) code base:
  13 *              SiS (www.sis.com)
  14 *              Copyright (C) 1999 Silicon Integrated Systems, Inc.
  15 *
  16 * See http://www.winischhofer.net/ for more information and updates
  17 *
  18 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
  19 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/moduleparam.h>
  24#include <linux/kernel.h>
  25#include <linux/spinlock.h>
  26#include <linux/errno.h>
  27#include <linux/string.h>
  28#include <linux/mm.h>
  29#include <linux/screen_info.h>
  30#include <linux/slab.h>
  31#include <linux/fb.h>
  32#include <linux/selection.h>
  33#include <linux/ioport.h>
  34#include <linux/init.h>
  35#include <linux/pci.h>
  36#include <linux/vmalloc.h>
  37#include <linux/capability.h>
  38#include <linux/fs.h>
  39#include <linux/types.h>
  40#include <linux/uaccess.h>
  41#include <asm/io.h>
  42
  43#include "sis.h"
  44#include "sis_main.h"
  45#include "init301.h"
  46
  47#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
  48#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
  49#warning sisfb will not work!
  50#endif
  51
  52/* ---------------------- Prototypes ------------------------- */
  53
  54/* Interface used by the world */
  55#ifndef MODULE
  56static int sisfb_setup(char *options);
  57#endif
  58
  59/* Interface to the low level console driver */
  60static int sisfb_init(void);
  61
  62/* fbdev routines */
  63static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
  64                                struct fb_info *info);
  65
  66static int      sisfb_ioctl(struct fb_info *info, unsigned int cmd,
  67                            unsigned long arg);
  68static int      sisfb_set_par(struct fb_info *info);
  69static int      sisfb_blank(int blank,
  70                                struct fb_info *info);
  71
  72static void sisfb_handle_command(struct sis_video_info *ivideo,
  73                                 struct sisfb_cmd *sisfb_command);
  74
  75static void     sisfb_search_mode(char *name, bool quiet);
  76static int      sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
  77static u8       sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
  78                                int index);
  79static int      sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  80                                unsigned blue, unsigned transp,
  81                                struct fb_info *fb_info);
  82static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
  83                                struct fb_info *info);
  84static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
  85static void     sisfb_post_setmode(struct sis_video_info *ivideo);
  86static bool     sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
  87static bool     sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
  88static bool     sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
  89static bool     sisfb_bridgeisslave(struct sis_video_info *ivideo);
  90static void     sisfb_detect_VB_connect(struct sis_video_info *ivideo);
  91static void     sisfb_get_VB_type(struct sis_video_info *ivideo);
  92static void     sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
  93static void     sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
  94
  95/* Internal heap routines */
  96static int              sisfb_heap_init(struct sis_video_info *ivideo);
  97static struct SIS_OH *  sisfb_poh_new_node(struct SIS_HEAP *memheap);
  98static struct SIS_OH *  sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
  99static void             sisfb_delete_node(struct SIS_OH *poh);
 100static void             sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
 101static struct SIS_OH *  sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
 102static void             sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
 103
 104
 105/* ------------------ Internal helper routines ----------------- */
 106
 107static void __init
 108sisfb_setdefaultparms(void)
 109{
 110        sisfb_off               = 0;
 111        sisfb_parm_mem          = 0;
 112        sisfb_accel             = -1;
 113        sisfb_ypan              = -1;
 114        sisfb_max               = -1;
 115        sisfb_userom            = -1;
 116        sisfb_useoem            = -1;
 117        sisfb_mode_idx          = -1;
 118        sisfb_parm_rate         = -1;
 119        sisfb_crt1off           = 0;
 120        sisfb_forcecrt1         = -1;
 121        sisfb_crt2type          = -1;
 122        sisfb_crt2flags         = 0;
 123        sisfb_pdc               = 0xff;
 124        sisfb_pdca              = 0xff;
 125        sisfb_scalelcd          = -1;
 126        sisfb_specialtiming     = CUT_NONE;
 127        sisfb_lvdshl            = -1;
 128        sisfb_dstn              = 0;
 129        sisfb_fstn              = 0;
 130        sisfb_tvplug            = -1;
 131        sisfb_tvstd             = -1;
 132        sisfb_tvxposoffset      = 0;
 133        sisfb_tvyposoffset      = 0;
 134        sisfb_nocrt2rate        = 0;
 135#if !defined(__i386__) && !defined(__x86_64__)
 136        sisfb_resetcard         = 0;
 137        sisfb_videoram          = 0;
 138#endif
 139}
 140
 141/* ------------- Parameter parsing -------------- */
 142
 143static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
 144{
 145        int i = 0, j = 0;
 146
 147        /* We don't know the hardware specs yet and there is no ivideo */
 148
 149        if(vesamode == 0) {
 150                if(!quiet)
 151                        printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
 152
 153                sisfb_mode_idx = DEFAULT_MODE;
 154
 155                return;
 156        }
 157
 158        vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
 159
 160        while(sisbios_mode[i++].mode_no[0] != 0) {
 161                if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
 162                    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
 163                        if(sisfb_fstn) {
 164                                if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
 165                                   sisbios_mode[i-1].mode_no[1] == 0x56 ||
 166                                   sisbios_mode[i-1].mode_no[1] == 0x53)
 167                                        continue;
 168                        } else {
 169                                if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
 170                                   sisbios_mode[i-1].mode_no[1] == 0x5b)
 171                                        continue;
 172                        }
 173                        sisfb_mode_idx = i - 1;
 174                        j = 1;
 175                        break;
 176                }
 177        }
 178        if((!j) && !quiet)
 179                printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
 180}
 181
 182static void sisfb_search_mode(char *name, bool quiet)
 183{
 184        unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
 185        int i = 0;
 186        char strbuf[16], strbuf1[20];
 187        char *nameptr = name;
 188
 189        /* We don't know the hardware specs yet and there is no ivideo */
 190
 191        if(name == NULL) {
 192                if(!quiet)
 193                        printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
 194
 195                sisfb_mode_idx = DEFAULT_MODE;
 196                return;
 197        }
 198
 199        if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
 200                if(!quiet)
 201                        printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
 202
 203                sisfb_mode_idx = DEFAULT_MODE;
 204                return;
 205        }
 206
 207        if(strlen(name) <= 19) {
 208                strcpy(strbuf1, name);
 209                for(i = 0; i < strlen(strbuf1); i++) {
 210                        if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
 211                }
 212
 213                /* This does some fuzzy mode naming detection */
 214                if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
 215                        if((rate <= 32) || (depth > 32)) {
 216                                j = rate; rate = depth; depth = j;
 217                        }
 218                        sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
 219                        nameptr = strbuf;
 220                        sisfb_parm_rate = rate;
 221                } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
 222                        sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
 223                        nameptr = strbuf;
 224                } else {
 225                        xres = 0;
 226                        if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
 227                                sprintf(strbuf, "%ux%ux8", xres, yres);
 228                                nameptr = strbuf;
 229                        } else {
 230                                sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
 231                                return;
 232                        }
 233                }
 234        }
 235
 236        i = 0; j = 0;
 237        while(sisbios_mode[i].mode_no[0] != 0) {
 238                if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
 239                        if(sisfb_fstn) {
 240                                if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
 241                                   sisbios_mode[i-1].mode_no[1] == 0x56 ||
 242                                   sisbios_mode[i-1].mode_no[1] == 0x53)
 243                                        continue;
 244                        } else {
 245                                if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
 246                                   sisbios_mode[i-1].mode_no[1] == 0x5b)
 247                                        continue;
 248                        }
 249                        sisfb_mode_idx = i - 1;
 250                        j = 1;
 251                        break;
 252                }
 253        }
 254
 255        if((!j) && !quiet)
 256                printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
 257}
 258
 259#ifndef MODULE
 260static void sisfb_get_vga_mode_from_kernel(void)
 261{
 262#ifdef CONFIG_X86
 263        char mymode[32];
 264        int  mydepth = screen_info.lfb_depth;
 265
 266        if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
 267
 268        if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
 269            (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
 270            (mydepth >= 8) && (mydepth <= 32) ) {
 271
 272                if(mydepth == 24) mydepth = 32;
 273
 274                sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
 275                                        screen_info.lfb_height,
 276                                        mydepth);
 277
 278                printk(KERN_DEBUG
 279                        "sisfb: Using vga mode %s pre-set by kernel as default\n",
 280                        mymode);
 281
 282                sisfb_search_mode(mymode, true);
 283        }
 284#endif
 285        return;
 286}
 287#endif
 288
 289static void __init
 290sisfb_search_crt2type(const char *name)
 291{
 292        int i = 0;
 293
 294        /* We don't know the hardware specs yet and there is no ivideo */
 295
 296        if(name == NULL) return;
 297
 298        while(sis_crt2type[i].type_no != -1) {
 299                if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
 300                        sisfb_crt2type = sis_crt2type[i].type_no;
 301                        sisfb_tvplug = sis_crt2type[i].tvplug_no;
 302                        sisfb_crt2flags = sis_crt2type[i].flags;
 303                        break;
 304                }
 305                i++;
 306        }
 307
 308        sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
 309        sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
 310
 311        if(sisfb_crt2type < 0)
 312                printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
 313}
 314
 315static void __init
 316sisfb_search_tvstd(const char *name)
 317{
 318        int i = 0;
 319
 320        /* We don't know the hardware specs yet and there is no ivideo */
 321
 322        if(name == NULL)
 323                return;
 324
 325        while(sis_tvtype[i].type_no != -1) {
 326                if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
 327                        sisfb_tvstd = sis_tvtype[i].type_no;
 328                        break;
 329                }
 330                i++;
 331        }
 332}
 333
 334static void __init
 335sisfb_search_specialtiming(const char *name)
 336{
 337        int i = 0;
 338        bool found = false;
 339
 340        /* We don't know the hardware specs yet and there is no ivideo */
 341
 342        if(name == NULL)
 343                return;
 344
 345        if(!strncasecmp(name, "none", 4)) {
 346                sisfb_specialtiming = CUT_FORCENONE;
 347                printk(KERN_DEBUG "sisfb: Special timing disabled\n");
 348        } else {
 349                while(mycustomttable[i].chipID != 0) {
 350                        if(!strncasecmp(name,mycustomttable[i].optionName,
 351                           strlen(mycustomttable[i].optionName))) {
 352                                sisfb_specialtiming = mycustomttable[i].SpecialID;
 353                                found = true;
 354                                printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
 355                                        mycustomttable[i].vendorName,
 356                                        mycustomttable[i].cardName,
 357                                        mycustomttable[i].optionName);
 358                                break;
 359                        }
 360                        i++;
 361                }
 362                if(!found) {
 363                        printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
 364                        printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
 365                        i = 0;
 366                        while(mycustomttable[i].chipID != 0) {
 367                                printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
 368                                        mycustomttable[i].optionName,
 369                                        mycustomttable[i].vendorName,
 370                                        mycustomttable[i].cardName);
 371                                i++;
 372                        }
 373                }
 374        }
 375}
 376
 377/* ----------- Various detection routines ----------- */
 378
 379static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
 380{
 381        unsigned char *biosver = NULL;
 382        unsigned char *biosdate = NULL;
 383        bool footprint;
 384        u32 chksum = 0;
 385        int i, j;
 386
 387        if(ivideo->SiS_Pr.UseROM) {
 388                biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
 389                biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
 390                for(i = 0; i < 32768; i++)
 391                        chksum += ivideo->SiS_Pr.VirtualRomBase[i];
 392        }
 393
 394        i = 0;
 395        do {
 396                if( (mycustomttable[i].chipID == ivideo->chip)                  &&
 397                    ((!strlen(mycustomttable[i].biosversion)) ||
 398                     (ivideo->SiS_Pr.UseROM &&
 399                      (!strncmp(mycustomttable[i].biosversion, biosver,
 400                                strlen(mycustomttable[i].biosversion)))))       &&
 401                    ((!strlen(mycustomttable[i].biosdate)) ||
 402                     (ivideo->SiS_Pr.UseROM &&
 403                      (!strncmp(mycustomttable[i].biosdate, biosdate,
 404                                strlen(mycustomttable[i].biosdate)))))          &&
 405                    ((!mycustomttable[i].bioschksum) ||
 406                     (ivideo->SiS_Pr.UseROM &&
 407                      (mycustomttable[i].bioschksum == chksum)))                &&
 408                    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
 409                    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
 410                        footprint = true;
 411                        for(j = 0; j < 5; j++) {
 412                                if(mycustomttable[i].biosFootprintAddr[j]) {
 413                                        if(ivideo->SiS_Pr.UseROM) {
 414                                                if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
 415                                                        mycustomttable[i].biosFootprintData[j]) {
 416                                                        footprint = false;
 417                                                }
 418                                        } else
 419                                                footprint = false;
 420                                }
 421                        }
 422                        if(footprint) {
 423                                ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
 424                                printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
 425                                        mycustomttable[i].vendorName,
 426                                mycustomttable[i].cardName);
 427                                printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
 428                                        mycustomttable[i].optionName);
 429                                break;
 430                        }
 431                }
 432                i++;
 433        } while(mycustomttable[i].chipID);
 434}
 435
 436static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 437{
 438        int i, j, xres, yres, refresh, index;
 439        u32 emodes;
 440
 441        if(buffer[0] != 0x00 || buffer[1] != 0xff ||
 442           buffer[2] != 0xff || buffer[3] != 0xff ||
 443           buffer[4] != 0xff || buffer[5] != 0xff ||
 444           buffer[6] != 0xff || buffer[7] != 0x00) {
 445                printk(KERN_DEBUG "sisfb: Bad EDID header\n");
 446                return false;
 447        }
 448
 449        if(buffer[0x12] != 0x01) {
 450                printk(KERN_INFO "sisfb: EDID version %d not supported\n",
 451                        buffer[0x12]);
 452                return false;
 453        }
 454
 455        monitor->feature = buffer[0x18];
 456
 457        if(!(buffer[0x14] & 0x80)) {
 458                if(!(buffer[0x14] & 0x08)) {
 459                        printk(KERN_INFO
 460                                "sisfb: WARNING: Monitor does not support separate syncs\n");
 461                }
 462        }
 463
 464        if(buffer[0x13] >= 0x01) {
 465           /* EDID V1 rev 1 and 2: Search for monitor descriptor
 466            * to extract ranges
 467            */
 468            j = 0x36;
 469            for(i=0; i<4; i++) {
 470               if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
 471                  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
 472                  buffer[j + 4] == 0x00) {
 473                  monitor->hmin = buffer[j + 7];
 474                  monitor->hmax = buffer[j + 8];
 475                  monitor->vmin = buffer[j + 5];
 476                  monitor->vmax = buffer[j + 6];
 477                  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
 478                  monitor->datavalid = true;
 479                  break;
 480               }
 481               j += 18;
 482            }
 483        }
 484
 485        if(!monitor->datavalid) {
 486           /* Otherwise: Get a range from the list of supported
 487            * Estabished Timings. This is not entirely accurate,
 488            * because fixed frequency monitors are not supported
 489            * that way.
 490            */
 491           monitor->hmin = 65535; monitor->hmax = 0;
 492           monitor->vmin = 65535; monitor->vmax = 0;
 493           monitor->dclockmax = 0;
 494           emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
 495           for(i = 0; i < 13; i++) {
 496              if(emodes & sisfb_ddcsmodes[i].mask) {
 497                 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
 498                 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
 499                 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
 500                 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
 501                 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
 502              }
 503           }
 504           index = 0x26;
 505           for(i = 0; i < 8; i++) {
 506              xres = (buffer[index] + 31) * 8;
 507              switch(buffer[index + 1] & 0xc0) {
 508                 case 0xc0: yres = (xres * 9) / 16; break;
 509                 case 0x80: yres = (xres * 4) /  5; break;
 510                 case 0x40: yres = (xres * 3) /  4; break;
 511                 default:   yres = xres;            break;
 512              }
 513              refresh = (buffer[index + 1] & 0x3f) + 60;
 514              if((xres >= 640) && (yres >= 480)) {
 515                 for(j = 0; j < 8; j++) {
 516                    if((xres == sisfb_ddcfmodes[j].x) &&
 517                       (yres == sisfb_ddcfmodes[j].y) &&
 518                       (refresh == sisfb_ddcfmodes[j].v)) {
 519                      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
 520                      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
 521                      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
 522                      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
 523                      if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
 524                    }
 525                 }
 526              }
 527              index += 2;
 528           }
 529           if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
 530              monitor->datavalid = true;
 531           }
 532        }
 533
 534        return monitor->datavalid;
 535}
 536
 537static void sisfb_handle_ddc(struct sis_video_info *ivideo,
 538                             struct sisfb_monitor *monitor, int crtno)
 539{
 540        unsigned short temp, i, realcrtno = crtno;
 541        unsigned char  buffer[256];
 542
 543        monitor->datavalid = false;
 544
 545        if(crtno) {
 546           if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
 547           else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
 548           else return;
 549        }
 550
 551        if((ivideo->sisfb_crt1off) && (!crtno))
 552                return;
 553
 554        temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
 555                                realcrtno, 0, &buffer[0], ivideo->vbflags2);
 556        if((!temp) || (temp == 0xffff)) {
 557           printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
 558           return;
 559        } else {
 560           printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
 561           printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
 562                crtno + 1,
 563                (temp & 0x1a) ? "" : "[none of the supported]",
 564                (temp & 0x02) ? "2 " : "",
 565                (temp & 0x08) ? "D&P" : "",
 566                (temp & 0x10) ? "FPDI-2" : "");
 567           if(temp & 0x02) {
 568              i = 3;  /* Number of retrys */
 569              do {
 570                 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
 571                                     realcrtno, 1, &buffer[0], ivideo->vbflags2);
 572              } while((temp) && i--);
 573              if(!temp) {
 574                 if(sisfb_interpret_edid(monitor, &buffer[0])) {
 575                    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
 576                        monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
 577                        monitor->dclockmax / 1000);
 578                 } else {
 579                    printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
 580                 }
 581              } else {
 582                 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
 583              }
 584           } else {
 585              printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
 586           }
 587        }
 588}
 589
 590/* -------------- Mode validation --------------- */
 591
 592static bool
 593sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
 594                int mode_idx, int rate_idx, int rate)
 595{
 596        int htotal, vtotal;
 597        unsigned int dclock, hsync;
 598
 599        if(!monitor->datavalid)
 600                return true;
 601
 602        if(mode_idx < 0)
 603                return false;
 604
 605        /* Skip for 320x200, 320x240, 640x400 */
 606        switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
 607        case 0x59:
 608        case 0x41:
 609        case 0x4f:
 610        case 0x50:
 611        case 0x56:
 612        case 0x53:
 613        case 0x2f:
 614        case 0x5d:
 615        case 0x5e:
 616                return true;
 617#ifdef CONFIG_FB_SIS_315
 618        case 0x5a:
 619        case 0x5b:
 620                if(ivideo->sisvga_engine == SIS_315_VGA) return true;
 621#endif
 622        }
 623
 624        if(rate < (monitor->vmin - 1))
 625                return false;
 626        if(rate > (monitor->vmax + 1))
 627                return false;
 628
 629        if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
 630                                  sisbios_mode[mode_idx].mode_no[ivideo->mni],
 631                                  &htotal, &vtotal, rate_idx)) {
 632                dclock = (htotal * vtotal * rate) / 1000;
 633                if(dclock > (monitor->dclockmax + 1000))
 634                        return false;
 635                hsync = dclock / htotal;
 636                if(hsync < (monitor->hmin - 1))
 637                        return false;
 638                if(hsync > (monitor->hmax + 1))
 639                        return false;
 640        } else {
 641                return false;
 642        }
 643        return true;
 644}
 645
 646static int
 647sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
 648{
 649        u16 xres=0, yres, myres;
 650
 651#ifdef CONFIG_FB_SIS_300
 652        if(ivideo->sisvga_engine == SIS_300_VGA) {
 653                if(!(sisbios_mode[myindex].chipset & MD_SIS300))
 654                        return -1 ;
 655        }
 656#endif
 657#ifdef CONFIG_FB_SIS_315
 658        if(ivideo->sisvga_engine == SIS_315_VGA) {
 659                if(!(sisbios_mode[myindex].chipset & MD_SIS315))
 660                        return -1;
 661        }
 662#endif
 663
 664        myres = sisbios_mode[myindex].yres;
 665
 666        switch(vbflags & VB_DISPTYPE_DISP2) {
 667
 668        case CRT2_LCD:
 669                xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 670
 671                if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
 672                   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
 673                        if(sisbios_mode[myindex].xres > xres)
 674                                return -1;
 675                        if(myres > yres)
 676                                return -1;
 677                }
 678
 679                if(ivideo->sisfb_fstn) {
 680                        if(sisbios_mode[myindex].xres == 320) {
 681                                if(myres == 240) {
 682                                        switch(sisbios_mode[myindex].mode_no[1]) {
 683                                                case 0x50: myindex = MODE_FSTN_8;  break;
 684                                                case 0x56: myindex = MODE_FSTN_16; break;
 685                                                case 0x53: return -1;
 686                                        }
 687                                }
 688                        }
 689                }
 690
 691                if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 692                                sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
 693                                ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
 694                        return -1;
 695                }
 696                break;
 697
 698        case CRT2_TV:
 699                if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 700                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
 701                        return -1;
 702                }
 703                break;
 704
 705        case CRT2_VGA:
 706                if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 707                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
 708                        return -1;
 709                }
 710                break;
 711        }
 712
 713        return myindex;
 714}
 715
 716static u8
 717sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
 718{
 719        int i = 0;
 720        u16 xres = sisbios_mode[mode_idx].xres;
 721        u16 yres = sisbios_mode[mode_idx].yres;
 722
 723        ivideo->rate_idx = 0;
 724        while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
 725                if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
 726                        if(sisfb_vrate[i].refresh == rate) {
 727                                ivideo->rate_idx = sisfb_vrate[i].idx;
 728                                break;
 729                        } else if(sisfb_vrate[i].refresh > rate) {
 730                                if((sisfb_vrate[i].refresh - rate) <= 3) {
 731                                        DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
 732                                                rate, sisfb_vrate[i].refresh);
 733                                        ivideo->rate_idx = sisfb_vrate[i].idx;
 734                                        ivideo->refresh_rate = sisfb_vrate[i].refresh;
 735                                } else if((sisfb_vrate[i].idx != 1) &&
 736                                                ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
 737                                        DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 738                                                rate, sisfb_vrate[i-1].refresh);
 739                                        ivideo->rate_idx = sisfb_vrate[i-1].idx;
 740                                        ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
 741                                }
 742                                break;
 743                        } else if((rate - sisfb_vrate[i].refresh) <= 2) {
 744                                DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 745                                                rate, sisfb_vrate[i].refresh);
 746                                ivideo->rate_idx = sisfb_vrate[i].idx;
 747                                break;
 748                        }
 749                }
 750                i++;
 751        }
 752        if(ivideo->rate_idx > 0) {
 753                return ivideo->rate_idx;
 754        } else {
 755                printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
 756                                rate, xres, yres);
 757                return 0;
 758        }
 759}
 760
 761static bool
 762sisfb_bridgeisslave(struct sis_video_info *ivideo)
 763{
 764        unsigned char P1_00;
 765
 766        if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
 767                return false;
 768
 769        P1_00 = SiS_GetReg(SISPART1, 0x00);
 770        if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
 771            ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 772                return true;
 773        } else {
 774                return false;
 775        }
 776}
 777
 778static bool
 779sisfballowretracecrt1(struct sis_video_info *ivideo)
 780{
 781        u8 temp;
 782
 783        temp = SiS_GetReg(SISCR, 0x17);
 784        if(!(temp & 0x80))
 785                return false;
 786
 787        temp = SiS_GetReg(SISSR, 0x1f);
 788        if(temp & 0xc0)
 789                return false;
 790
 791        return true;
 792}
 793
 794static bool
 795sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 796{
 797        if(!sisfballowretracecrt1(ivideo))
 798                return false;
 799
 800        if (SiS_GetRegByte(SISINPSTAT) & 0x08)
 801                return true;
 802        else
 803                return false;
 804}
 805
 806static void
 807sisfbwaitretracecrt1(struct sis_video_info *ivideo)
 808{
 809        int watchdog;
 810
 811        if(!sisfballowretracecrt1(ivideo))
 812                return;
 813
 814        watchdog = 65536;
 815        while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
 816        watchdog = 65536;
 817        while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
 818}
 819
 820static bool
 821sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 822{
 823        unsigned char temp, reg;
 824
 825        switch(ivideo->sisvga_engine) {
 826        case SIS_300_VGA: reg = 0x25; break;
 827        case SIS_315_VGA: reg = 0x30; break;
 828        default:          return false;
 829        }
 830
 831        temp = SiS_GetReg(SISPART1, reg);
 832        if(temp & 0x02)
 833                return true;
 834        else
 835                return false;
 836}
 837
 838static bool
 839sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 840{
 841        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 842                if(!sisfb_bridgeisslave(ivideo)) {
 843                        return sisfbcheckvretracecrt2(ivideo);
 844                }
 845        }
 846        return sisfbcheckvretracecrt1(ivideo);
 847}
 848
 849static u32
 850sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
 851{
 852        u8 idx, reg1, reg2, reg3, reg4;
 853        u32 ret = 0;
 854
 855        (*vcount) = (*hcount) = 0;
 856
 857        if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
 858
 859                ret |= (FB_VBLANK_HAVE_VSYNC  |
 860                        FB_VBLANK_HAVE_HBLANK |
 861                        FB_VBLANK_HAVE_VBLANK |
 862                        FB_VBLANK_HAVE_VCOUNT |
 863                        FB_VBLANK_HAVE_HCOUNT);
 864                switch(ivideo->sisvga_engine) {
 865                        case SIS_300_VGA: idx = 0x25; break;
 866                        default:
 867                        case SIS_315_VGA: idx = 0x30; break;
 868                }
 869                reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
 870                reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
 871                reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
 872                reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
 873                if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
 874                if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
 875                if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
 876                (*vcount) = reg3 | ((reg4 & 0x70) << 4);
 877                (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
 878
 879        } else if(sisfballowretracecrt1(ivideo)) {
 880
 881                ret |= (FB_VBLANK_HAVE_VSYNC  |
 882                        FB_VBLANK_HAVE_VBLANK |
 883                        FB_VBLANK_HAVE_VCOUNT |
 884                        FB_VBLANK_HAVE_HCOUNT);
 885                reg1 = SiS_GetRegByte(SISINPSTAT);
 886                if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
 887                if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
 888                reg1 = SiS_GetReg(SISCR, 0x20);
 889                reg1 = SiS_GetReg(SISCR, 0x1b);
 890                reg2 = SiS_GetReg(SISCR, 0x1c);
 891                reg3 = SiS_GetReg(SISCR, 0x1d);
 892                (*vcount) = reg2 | ((reg3 & 0x07) << 8);
 893                (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
 894        }
 895
 896        return ret;
 897}
 898
 899static int
 900sisfb_myblank(struct sis_video_info *ivideo, int blank)
 901{
 902        u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
 903        bool backlight = true;
 904
 905        switch(blank) {
 906                case FB_BLANK_UNBLANK:  /* on */
 907                        sr01  = 0x00;
 908                        sr11  = 0x00;
 909                        sr1f  = 0x00;
 910                        cr63  = 0x00;
 911                        p2_0  = 0x20;
 912                        p1_13 = 0x00;
 913                        backlight = true;
 914                        break;
 915                case FB_BLANK_NORMAL:   /* blank */
 916                        sr01  = 0x20;
 917                        sr11  = 0x00;
 918                        sr1f  = 0x00;
 919                        cr63  = 0x00;
 920                        p2_0  = 0x20;
 921                        p1_13 = 0x00;
 922                        backlight = true;
 923                        break;
 924                case FB_BLANK_VSYNC_SUSPEND:    /* no vsync */
 925                        sr01  = 0x20;
 926                        sr11  = 0x08;
 927                        sr1f  = 0x80;
 928                        cr63  = 0x40;
 929                        p2_0  = 0x40;
 930                        p1_13 = 0x80;
 931                        backlight = false;
 932                        break;
 933                case FB_BLANK_HSYNC_SUSPEND:    /* no hsync */
 934                        sr01  = 0x20;
 935                        sr11  = 0x08;
 936                        sr1f  = 0x40;
 937                        cr63  = 0x40;
 938                        p2_0  = 0x80;
 939                        p1_13 = 0x40;
 940                        backlight = false;
 941                        break;
 942                case FB_BLANK_POWERDOWN:        /* off */
 943                        sr01  = 0x20;
 944                        sr11  = 0x08;
 945                        sr1f  = 0xc0;
 946                        cr63  = 0x40;
 947                        p2_0  = 0xc0;
 948                        p1_13 = 0xc0;
 949                        backlight = false;
 950                        break;
 951                default:
 952                        return 1;
 953        }
 954
 955        if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
 956
 957                if( (!ivideo->sisfb_thismonitor.datavalid) ||
 958                    ((ivideo->sisfb_thismonitor.datavalid) &&
 959                     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 960
 961                        if(ivideo->sisvga_engine == SIS_315_VGA) {
 962                                SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 963                        }
 964
 965                        if(!(sisfb_bridgeisslave(ivideo))) {
 966                                SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
 967                                SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
 968                        }
 969                }
 970
 971        }
 972
 973        if(ivideo->currentvbflags & CRT2_LCD) {
 974
 975                if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
 976                        if(backlight) {
 977                                SiS_SiS30xBLOn(&ivideo->SiS_Pr);
 978                        } else {
 979                                SiS_SiS30xBLOff(&ivideo->SiS_Pr);
 980                        }
 981                } else if(ivideo->sisvga_engine == SIS_315_VGA) {
 982#ifdef CONFIG_FB_SIS_315
 983                        if(ivideo->vbflags2 & VB2_CHRONTEL) {
 984                                if(backlight) {
 985                                        SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
 986                                } else {
 987                                        SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
 988                                }
 989                        }
 990#endif
 991                }
 992
 993                if(((ivideo->sisvga_engine == SIS_300_VGA) &&
 994                    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
 995                   ((ivideo->sisvga_engine == SIS_315_VGA) &&
 996                    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
 997                        SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
 998                }
 999
1000                if(ivideo->sisvga_engine == SIS_300_VGA) {
1001                        if((ivideo->vbflags2 & VB2_30xB) &&
1002                           (!(ivideo->vbflags2 & VB2_30xBDH))) {
1003                                SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
1004                        }
1005                } else if(ivideo->sisvga_engine == SIS_315_VGA) {
1006                        if((ivideo->vbflags2 & VB2_30xB) &&
1007                           (!(ivideo->vbflags2 & VB2_30xBDH))) {
1008                                SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1009                        }
1010                }
1011
1012        } else if(ivideo->currentvbflags & CRT2_VGA) {
1013
1014                if(ivideo->vbflags2 & VB2_30xB) {
1015                        SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1016                }
1017
1018        }
1019
1020        return 0;
1021}
1022
1023/* ------------- Callbacks from init.c/init301.c  -------------- */
1024
1025#ifdef CONFIG_FB_SIS_300
1026unsigned int
1027sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1028{
1029   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1030   u32 val = 0;
1031
1032   pci_read_config_dword(ivideo->nbridge, reg, &val);
1033   return (unsigned int)val;
1034}
1035
1036void
1037sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1038{
1039   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1040
1041   pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1042}
1043
1044unsigned int
1045sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1046{
1047   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1048   u32 val = 0;
1049
1050   if(!ivideo->lpcdev) return 0;
1051
1052   pci_read_config_dword(ivideo->lpcdev, reg, &val);
1053   return (unsigned int)val;
1054}
1055#endif
1056
1057#ifdef CONFIG_FB_SIS_315
1058void
1059sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1060{
1061   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1062
1063   pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1064}
1065
1066unsigned int
1067sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1068{
1069   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1070   u16 val = 0;
1071
1072   if(!ivideo->lpcdev) return 0;
1073
1074   pci_read_config_word(ivideo->lpcdev, reg, &val);
1075   return (unsigned int)val;
1076}
1077#endif
1078
1079/* ----------- FBDev related routines for all series ----------- */
1080
1081static int
1082sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1083{
1084        return (var->bits_per_pixel == 8) ? 256 : 16;
1085}
1086
1087static void
1088sisfb_set_vparms(struct sis_video_info *ivideo)
1089{
1090        switch(ivideo->video_bpp) {
1091        case 8:
1092                ivideo->DstColor = 0x0000;
1093                ivideo->SiS310_AccelDepth = 0x00000000;
1094                ivideo->video_cmap_len = 256;
1095                break;
1096        case 16:
1097                ivideo->DstColor = 0x8000;
1098                ivideo->SiS310_AccelDepth = 0x00010000;
1099                ivideo->video_cmap_len = 16;
1100                break;
1101        case 32:
1102                ivideo->DstColor = 0xC000;
1103                ivideo->SiS310_AccelDepth = 0x00020000;
1104                ivideo->video_cmap_len = 16;
1105                break;
1106        default:
1107                ivideo->video_cmap_len = 16;
1108                printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1109                ivideo->accel = 0;
1110        }
1111}
1112
1113static int
1114sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1115{
1116        int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1117
1118        if(maxyres > 32767) maxyres = 32767;
1119
1120        return maxyres;
1121}
1122
1123static void
1124sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1125{
1126        ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1127        ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1128        if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1129                if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1130                        ivideo->scrnpitchCRT1 <<= 1;
1131                }
1132        }
1133}
1134
1135static void
1136sisfb_set_pitch(struct sis_video_info *ivideo)
1137{
1138        bool isslavemode = false;
1139        unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1140        unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1141
1142        if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1143
1144        /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1145        if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1146                SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1147                SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1148        }
1149
1150        /* We must not set the pitch for CRT2 if bridge is in slave mode */
1151        if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1152                SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1153                SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1154                SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1155        }
1156}
1157
1158static void
1159sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1160{
1161        ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1162
1163        switch(var->bits_per_pixel) {
1164        case 8:
1165                var->red.offset = var->green.offset = var->blue.offset = 0;
1166                var->red.length = var->green.length = var->blue.length = 8;
1167                break;
1168        case 16:
1169                var->red.offset = 11;
1170                var->red.length = 5;
1171                var->green.offset = 5;
1172                var->green.length = 6;
1173                var->blue.offset = 0;
1174                var->blue.length = 5;
1175                var->transp.offset = 0;
1176                var->transp.length = 0;
1177                break;
1178        case 32:
1179                var->red.offset = 16;
1180                var->red.length = 8;
1181                var->green.offset = 8;
1182                var->green.length = 8;
1183                var->blue.offset = 0;
1184                var->blue.length = 8;
1185                var->transp.offset = 24;
1186                var->transp.length = 8;
1187                break;
1188        }
1189}
1190
1191static int
1192sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1193{
1194        unsigned short modeno = ivideo->mode_no;
1195
1196        /* >=2.6.12's fbcon clears the screen anyway */
1197        modeno |= 0x80;
1198
1199        SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1200
1201        sisfb_pre_setmode(ivideo);
1202
1203        if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1204                printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1205                return -EINVAL;
1206        }
1207
1208        SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1209
1210        sisfb_post_setmode(ivideo);
1211
1212        return 0;
1213}
1214
1215
1216static int
1217sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1218{
1219        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1220        unsigned int htotal = 0, vtotal = 0;
1221        unsigned int drate = 0, hrate = 0;
1222        int found_mode = 0, ret;
1223        int old_mode;
1224        u32 pixclock;
1225
1226        htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1227
1228        vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1229
1230        pixclock = var->pixclock;
1231
1232        if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1233                vtotal += var->yres;
1234                vtotal <<= 1;
1235        } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1236                vtotal += var->yres;
1237                vtotal <<= 2;
1238        } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1239                vtotal += var->yres;
1240                vtotal <<= 1;
1241        } else  vtotal += var->yres;
1242
1243        if(!(htotal) || !(vtotal)) {
1244                DPRINTK("sisfb: Invalid 'var' information\n");
1245                return -EINVAL;
1246        }
1247
1248        if(pixclock && htotal && vtotal) {
1249                drate = 1000000000 / pixclock;
1250                hrate = (drate * 1000) / htotal;
1251                ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1252        } else {
1253                ivideo->refresh_rate = 60;
1254        }
1255
1256        old_mode = ivideo->sisfb_mode_idx;
1257        ivideo->sisfb_mode_idx = 0;
1258
1259        while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1260               (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1261                if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1262                    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1263                    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1264                        ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1265                        found_mode = 1;
1266                        break;
1267                }
1268                ivideo->sisfb_mode_idx++;
1269        }
1270
1271        if(found_mode) {
1272                ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1273                                ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1274        } else {
1275                ivideo->sisfb_mode_idx = -1;
1276        }
1277
1278        if(ivideo->sisfb_mode_idx < 0) {
1279                printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1280                       var->yres, var->bits_per_pixel);
1281                ivideo->sisfb_mode_idx = old_mode;
1282                return -EINVAL;
1283        }
1284
1285        ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1286
1287        if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1288                ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1289                ivideo->refresh_rate = 60;
1290        }
1291
1292        if(isactive) {
1293                /* If acceleration to be used? Need to know
1294                 * before pre/post_set_mode()
1295                 */
1296                ivideo->accel = 0;
1297#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1298#ifdef STUPID_ACCELF_TEXT_SHIT
1299                if(var->accel_flags & FB_ACCELF_TEXT) {
1300                        info->flags &= ~FBINFO_HWACCEL_DISABLED;
1301                } else {
1302                        info->flags |= FBINFO_HWACCEL_DISABLED;
1303                }
1304#endif
1305                if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1306#else
1307                if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1308#endif
1309
1310                if((ret = sisfb_set_mode(ivideo, 1))) {
1311                        return ret;
1312                }
1313
1314                ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1315                ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1316                ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1317
1318                sisfb_calc_pitch(ivideo, var);
1319                sisfb_set_pitch(ivideo);
1320
1321                sisfb_set_vparms(ivideo);
1322
1323                ivideo->current_width = ivideo->video_width;
1324                ivideo->current_height = ivideo->video_height;
1325                ivideo->current_bpp = ivideo->video_bpp;
1326                ivideo->current_htotal = htotal;
1327                ivideo->current_vtotal = vtotal;
1328                ivideo->current_linelength = ivideo->video_linelength;
1329                ivideo->current_pixclock = var->pixclock;
1330                ivideo->current_refresh_rate = ivideo->refresh_rate;
1331                ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1332        }
1333
1334        return 0;
1335}
1336
1337static void
1338sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1339{
1340        SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1341
1342        SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1343        SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1344        SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1345        if(ivideo->sisvga_engine == SIS_315_VGA) {
1346                SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1347        }
1348}
1349
1350static void
1351sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1352{
1353        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1354                SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1355                SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1356                SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1357                SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1358                if(ivideo->sisvga_engine == SIS_315_VGA) {
1359                        SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1360                }
1361        }
1362}
1363
1364static int
1365sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1366              struct fb_var_screeninfo *var)
1367{
1368        ivideo->current_base = var->yoffset * info->var.xres_virtual
1369                             + var->xoffset;
1370
1371        /* calculate base bpp dep. */
1372        switch (info->var.bits_per_pixel) {
1373        case 32:
1374                break;
1375        case 16:
1376                ivideo->current_base >>= 1;
1377                break;
1378        case 8:
1379        default:
1380                ivideo->current_base >>= 2;
1381                break;
1382        }
1383
1384        ivideo->current_base += (ivideo->video_offset >> 2);
1385
1386        sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1387        sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1388
1389        return 0;
1390}
1391
1392static int
1393sisfb_open(struct fb_info *info, int user)
1394{
1395        return 0;
1396}
1397
1398static int
1399sisfb_release(struct fb_info *info, int user)
1400{
1401        return 0;
1402}
1403
1404static int
1405sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1406                unsigned transp, struct fb_info *info)
1407{
1408        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1409
1410        if(regno >= sisfb_get_cmap_len(&info->var))
1411                return 1;
1412
1413        switch(info->var.bits_per_pixel) {
1414        case 8:
1415                SiS_SetRegByte(SISDACA, regno);
1416                SiS_SetRegByte(SISDACD, (red >> 10));
1417                SiS_SetRegByte(SISDACD, (green >> 10));
1418                SiS_SetRegByte(SISDACD, (blue >> 10));
1419                if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1420                        SiS_SetRegByte(SISDAC2A, regno);
1421                        SiS_SetRegByte(SISDAC2D, (red >> 8));
1422                        SiS_SetRegByte(SISDAC2D, (green >> 8));
1423                        SiS_SetRegByte(SISDAC2D, (blue >> 8));
1424                }
1425                break;
1426        case 16:
1427                if (regno >= 16)
1428                        break;
1429
1430                ((u32 *)(info->pseudo_palette))[regno] =
1431                                (red & 0xf800)          |
1432                                ((green & 0xfc00) >> 5) |
1433                                ((blue & 0xf800) >> 11);
1434                break;
1435        case 32:
1436                if (regno >= 16)
1437                        break;
1438
1439                red >>= 8;
1440                green >>= 8;
1441                blue >>= 8;
1442                ((u32 *)(info->pseudo_palette))[regno] =
1443                                (red << 16) | (green << 8) | (blue);
1444                break;
1445        }
1446        return 0;
1447}
1448
1449static int
1450sisfb_set_par(struct fb_info *info)
1451{
1452        int err;
1453
1454        if((err = sisfb_do_set_var(&info->var, 1, info)))
1455                return err;
1456
1457        sisfb_get_fix(&info->fix, -1, info);
1458
1459        return 0;
1460}
1461
1462static int
1463sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1464{
1465        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1466        unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1467        unsigned int drate = 0, hrate = 0, maxyres;
1468        int found_mode = 0;
1469        int refresh_rate, search_idx, tidx;
1470        bool recalc_clock = false;
1471        u32 pixclock;
1472
1473        htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1474
1475        vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1476
1477        pixclock = var->pixclock;
1478
1479        if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1480                vtotal += var->yres;
1481                vtotal <<= 1;
1482        } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1483                vtotal += var->yres;
1484                vtotal <<= 2;
1485        } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1486                vtotal += var->yres;
1487                vtotal <<= 1;
1488        } else
1489                vtotal += var->yres;
1490
1491        if(!(htotal) || !(vtotal)) {
1492                SISFAIL("sisfb: no valid timing data");
1493        }
1494
1495        search_idx = 0;
1496        while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1497               (sisbios_mode[search_idx].xres <= var->xres) ) {
1498                if( (sisbios_mode[search_idx].xres == var->xres) &&
1499                    (sisbios_mode[search_idx].yres == var->yres) &&
1500                    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1501                        if((tidx = sisfb_validate_mode(ivideo, search_idx,
1502                                                ivideo->currentvbflags)) > 0) {
1503                                found_mode = 1;
1504                                search_idx = tidx;
1505                                break;
1506                        }
1507                }
1508                search_idx++;
1509        }
1510
1511        if(!found_mode) {
1512                search_idx = 0;
1513                while(sisbios_mode[search_idx].mode_no[0] != 0) {
1514                   if( (var->xres <= sisbios_mode[search_idx].xres) &&
1515                       (var->yres <= sisbios_mode[search_idx].yres) &&
1516                       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1517                        if((tidx = sisfb_validate_mode(ivideo,search_idx,
1518                                                ivideo->currentvbflags)) > 0) {
1519                                found_mode = 1;
1520                                search_idx = tidx;
1521                                break;
1522                        }
1523                   }
1524                   search_idx++;
1525                }
1526                if(found_mode) {
1527                        printk(KERN_DEBUG
1528                                "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1529                                var->xres, var->yres, var->bits_per_pixel,
1530                                sisbios_mode[search_idx].xres,
1531                                sisbios_mode[search_idx].yres,
1532                                var->bits_per_pixel);
1533                        var->xres = sisbios_mode[search_idx].xres;
1534                        var->yres = sisbios_mode[search_idx].yres;
1535                } else {
1536                        printk(KERN_ERR
1537                                "sisfb: Failed to find supported mode near %dx%dx%d\n",
1538                                var->xres, var->yres, var->bits_per_pixel);
1539                        return -EINVAL;
1540                }
1541        }
1542
1543        if( ((ivideo->vbflags2 & VB2_LVDS) ||
1544             ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1545            (var->bits_per_pixel == 8) ) {
1546                /* Slave modes on LVDS and 301B-DH */
1547                refresh_rate = 60;
1548                recalc_clock = true;
1549        } else if( (ivideo->current_htotal == htotal) &&
1550                   (ivideo->current_vtotal == vtotal) &&
1551                   (ivideo->current_pixclock == pixclock) ) {
1552                /* x=x & y=y & c=c -> assume depth change */
1553                drate = 1000000000 / pixclock;
1554                hrate = (drate * 1000) / htotal;
1555                refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1556        } else if( ( (ivideo->current_htotal != htotal) ||
1557                     (ivideo->current_vtotal != vtotal) ) &&
1558                   (ivideo->current_pixclock == var->pixclock) ) {
1559                /* x!=x | y!=y & c=c -> invalid pixclock */
1560                if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1561                        refresh_rate =
1562                                ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1563                } else if(ivideo->sisfb_parm_rate != -1) {
1564                        /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1565                        refresh_rate = ivideo->sisfb_parm_rate;
1566                } else {
1567                        refresh_rate = 60;
1568                }
1569                recalc_clock = true;
1570        } else if((pixclock) && (htotal) && (vtotal)) {
1571                drate = 1000000000 / pixclock;
1572                hrate = (drate * 1000) / htotal;
1573                refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1574        } else if(ivideo->current_refresh_rate) {
1575                refresh_rate = ivideo->current_refresh_rate;
1576                recalc_clock = true;
1577        } else {
1578                refresh_rate = 60;
1579                recalc_clock = true;
1580        }
1581
1582        myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1583
1584        /* Eventually recalculate timing and clock */
1585        if(recalc_clock) {
1586                if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1587                var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1588                                                sisbios_mode[search_idx].mode_no[ivideo->mni],
1589                                                myrateindex));
1590                sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1591                                        sisbios_mode[search_idx].mode_no[ivideo->mni],
1592                                        myrateindex, var);
1593                if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1594                        var->pixclock <<= 1;
1595                }
1596        }
1597
1598        if(ivideo->sisfb_thismonitor.datavalid) {
1599                if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1600                                myrateindex, refresh_rate)) {
1601                        printk(KERN_INFO
1602                                "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1603                }
1604        }
1605
1606        /* Adapt RGB settings */
1607        sisfb_bpp_to_var(ivideo, var);
1608
1609        if(var->xres > var->xres_virtual)
1610                var->xres_virtual = var->xres;
1611
1612        if(ivideo->sisfb_ypan) {
1613                maxyres = sisfb_calc_maxyres(ivideo, var);
1614                if(ivideo->sisfb_max) {
1615                        var->yres_virtual = maxyres;
1616                } else {
1617                        if(var->yres_virtual > maxyres) {
1618                                var->yres_virtual = maxyres;
1619                        }
1620                }
1621                if(var->yres_virtual <= var->yres) {
1622                        var->yres_virtual = var->yres;
1623                }
1624        } else {
1625                if(var->yres != var->yres_virtual) {
1626                        var->yres_virtual = var->yres;
1627                }
1628                var->xoffset = 0;
1629                var->yoffset = 0;
1630        }
1631
1632        /* Truncate offsets to maximum if too high */
1633        if(var->xoffset > var->xres_virtual - var->xres) {
1634                var->xoffset = var->xres_virtual - var->xres - 1;
1635        }
1636
1637        if(var->yoffset > var->yres_virtual - var->yres) {
1638                var->yoffset = var->yres_virtual - var->yres - 1;
1639        }
1640
1641        /* Set everything else to 0 */
1642        var->red.msb_right =
1643                var->green.msb_right =
1644                var->blue.msb_right =
1645                var->transp.offset =
1646                var->transp.length =
1647                var->transp.msb_right = 0;
1648
1649        return 0;
1650}
1651
1652static int
1653sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1654{
1655        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1656        int err;
1657
1658        if (var->vmode & FB_VMODE_YWRAP)
1659                return -EINVAL;
1660
1661        if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1662            var->yoffset + info->var.yres > info->var.yres_virtual)
1663                return -EINVAL;
1664
1665        err = sisfb_pan_var(ivideo, info, var);
1666        if (err < 0)
1667                return err;
1668
1669        info->var.xoffset = var->xoffset;
1670        info->var.yoffset = var->yoffset;
1671
1672        return 0;
1673}
1674
1675static int
1676sisfb_blank(int blank, struct fb_info *info)
1677{
1678        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1679
1680        return sisfb_myblank(ivideo, blank);
1681}
1682
1683/* ----------- FBDev related routines for all series ---------- */
1684
1685static int      sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1686                            unsigned long arg)
1687{
1688        struct sis_video_info   *ivideo = (struct sis_video_info *)info->par;
1689        struct sis_memreq       sismemreq;
1690        struct fb_vblank        sisvbblank;
1691        u32                     gpu32 = 0;
1692#ifndef __user
1693#define __user
1694#endif
1695        u32 __user              *argp = (u32 __user *)arg;
1696
1697        switch(cmd) {
1698           case FBIO_ALLOC:
1699                if(!capable(CAP_SYS_RAWIO))
1700                        return -EPERM;
1701
1702                if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1703                        return -EFAULT;
1704
1705                sis_malloc(&sismemreq);
1706
1707                if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1708                        sis_free((u32)sismemreq.offset);
1709                        return -EFAULT;
1710                }
1711                break;
1712
1713           case FBIO_FREE:
1714                if(!capable(CAP_SYS_RAWIO))
1715                        return -EPERM;
1716
1717                if(get_user(gpu32, argp))
1718                        return -EFAULT;
1719
1720                sis_free(gpu32);
1721                break;
1722
1723           case FBIOGET_VBLANK:
1724
1725                memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1726
1727                sisvbblank.count = 0;
1728                sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1729
1730                if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1731                        return -EFAULT;
1732
1733                break;
1734
1735           case SISFB_GET_INFO_SIZE:
1736                return put_user(sizeof(struct sisfb_info), argp);
1737
1738           case SISFB_GET_INFO_OLD:
1739                if(ivideo->warncount++ < 10)
1740                        printk(KERN_INFO
1741                                "sisfb: Deprecated ioctl call received - update your application!\n");
1742                /* fall through */
1743           case SISFB_GET_INFO:  /* For communication with X driver */
1744                ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
1745                ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
1746                ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
1747                ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1748                ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1749                ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1750                ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1751                ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1752                if(ivideo->modechanged) {
1753                        ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1754                } else {
1755                        ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1756                }
1757                ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1758                ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1759                ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1760                ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1761                ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1762                ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1763                ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1764                ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1765                ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1766                ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1767                ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1768                ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1769                ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1770                ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1771                ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1772                ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1773                ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1774                ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1775                ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1776                ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1777                ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1778                ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1779                ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1780                ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1781                ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1782                ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1783                ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1784                ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1785
1786                if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1787                                                sizeof(ivideo->sisfb_infoblock)))
1788                        return -EFAULT;
1789
1790                break;
1791
1792           case SISFB_GET_VBRSTATUS_OLD:
1793                if(ivideo->warncount++ < 10)
1794                        printk(KERN_INFO
1795                                "sisfb: Deprecated ioctl call received - update your application!\n");
1796                /* fall through */
1797           case SISFB_GET_VBRSTATUS:
1798                if(sisfb_CheckVBRetrace(ivideo))
1799                        return put_user((u32)1, argp);
1800                else
1801                        return put_user((u32)0, argp);
1802
1803           case SISFB_GET_AUTOMAXIMIZE_OLD:
1804                if(ivideo->warncount++ < 10)
1805                        printk(KERN_INFO
1806                                "sisfb: Deprecated ioctl call received - update your application!\n");
1807                /* fall through */
1808           case SISFB_GET_AUTOMAXIMIZE:
1809                if(ivideo->sisfb_max)
1810                        return put_user((u32)1, argp);
1811                else
1812                        return put_user((u32)0, argp);
1813
1814           case SISFB_SET_AUTOMAXIMIZE_OLD:
1815                if(ivideo->warncount++ < 10)
1816                        printk(KERN_INFO
1817                                "sisfb: Deprecated ioctl call received - update your application!\n");
1818                /* fall through */
1819           case SISFB_SET_AUTOMAXIMIZE:
1820                if(get_user(gpu32, argp))
1821                        return -EFAULT;
1822
1823                ivideo->sisfb_max = (gpu32) ? 1 : 0;
1824                break;
1825
1826           case SISFB_SET_TVPOSOFFSET:
1827                if(get_user(gpu32, argp))
1828                        return -EFAULT;
1829
1830                sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1831                sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1832                break;
1833
1834           case SISFB_GET_TVPOSOFFSET:
1835                return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1836                                                        argp);
1837
1838           case SISFB_COMMAND:
1839                if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1840                                                        sizeof(struct sisfb_cmd)))
1841                        return -EFAULT;
1842
1843                sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1844
1845                if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1846                                                        sizeof(struct sisfb_cmd)))
1847                        return -EFAULT;
1848
1849                break;
1850
1851           case SISFB_SET_LOCK:
1852                if(get_user(gpu32, argp))
1853                        return -EFAULT;
1854
1855                ivideo->sisfblocked = (gpu32) ? 1 : 0;
1856                break;
1857
1858           default:
1859#ifdef SIS_NEW_CONFIG_COMPAT
1860                return -ENOIOCTLCMD;
1861#else
1862                return -EINVAL;
1863#endif
1864        }
1865        return 0;
1866}
1867
1868static int
1869sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1870{
1871        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1872
1873        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1874
1875        strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1876
1877        mutex_lock(&info->mm_lock);
1878        fix->smem_start  = ivideo->video_base + ivideo->video_offset;
1879        fix->smem_len    = ivideo->sisfb_mem;
1880        mutex_unlock(&info->mm_lock);
1881        fix->type        = FB_TYPE_PACKED_PIXELS;
1882        fix->type_aux    = 0;
1883        fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1884        fix->xpanstep    = 1;
1885        fix->ypanstep    = (ivideo->sisfb_ypan) ? 1 : 0;
1886        fix->ywrapstep   = 0;
1887        fix->line_length = ivideo->video_linelength;
1888        fix->mmio_start  = ivideo->mmio_base;
1889        fix->mmio_len    = ivideo->mmio_size;
1890        if(ivideo->sisvga_engine == SIS_300_VGA) {
1891                fix->accel = FB_ACCEL_SIS_GLAMOUR;
1892        } else if((ivideo->chip == SIS_330) ||
1893                  (ivideo->chip == SIS_760) ||
1894                  (ivideo->chip == SIS_761)) {
1895                fix->accel = FB_ACCEL_SIS_XABRE;
1896        } else if(ivideo->chip == XGI_20) {
1897                fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1898        } else if(ivideo->chip >= XGI_40) {
1899                fix->accel = FB_ACCEL_XGI_VOLARI_V;
1900        } else {
1901                fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1902        }
1903
1904        return 0;
1905}
1906
1907/* ----------------  fb_ops structures ----------------- */
1908
1909static struct fb_ops sisfb_ops = {
1910        .owner          = THIS_MODULE,
1911        .fb_open        = sisfb_open,
1912        .fb_release     = sisfb_release,
1913        .fb_check_var   = sisfb_check_var,
1914        .fb_set_par     = sisfb_set_par,
1915        .fb_setcolreg   = sisfb_setcolreg,
1916        .fb_pan_display = sisfb_pan_display,
1917        .fb_blank       = sisfb_blank,
1918        .fb_fillrect    = fbcon_sis_fillrect,
1919        .fb_copyarea    = fbcon_sis_copyarea,
1920        .fb_imageblit   = cfb_imageblit,
1921        .fb_sync        = fbcon_sis_sync,
1922#ifdef SIS_NEW_CONFIG_COMPAT
1923        .fb_compat_ioctl= sisfb_ioctl,
1924#endif
1925        .fb_ioctl       = sisfb_ioctl
1926};
1927
1928/* ---------------- Chip generation dependent routines ---------------- */
1929
1930static struct pci_dev *sisfb_get_northbridge(int basechipid)
1931{
1932        struct pci_dev *pdev = NULL;
1933        int nbridgenum, nbridgeidx, i;
1934        static const unsigned short nbridgeids[] = {
1935                PCI_DEVICE_ID_SI_540,   /* for SiS 540 VGA */
1936                PCI_DEVICE_ID_SI_630,   /* for SiS 630/730 VGA */
1937                PCI_DEVICE_ID_SI_730,
1938                PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
1939                PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
1940                PCI_DEVICE_ID_SI_651,
1941                PCI_DEVICE_ID_SI_740,
1942                PCI_DEVICE_ID_SI_661,   /* for SiS 661/741/660/760/761 VGA */
1943                PCI_DEVICE_ID_SI_741,
1944                PCI_DEVICE_ID_SI_660,
1945                PCI_DEVICE_ID_SI_760,
1946                PCI_DEVICE_ID_SI_761
1947        };
1948
1949        switch(basechipid) {
1950#ifdef CONFIG_FB_SIS_300
1951        case SIS_540:   nbridgeidx = 0; nbridgenum = 1; break;
1952        case SIS_630:   nbridgeidx = 1; nbridgenum = 2; break;
1953#endif
1954#ifdef CONFIG_FB_SIS_315
1955        case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
1956        case SIS_650:   nbridgeidx = 4; nbridgenum = 3; break;
1957        case SIS_660:   nbridgeidx = 7; nbridgenum = 5; break;
1958#endif
1959        default:        return NULL;
1960        }
1961        for(i = 0; i < nbridgenum; i++) {
1962                if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1963                                nbridgeids[nbridgeidx+i], NULL)))
1964                        break;
1965        }
1966        return pdev;
1967}
1968
1969static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1970{
1971#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1972        u8 reg;
1973#endif
1974
1975        ivideo->video_size = 0;
1976        ivideo->UMAsize = ivideo->LFBsize = 0;
1977
1978        switch(ivideo->chip) {
1979#ifdef CONFIG_FB_SIS_300
1980        case SIS_300:
1981                reg = SiS_GetReg(SISSR, 0x14);
1982                ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1983                break;
1984        case SIS_540:
1985        case SIS_630:
1986        case SIS_730:
1987                if(!ivideo->nbridge)
1988                        return -1;
1989                pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
1990                ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1991                break;
1992#endif
1993#ifdef CONFIG_FB_SIS_315
1994        case SIS_315H:
1995        case SIS_315PRO:
1996        case SIS_315:
1997                reg = SiS_GetReg(SISSR, 0x14);
1998                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1999                switch((reg >> 2) & 0x03) {
2000                case 0x01:
2001                case 0x03:
2002                        ivideo->video_size <<= 1;
2003                        break;
2004                case 0x02:
2005                        ivideo->video_size += (ivideo->video_size/2);
2006                }
2007                break;
2008        case SIS_330:
2009                reg = SiS_GetReg(SISSR, 0x14);
2010                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2011                if(reg & 0x0c) ivideo->video_size <<= 1;
2012                break;
2013        case SIS_550:
2014        case SIS_650:
2015        case SIS_740:
2016                reg = SiS_GetReg(SISSR, 0x14);
2017                ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2018                break;
2019        case SIS_661:
2020        case SIS_741:
2021                reg = SiS_GetReg(SISCR, 0x79);
2022                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2023                break;
2024        case SIS_660:
2025        case SIS_760:
2026        case SIS_761:
2027                reg = SiS_GetReg(SISCR, 0x79);
2028                reg = (reg & 0xf0) >> 4;
2029                if(reg) {
2030                        ivideo->video_size = (1 << reg) << 20;
2031                        ivideo->UMAsize = ivideo->video_size;
2032                }
2033                reg = SiS_GetReg(SISCR, 0x78);
2034                reg &= 0x30;
2035                if(reg) {
2036                        if(reg == 0x10) {
2037                                ivideo->LFBsize = (32 << 20);
2038                        } else {
2039                                ivideo->LFBsize = (64 << 20);
2040                        }
2041                        ivideo->video_size += ivideo->LFBsize;
2042                }
2043                break;
2044        case SIS_340:
2045        case XGI_20:
2046        case XGI_40:
2047                reg = SiS_GetReg(SISSR, 0x14);
2048                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2049                if(ivideo->chip != XGI_20) {
2050                        reg = (reg & 0x0c) >> 2;
2051                        if(ivideo->revision_id == 2) {
2052                                if(reg & 0x01) reg = 0x02;
2053                                else           reg = 0x00;
2054                        }
2055                        if(reg == 0x02)         ivideo->video_size <<= 1;
2056                        else if(reg == 0x03)    ivideo->video_size <<= 2;
2057                }
2058                break;
2059#endif
2060        default:
2061                return -1;
2062        }
2063        return 0;
2064}
2065
2066/* -------------- video bridge device detection --------------- */
2067
2068static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2069{
2070        u8 cr32, temp;
2071
2072        /* No CRT2 on XGI Z7 */
2073        if(ivideo->chip == XGI_20) {
2074                ivideo->sisfb_crt1off = 0;
2075                return;
2076        }
2077
2078#ifdef CONFIG_FB_SIS_300
2079        if(ivideo->sisvga_engine == SIS_300_VGA) {
2080                temp = SiS_GetReg(SISSR, 0x17);
2081                if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2082                        /* PAL/NTSC is stored on SR16 on such machines */
2083                        if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2084                                temp = SiS_GetReg(SISSR, 0x16);
2085                                if(temp & 0x20)
2086                                        ivideo->vbflags |= TV_PAL;
2087                                else
2088                                        ivideo->vbflags |= TV_NTSC;
2089                        }
2090                }
2091        }
2092#endif
2093
2094        cr32 = SiS_GetReg(SISCR, 0x32);
2095
2096        if(cr32 & SIS_CRT1) {
2097                ivideo->sisfb_crt1off = 0;
2098        } else {
2099                ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2100        }
2101
2102        ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2103
2104        if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
2105        if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
2106        if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2107
2108        /* Check given parms for hardware compatibility.
2109         * (Cannot do this in the search_xx routines since we don't
2110         * know what hardware we are running on then)
2111         */
2112
2113        if(ivideo->chip != SIS_550) {
2114           ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2115        }
2116
2117        if(ivideo->sisfb_tvplug != -1) {
2118           if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2119               (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2120              if(ivideo->sisfb_tvplug & TV_YPBPR) {
2121                 ivideo->sisfb_tvplug = -1;
2122                 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2123              }
2124           }
2125        }
2126        if(ivideo->sisfb_tvplug != -1) {
2127           if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2128               (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2129              if(ivideo->sisfb_tvplug & TV_HIVISION) {
2130                 ivideo->sisfb_tvplug = -1;
2131                 printk(KERN_ERR "sisfb: HiVision not supported\n");
2132              }
2133           }
2134        }
2135        if(ivideo->sisfb_tvstd != -1) {
2136           if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2137               (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2138                        (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2139              if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2140                 ivideo->sisfb_tvstd = -1;
2141                 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2142              }
2143           }
2144        }
2145
2146        /* Detect/set TV plug & type */
2147        if(ivideo->sisfb_tvplug != -1) {
2148                ivideo->vbflags |= ivideo->sisfb_tvplug;
2149        } else {
2150                if(cr32 & SIS_VB_YPBPR)          ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2151                else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
2152                else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
2153                else {
2154                        if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
2155                        if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2156                }
2157        }
2158
2159        if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2160            if(ivideo->sisfb_tvstd != -1) {
2161               ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2162               ivideo->vbflags |= ivideo->sisfb_tvstd;
2163            }
2164            if(ivideo->vbflags & TV_SCART) {
2165               ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2166               ivideo->vbflags |= TV_PAL;
2167            }
2168            if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2169                if(ivideo->sisvga_engine == SIS_300_VGA) {
2170                        temp = SiS_GetReg(SISSR, 0x38);
2171                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2172                        else            ivideo->vbflags |= TV_NTSC;
2173                } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2174                        temp = SiS_GetReg(SISSR, 0x38);
2175                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2176                        else            ivideo->vbflags |= TV_NTSC;
2177                } else {
2178                        temp = SiS_GetReg(SISCR, 0x79);
2179                        if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2180                        else            ivideo->vbflags |= TV_NTSC;
2181                }
2182            }
2183        }
2184
2185        /* Copy forceCRT1 option to CRT1off if option is given */
2186        if(ivideo->sisfb_forcecrt1 != -1) {
2187           ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2188        }
2189}
2190
2191/* ------------------ Sensing routines ------------------ */
2192
2193static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2194{
2195    unsigned short old;
2196    int count = 48;
2197
2198    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2199    do {
2200        if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2201    } while(count--);
2202    return (count != -1);
2203}
2204
2205static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2206{
2207    bool mustwait = false;
2208    u8  sr1F, cr17;
2209#ifdef CONFIG_FB_SIS_315
2210    u8  cr63=0;
2211#endif
2212    u16 temp = 0xffff;
2213    int i;
2214
2215    sr1F = SiS_GetReg(SISSR, 0x1F);
2216    SiS_SetRegOR(SISSR, 0x1F, 0x04);
2217    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2218    if(sr1F & 0xc0) mustwait = true;
2219
2220#ifdef CONFIG_FB_SIS_315
2221    if(ivideo->sisvga_engine == SIS_315_VGA) {
2222       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2223       cr63 &= 0x40;
2224       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2225    }
2226#endif
2227
2228    cr17 = SiS_GetReg(SISCR, 0x17);
2229    cr17 &= 0x80;
2230    if(!cr17) {
2231       SiS_SetRegOR(SISCR, 0x17, 0x80);
2232       mustwait = true;
2233       SiS_SetReg(SISSR, 0x00, 0x01);
2234       SiS_SetReg(SISSR, 0x00, 0x03);
2235    }
2236
2237    if(mustwait) {
2238       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2239    }
2240
2241#ifdef CONFIG_FB_SIS_315
2242    if(ivideo->chip >= SIS_330) {
2243       SiS_SetRegAND(SISCR, 0x32, ~0x20);
2244       if(ivideo->chip >= SIS_340) {
2245           SiS_SetReg(SISCR, 0x57, 0x4a);
2246       } else {
2247           SiS_SetReg(SISCR, 0x57, 0x5f);
2248       }
2249        SiS_SetRegOR(SISCR, 0x53, 0x02);
2250        while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
2251        while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2252        if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2253        SiS_SetRegAND(SISCR, 0x53, 0xfd);
2254        SiS_SetRegAND(SISCR, 0x57, 0x00);
2255    }
2256#endif
2257
2258    if(temp == 0xffff) {
2259       i = 3;
2260       do {
2261          temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2262                ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2263       } while(((temp == 0) || (temp == 0xffff)) && i--);
2264
2265       if((temp == 0) || (temp == 0xffff)) {
2266          if(sisfb_test_DDC1(ivideo)) temp = 1;
2267       }
2268    }
2269
2270    if((temp) && (temp != 0xffff)) {
2271       SiS_SetRegOR(SISCR, 0x32, 0x20);
2272    }
2273
2274#ifdef CONFIG_FB_SIS_315
2275    if(ivideo->sisvga_engine == SIS_315_VGA) {
2276        SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2277    }
2278#endif
2279
2280    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2281
2282    SiS_SetReg(SISSR, 0x1F, sr1F);
2283}
2284
2285/* Determine and detect attached devices on SiS30x */
2286static void SiS_SenseLCD(struct sis_video_info *ivideo)
2287{
2288        unsigned char buffer[256];
2289        unsigned short temp, realcrtno, i;
2290        u8 reg, cr37 = 0, paneltype = 0;
2291        u16 xres, yres;
2292
2293        ivideo->SiS_Pr.PanelSelfDetected = false;
2294
2295        /* LCD detection only for TMDS bridges */
2296        if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2297                return;
2298        if(ivideo->vbflags2 & VB2_30xBDH)
2299                return;
2300
2301        /* If LCD already set up by BIOS, skip it */
2302        reg = SiS_GetReg(SISCR, 0x32);
2303        if(reg & 0x08)
2304                return;
2305
2306        realcrtno = 1;
2307        if(ivideo->SiS_Pr.DDCPortMixup)
2308                realcrtno = 0;
2309
2310        /* Check DDC capabilities */
2311        temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2312                                realcrtno, 0, &buffer[0], ivideo->vbflags2);
2313
2314        if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2315                return;
2316
2317        /* Read DDC data */
2318        i = 3;  /* Number of retrys */
2319        do {
2320                temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2321                                ivideo->sisvga_engine, realcrtno, 1,
2322                                &buffer[0], ivideo->vbflags2);
2323        } while((temp) && i--);
2324
2325        if(temp)
2326                return;
2327
2328        /* No digital device */
2329        if(!(buffer[0x14] & 0x80))
2330                return;
2331
2332        /* First detailed timing preferred timing? */
2333        if(!(buffer[0x18] & 0x02))
2334                return;
2335
2336        xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2337        yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2338
2339        switch(xres) {
2340                case 1024:
2341                        if(yres == 768)
2342                                paneltype = 0x02;
2343                        break;
2344                case 1280:
2345                        if(yres == 1024)
2346                                paneltype = 0x03;
2347                        break;
2348                case 1600:
2349                        if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2350                                paneltype = 0x0b;
2351                        break;
2352        }
2353
2354        if(!paneltype)
2355                return;
2356
2357        if(buffer[0x23])
2358                cr37 |= 0x10;
2359
2360        if((buffer[0x47] & 0x18) == 0x18)
2361                cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2362        else
2363                cr37 |= 0xc0;
2364
2365        SiS_SetReg(SISCR, 0x36, paneltype);
2366        cr37 &= 0xf1;
2367        SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2368        SiS_SetRegOR(SISCR, 0x32, 0x08);
2369
2370        ivideo->SiS_Pr.PanelSelfDetected = true;
2371}
2372
2373static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2374{
2375    int temp, mytest, result, i, j;
2376
2377    for(j = 0; j < 10; j++) {
2378       result = 0;
2379       for(i = 0; i < 3; i++) {
2380          mytest = test;
2381           SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2382          temp = (type >> 8) | (mytest & 0x00ff);
2383          SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2384          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2385          mytest >>= 8;
2386          mytest &= 0x7f;
2387           temp = SiS_GetReg(SISPART4, 0x03);
2388          temp ^= 0x0e;
2389          temp &= mytest;
2390          if(temp == mytest) result++;
2391#if 1
2392          SiS_SetReg(SISPART4, 0x11, 0x00);
2393          SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2394          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2395#endif
2396       }
2397       if((result == 0) || (result >= 2)) break;
2398    }
2399    return result;
2400}
2401
2402static void SiS_Sense30x(struct sis_video_info *ivideo)
2403{
2404    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2405    u16 svhs=0, svhs_c=0;
2406    u16 cvbs=0, cvbs_c=0;
2407    u16 vga2=0, vga2_c=0;
2408    int myflag, result;
2409    char stdstr[] = "sisfb: Detected";
2410    char tvstr[]  = "TV connected to";
2411
2412    if(ivideo->vbflags2 & VB2_301) {
2413       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2414       myflag = SiS_GetReg(SISPART4, 0x01);
2415       if(myflag & 0x04) {
2416          svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2417       }
2418    } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2419       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2420    } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2421       svhs = 0x0200; cvbs = 0x0100;
2422    } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2423       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2424    } else
2425       return;
2426
2427    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2428    if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2429       svhs_c = 0x0408; cvbs_c = 0x0808;
2430    }
2431
2432    biosflag = 2;
2433    if(ivideo->haveXGIROM) {
2434       biosflag = ivideo->bios_abase[0x58] & 0x03;
2435    } else if(ivideo->newrom) {
2436       if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2437    } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2438       if(ivideo->bios_abase) {
2439          biosflag = ivideo->bios_abase[0xfe] & 0x03;
2440       }
2441    }
2442
2443    if(ivideo->chip == SIS_300) {
2444       myflag = SiS_GetReg(SISSR, 0x3b);
2445       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2446    }
2447
2448    if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2449       vga2 = vga2_c = 0;
2450    }
2451
2452    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2453    SiS_SetRegOR(SISSR, 0x1e, 0x20);
2454
2455    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2456    if(ivideo->vbflags2 & VB2_30xC) {
2457        SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2458    } else {
2459       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2460    }
2461    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2462
2463    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2464    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2465
2466    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2467    if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2468        SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2469    }
2470
2471    if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2472       SISDoSense(ivideo, 0, 0);
2473    }
2474
2475    SiS_SetRegAND(SISCR, 0x32, ~0x14);
2476
2477    if(vga2_c || vga2) {
2478       if(SISDoSense(ivideo, vga2, vga2_c)) {
2479          if(biosflag & 0x01) {
2480             printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2481             SiS_SetRegOR(SISCR, 0x32, 0x04);
2482          } else {
2483             printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2484             SiS_SetRegOR(SISCR, 0x32, 0x10);
2485          }
2486       }
2487    }
2488
2489    SiS_SetRegAND(SISCR, 0x32, 0x3f);
2490
2491    if(ivideo->vbflags2 & VB2_30xCLV) {
2492       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2493    }
2494
2495    if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2496       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2497       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2498       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2499          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2500             printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2501             SiS_SetRegOR(SISCR, 0x32, 0x80);
2502          }
2503       }
2504       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2505    }
2506
2507    SiS_SetRegAND(SISCR, 0x32, ~0x03);
2508
2509    if(!(ivideo->vbflags & TV_YPBPR)) {
2510       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2511          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2512           SiS_SetRegOR(SISCR, 0x32, 0x02);
2513       }
2514       if((biosflag & 0x02) || (!result)) {
2515          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2516             printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2517             SiS_SetRegOR(SISCR, 0x32, 0x01);
2518          }
2519       }
2520    }
2521
2522    SISDoSense(ivideo, 0, 0);
2523
2524    SiS_SetReg(SISPART2, 0x00, backupP2_00);
2525    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2526    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2527
2528    if(ivideo->vbflags2 & VB2_30xCLV) {
2529        biosflag = SiS_GetReg(SISPART2, 0x00);
2530       if(biosflag & 0x20) {
2531          for(myflag = 2; myflag > 0; myflag--) {
2532             biosflag ^= 0x20;
2533             SiS_SetReg(SISPART2, 0x00, biosflag);
2534          }
2535       }
2536    }
2537
2538    SiS_SetReg(SISPART2, 0x00, backupP2_00);
2539}
2540
2541/* Determine and detect attached TV's on Chrontel */
2542static void SiS_SenseCh(struct sis_video_info *ivideo)
2543{
2544#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2545    u8 temp1, temp2;
2546    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2547#endif
2548#ifdef CONFIG_FB_SIS_300
2549    unsigned char test[3];
2550    int i;
2551#endif
2552
2553    if(ivideo->chip < SIS_315H) {
2554
2555#ifdef CONFIG_FB_SIS_300
2556       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;            /* Chrontel 700x */
2557       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);      /* Set general purpose IO for Chrontel communication */
2558       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2559       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2560       /* See Chrontel TB31 for explanation */
2561       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2562       if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2563          SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2564          SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2565       }
2566       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2567       if(temp2 != temp1) temp1 = temp2;
2568
2569       if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2570           /* Read power status */
2571           temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2572           if((temp1 & 0x03) != 0x03) {
2573                /* Power all outputs */
2574                SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2575                SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2576           }
2577           /* Sense connected TV devices */
2578           for(i = 0; i < 3; i++) {
2579               SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2580               SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2581               SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2582               SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2583               temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2584               if(!(temp1 & 0x08))       test[i] = 0x02;
2585               else if(!(temp1 & 0x02))  test[i] = 0x01;
2586               else                      test[i] = 0;
2587               SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2588           }
2589
2590           if(test[0] == test[1])      temp1 = test[0];
2591           else if(test[0] == test[2]) temp1 = test[0];
2592           else if(test[1] == test[2]) temp1 = test[1];
2593           else {
2594                printk(KERN_INFO
2595                        "sisfb: TV detection unreliable - test results varied\n");
2596                temp1 = test[2];
2597           }
2598           if(temp1 == 0x02) {
2599                printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2600                ivideo->vbflags |= TV_SVIDEO;
2601                SiS_SetRegOR(SISCR, 0x32, 0x02);
2602                SiS_SetRegAND(SISCR, 0x32, ~0x05);
2603           } else if (temp1 == 0x01) {
2604                printk(KERN_INFO "%s CVBS output\n", stdstr);
2605                ivideo->vbflags |= TV_AVIDEO;
2606                SiS_SetRegOR(SISCR, 0x32, 0x01);
2607                SiS_SetRegAND(SISCR, 0x32, ~0x06);
2608           } else {
2609                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2610                SiS_SetRegAND(SISCR, 0x32, ~0x07);
2611           }
2612       } else if(temp1 == 0) {
2613          SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2614          SiS_SetRegAND(SISCR, 0x32, ~0x07);
2615       }
2616       /* Set general purpose IO for Chrontel communication */
2617       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2618#endif
2619
2620    } else {
2621
2622#ifdef CONFIG_FB_SIS_315
2623        ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;           /* Chrontel 7019 */
2624        temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2625        SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2626        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2627        temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2628        temp2 |= 0x01;
2629        SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2630        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2631        temp2 ^= 0x01;
2632        SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2633        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2634        temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2635        SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2636        temp1 = 0;
2637        if(temp2 & 0x02) temp1 |= 0x01;
2638        if(temp2 & 0x10) temp1 |= 0x01;
2639        if(temp2 & 0x04) temp1 |= 0x02;
2640        if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2641        switch(temp1) {
2642        case 0x01:
2643             printk(KERN_INFO "%s CVBS output\n", stdstr);
2644             ivideo->vbflags |= TV_AVIDEO;
2645             SiS_SetRegOR(SISCR, 0x32, 0x01);
2646             SiS_SetRegAND(SISCR, 0x32, ~0x06);
2647             break;
2648        case 0x02:
2649             printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2650             ivideo->vbflags |= TV_SVIDEO;
2651             SiS_SetRegOR(SISCR, 0x32, 0x02);
2652             SiS_SetRegAND(SISCR, 0x32, ~0x05);
2653             break;
2654        case 0x04:
2655             printk(KERN_INFO "%s SCART output\n", stdstr);
2656             SiS_SetRegOR(SISCR, 0x32, 0x04);
2657             SiS_SetRegAND(SISCR, 0x32, ~0x03);
2658             break;
2659        default:
2660             SiS_SetRegAND(SISCR, 0x32, ~0x07);
2661        }
2662#endif
2663    }
2664}
2665
2666static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2667{
2668        char stdstr[]    = "sisfb: Detected";
2669        char bridgestr[] = "video bridge";
2670        u8 vb_chipid;
2671        u8 reg;
2672
2673        /* No CRT2 on XGI Z7 */
2674        if(ivideo->chip == XGI_20)
2675                return;
2676
2677        vb_chipid = SiS_GetReg(SISPART4, 0x00);
2678        switch(vb_chipid) {
2679        case 0x01:
2680                reg = SiS_GetReg(SISPART4, 0x01);
2681                if(reg < 0xb0) {
2682                        ivideo->vbflags |= VB_301;      /* Deprecated */
2683                        ivideo->vbflags2 |= VB2_301;
2684                        printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2685                } else if(reg < 0xc0) {
2686                        ivideo->vbflags |= VB_301B;     /* Deprecated */
2687                        ivideo->vbflags2 |= VB2_301B;
2688                        reg = SiS_GetReg(SISPART4, 0x23);
2689                        if(!(reg & 0x02)) {
2690                           ivideo->vbflags |= VB_30xBDH;        /* Deprecated */
2691                           ivideo->vbflags2 |= VB2_30xBDH;
2692                           printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2693                        } else {
2694                           printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2695                        }
2696                } else if(reg < 0xd0) {
2697                        ivideo->vbflags |= VB_301C;     /* Deprecated */
2698                        ivideo->vbflags2 |= VB2_301C;
2699                        printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2700                } else if(reg < 0xe0) {
2701                        ivideo->vbflags |= VB_301LV;    /* Deprecated */
2702                        ivideo->vbflags2 |= VB2_301LV;
2703                        printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2704                } else if(reg <= 0xe1) {
2705                        reg = SiS_GetReg(SISPART4, 0x39);
2706                        if(reg == 0xff) {
2707                           ivideo->vbflags |= VB_302LV; /* Deprecated */
2708                           ivideo->vbflags2 |= VB2_302LV;
2709                           printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2710                        } else {
2711                           ivideo->vbflags |= VB_301C;  /* Deprecated */
2712                           ivideo->vbflags2 |= VB2_301C;
2713                           printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2714#if 0
2715                           ivideo->vbflags |= VB_302ELV;        /* Deprecated */
2716                           ivideo->vbflags2 |= VB2_302ELV;
2717                           printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2718#endif
2719                        }
2720                }
2721                break;
2722        case 0x02:
2723                ivideo->vbflags |= VB_302B;     /* Deprecated */
2724                ivideo->vbflags2 |= VB2_302B;
2725                printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2726                break;
2727        }
2728
2729        if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2730                reg = SiS_GetReg(SISCR, 0x37);
2731                reg &= SIS_EXTERNAL_CHIP_MASK;
2732                reg >>= 1;
2733                if(ivideo->sisvga_engine == SIS_300_VGA) {
2734#ifdef CONFIG_FB_SIS_300
2735                        switch(reg) {
2736                           case SIS_EXTERNAL_CHIP_LVDS:
2737                                ivideo->vbflags |= VB_LVDS;     /* Deprecated */
2738                                ivideo->vbflags2 |= VB2_LVDS;
2739                                break;
2740                           case SIS_EXTERNAL_CHIP_TRUMPION:
2741                                ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);     /* Deprecated */
2742                                ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2743                                break;
2744                           case SIS_EXTERNAL_CHIP_CHRONTEL:
2745                                ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2746                                ivideo->vbflags2 |= VB2_CHRONTEL;
2747                                break;
2748                           case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2749                                ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
2750                                ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2751                                break;
2752                        }
2753                        if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2754#endif
2755                } else if(ivideo->chip < SIS_661) {
2756#ifdef CONFIG_FB_SIS_315
2757                        switch (reg) {
2758                           case SIS310_EXTERNAL_CHIP_LVDS:
2759                                ivideo->vbflags |= VB_LVDS;     /* Deprecated */
2760                                ivideo->vbflags2 |= VB2_LVDS;
2761                                break;
2762                           case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2763                                ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
2764                                ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2765                                break;
2766                        }
2767                        if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2768#endif
2769                } else if(ivideo->chip >= SIS_661) {
2770#ifdef CONFIG_FB_SIS_315
2771                        reg = SiS_GetReg(SISCR, 0x38);
2772                        reg >>= 5;
2773                        switch(reg) {
2774                           case 0x02:
2775                                ivideo->vbflags |= VB_LVDS;     /* Deprecated */
2776                                ivideo->vbflags2 |= VB2_LVDS;
2777                                break;
2778                           case 0x03:
2779                                ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
2780                                ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2781                                break;
2782                           case 0x04:
2783                                ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);     /* Deprecated */
2784                                ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2785                                break;
2786                        }
2787                        if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2788#endif
2789                }
2790                if(ivideo->vbflags2 & VB2_LVDS) {
2791                   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2792                }
2793                if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2794                   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2795                }
2796                if(ivideo->vbflags2 & VB2_CHRONTEL) {
2797                   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2798                }
2799                if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2800                   printk(KERN_INFO "%s Conexant external device\n", stdstr);
2801                }
2802        }
2803
2804        if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2805                SiS_SenseLCD(ivideo);
2806                SiS_Sense30x(ivideo);
2807        } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2808                SiS_SenseCh(ivideo);
2809        }
2810}
2811
2812/* ---------- Engine initialization routines ------------ */
2813
2814static void
2815sisfb_engine_init(struct sis_video_info *ivideo)
2816{
2817
2818        /* Initialize command queue (we use MMIO only) */
2819
2820        /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2821
2822        ivideo->caps &= ~(TURBO_QUEUE_CAP    |
2823                          MMIO_CMD_QUEUE_CAP |
2824                          VM_CMD_QUEUE_CAP   |
2825                          AGP_CMD_QUEUE_CAP);
2826
2827#ifdef CONFIG_FB_SIS_300
2828        if(ivideo->sisvga_engine == SIS_300_VGA) {
2829                u32 tqueue_pos;
2830                u8 tq_state;
2831
2832                tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2833
2834                tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2835                tq_state |= 0xf0;
2836                tq_state &= 0xfc;
2837                tq_state |= (u8)(tqueue_pos >> 8);
2838                SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2839
2840                SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2841
2842                ivideo->caps |= TURBO_QUEUE_CAP;
2843        }
2844#endif
2845
2846#ifdef CONFIG_FB_SIS_315
2847        if(ivideo->sisvga_engine == SIS_315_VGA) {
2848                u32 tempq = 0, templ;
2849                u8  temp;
2850
2851                if(ivideo->chip == XGI_20) {
2852                        switch(ivideo->cmdQueueSize) {
2853                        case (64 * 1024):
2854                                temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2855                                break;
2856                        case (128 * 1024):
2857                        default:
2858                                temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2859                        }
2860                } else {
2861                        switch(ivideo->cmdQueueSize) {
2862                        case (4 * 1024 * 1024):
2863                                temp = SIS_CMD_QUEUE_SIZE_4M;
2864                                break;
2865                        case (2 * 1024 * 1024):
2866                                temp = SIS_CMD_QUEUE_SIZE_2M;
2867                                break;
2868                        case (1 * 1024 * 1024):
2869                                temp = SIS_CMD_QUEUE_SIZE_1M;
2870                                break;
2871                        default:
2872                        case (512 * 1024):
2873                                temp = SIS_CMD_QUEUE_SIZE_512k;
2874                        }
2875                }
2876
2877                SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2878                SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2879
2880                if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2881                        /* Must disable dual pipe on XGI_40. Can't do
2882                         * this in MMIO mode, because it requires
2883                         * setting/clearing a bit in the MMIO fire trigger
2884                         * register.
2885                         */
2886                        if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2887
2888                                MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2889
2890                                SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2891
2892                                tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2893                                MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2894
2895                                tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2896                                MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2897
2898                                writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2899                                writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2900                                writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2901                                writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2902
2903                                MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2904
2905                                sisfb_syncaccel(ivideo);
2906
2907                                SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2908
2909                        }
2910                }
2911
2912                tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2913                MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2914
2915                temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2916                SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2917
2918                tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2919                MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2920
2921                ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2922        }
2923#endif
2924
2925        ivideo->engineok = 1;
2926}
2927
2928static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2929{
2930        u8 reg;
2931        int i;
2932
2933        reg = SiS_GetReg(SISCR, 0x36);
2934        reg &= 0x0f;
2935        if(ivideo->sisvga_engine == SIS_300_VGA) {
2936                ivideo->CRT2LCDType = sis300paneltype[reg];
2937        } else if(ivideo->chip >= SIS_661) {
2938                ivideo->CRT2LCDType = sis661paneltype[reg];
2939        } else {
2940                ivideo->CRT2LCDType = sis310paneltype[reg];
2941                if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2942                        if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2943                           (ivideo->CRT2LCDType != LCD_320x240_3)) {
2944                                ivideo->CRT2LCDType = LCD_320x240;
2945                        }
2946                }
2947        }
2948
2949        if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2950                /* For broken BIOSes: Assume 1024x768, RGB18 */
2951                ivideo->CRT2LCDType = LCD_1024x768;
2952                SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2953                SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2954                printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2955        }
2956
2957        for(i = 0; i < SIS_LCD_NUMBER; i++) {
2958                if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2959                        ivideo->lcdxres = sis_lcd_data[i].xres;
2960                        ivideo->lcdyres = sis_lcd_data[i].yres;
2961                        ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2962                        break;
2963                }
2964        }
2965
2966#ifdef CONFIG_FB_SIS_300
2967        if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2968                ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2969                ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2970        } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2971                ivideo->lcdxres =  848; ivideo->lcdyres =  480;
2972                ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2973        } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2974                ivideo->lcdxres =  856; ivideo->lcdyres =  480;
2975                ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2976        }
2977#endif
2978
2979        printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2980                        ivideo->lcdxres, ivideo->lcdyres);
2981}
2982
2983static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2984{
2985#ifdef CONFIG_FB_SIS_300
2986        /* Save the current PanelDelayCompensation if the LCD is currently used */
2987        if(ivideo->sisvga_engine == SIS_300_VGA) {
2988                if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2989                        int tmp;
2990                        tmp = SiS_GetReg(SISCR, 0x30);
2991                        if(tmp & 0x20) {
2992                                /* Currently on LCD? If yes, read current pdc */
2993                                ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2994                                ivideo->detectedpdc &= 0x3c;
2995                                if(ivideo->SiS_Pr.PDC == -1) {
2996                                        /* Let option override detection */
2997                                        ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2998                                }
2999                                printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3000                                        ivideo->detectedpdc);
3001                        }
3002                        if((ivideo->SiS_Pr.PDC != -1) &&
3003                           (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3004                                printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3005                                        ivideo->SiS_Pr.PDC);
3006                        }
3007                }
3008        }
3009#endif
3010
3011#ifdef CONFIG_FB_SIS_315
3012        if(ivideo->sisvga_engine == SIS_315_VGA) {
3013
3014                /* Try to find about LCDA */
3015                if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3016                        int tmp;
3017                        tmp = SiS_GetReg(SISPART1, 0x13);
3018                        if(tmp & 0x04) {
3019                                ivideo->SiS_Pr.SiS_UseLCDA = true;
3020                                ivideo->detectedlcda = 0x03;
3021                        }
3022                }
3023
3024                /* Save PDC */
3025                if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3026                        int tmp;
3027                        tmp = SiS_GetReg(SISCR, 0x30);
3028                        if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3029                                /* Currently on LCD? If yes, read current pdc */
3030                                u8 pdc;
3031                                pdc = SiS_GetReg(SISPART1, 0x2D);
3032                                ivideo->detectedpdc  = (pdc & 0x0f) << 1;
3033                                ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3034                                pdc = SiS_GetReg(SISPART1, 0x35);
3035                                ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3036                                pdc = SiS_GetReg(SISPART1, 0x20);
3037                                ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3038                                if(ivideo->newrom) {
3039                                        /* New ROM invalidates other PDC resp. */
3040                                        if(ivideo->detectedlcda != 0xff) {
3041                                                ivideo->detectedpdc = 0xff;
3042                                        } else {
3043                                                ivideo->detectedpdca = 0xff;
3044                                        }
3045                                }
3046                                if(ivideo->SiS_Pr.PDC == -1) {
3047                                        if(ivideo->detectedpdc != 0xff) {
3048                                                ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3049                                        }
3050                                }
3051                                if(ivideo->SiS_Pr.PDCA == -1) {
3052                                        if(ivideo->detectedpdca != 0xff) {
3053                                                ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3054                                        }
3055                                }
3056                                if(ivideo->detectedpdc != 0xff) {
3057                                        printk(KERN_INFO
3058                                                "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3059                                                ivideo->detectedpdc);
3060                                }
3061                                if(ivideo->detectedpdca != 0xff) {
3062                                        printk(KERN_INFO
3063                                                "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3064                                                ivideo->detectedpdca);
3065                                }
3066                        }
3067
3068                        /* Save EMI */
3069                        if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3070                                ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3071                                ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3072                                ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3073                                ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3074                                ivideo->SiS_Pr.HaveEMI = true;
3075                                if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3076                                        ivideo->SiS_Pr.HaveEMILCD = true;
3077                                }
3078                        }
3079                }
3080
3081                /* Let user override detected PDCs (all bridges) */
3082                if(ivideo->vbflags2 & VB2_30xBLV) {
3083                        if((ivideo->SiS_Pr.PDC != -1) &&
3084                           (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3085                                printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3086                                        ivideo->SiS_Pr.PDC);
3087                        }
3088                        if((ivideo->SiS_Pr.PDCA != -1) &&
3089                           (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3090                                printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3091                                 ivideo->SiS_Pr.PDCA);
3092                        }
3093                }
3094
3095        }
3096#endif
3097}
3098
3099/* -------------------- Memory manager routines ---------------------- */
3100
3101static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3102{
3103        u32 ret = ivideo->sisfb_parm_mem * 1024;
3104        u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3105        u32 def;
3106
3107        /* Calculate heap start = end of memory for console
3108         *
3109         * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3110         * C = console, D = heap, H = HWCursor, Q = cmd-queue
3111         *
3112         * On 76x in UMA+LFB mode, the layout is as follows:
3113         * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3114         * where the heap is the entire UMA area, eventually
3115         * into the LFB area if the given mem parameter is
3116         * higher than the size of the UMA memory.
3117         *
3118         * Basically given by "mem" parameter
3119         *
3120         * maximum = videosize - cmd_queue - hwcursor
3121         *           (results in a heap of size 0)
3122         * default = SiS 300: depends on videosize
3123         *           SiS 315/330/340/XGI: 32k below max
3124         */
3125
3126        if(ivideo->sisvga_engine == SIS_300_VGA) {
3127                if(ivideo->video_size > 0x1000000) {
3128                        def = 0xc00000;
3129                } else if(ivideo->video_size > 0x800000) {
3130                        def = 0x800000;
3131                } else {
3132                        def = 0x400000;
3133                }
3134        } else if(ivideo->UMAsize && ivideo->LFBsize) {
3135                ret = def = 0;
3136        } else {
3137                def = maxoffs - 0x8000;
3138        }
3139
3140        /* Use default for secondary card for now (FIXME) */
3141        if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3142                ret = def;
3143
3144        return ret;
3145}
3146
3147static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3148{
3149        u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3150        u32 ret = 0;
3151
3152        if(ivideo->UMAsize && ivideo->LFBsize) {
3153                if( (!ivideo->sisfb_parm_mem)                   ||
3154                    ((ivideo->sisfb_parm_mem * 1024) > max)     ||
3155                    ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3156                        ret = ivideo->UMAsize;
3157                        max -= ivideo->UMAsize;
3158                } else {
3159                        ret = max - (ivideo->sisfb_parm_mem * 1024);
3160                        max = ivideo->sisfb_parm_mem * 1024;
3161                }
3162                ivideo->video_offset = ret;
3163                ivideo->sisfb_mem = max;
3164        } else {
3165                ret = max - ivideo->heapstart;
3166                ivideo->sisfb_mem = ivideo->heapstart;
3167        }
3168
3169        return ret;
3170}
3171
3172static int sisfb_heap_init(struct sis_video_info *ivideo)
3173{
3174        struct SIS_OH *poh;
3175
3176        ivideo->video_offset = 0;
3177        if(ivideo->sisfb_parm_mem) {
3178                if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3179                    (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3180                        ivideo->sisfb_parm_mem = 0;
3181                }
3182        }
3183
3184        ivideo->heapstart = sisfb_getheapstart(ivideo);
3185        ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3186
3187        ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3188        ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3189
3190        printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3191                (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3192
3193        ivideo->sisfb_heap.vinfo = ivideo;
3194
3195        ivideo->sisfb_heap.poha_chain = NULL;
3196        ivideo->sisfb_heap.poh_freelist = NULL;
3197
3198        poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3199        if(poh == NULL)
3200                return 1;
3201
3202        poh->poh_next = &ivideo->sisfb_heap.oh_free;
3203        poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3204        poh->size = ivideo->sisfb_heap_size;
3205        poh->offset = ivideo->heapstart;
3206
3207        ivideo->sisfb_heap.oh_free.poh_next = poh;
3208        ivideo->sisfb_heap.oh_free.poh_prev = poh;
3209        ivideo->sisfb_heap.oh_free.size = 0;
3210        ivideo->sisfb_heap.max_freesize = poh->size;
3211
3212        ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3213        ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3214        ivideo->sisfb_heap.oh_used.size = SENTINEL;
3215
3216        if(ivideo->cardnumber == 0) {
3217                /* For the first card, make this heap the "global" one
3218                 * for old DRM (which could handle only one card)
3219                 */
3220                sisfb_heap = &ivideo->sisfb_heap;
3221        }
3222
3223        return 0;
3224}
3225
3226static struct SIS_OH *
3227sisfb_poh_new_node(struct SIS_HEAP *memheap)
3228{
3229        struct SIS_OHALLOC      *poha;
3230        struct SIS_OH           *poh;
3231        unsigned long           cOhs;
3232        int                     i;
3233
3234        if(memheap->poh_freelist == NULL) {
3235                poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3236                if(!poha)
3237                        return NULL;
3238
3239                poha->poha_next = memheap->poha_chain;
3240                memheap->poha_chain = poha;
3241
3242                cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3243
3244                poh = &poha->aoh[0];
3245                for(i = cOhs - 1; i != 0; i--) {
3246                        poh->poh_next = poh + 1;
3247                        poh = poh + 1;
3248                }
3249
3250                poh->poh_next = NULL;
3251                memheap->poh_freelist = &poha->aoh[0];
3252        }
3253
3254        poh = memheap->poh_freelist;
3255        memheap->poh_freelist = poh->poh_next;
3256
3257        return poh;
3258}
3259
3260static struct SIS_OH *
3261sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3262{
3263        struct SIS_OH   *pohThis;
3264        struct SIS_OH   *pohRoot;
3265        int             bAllocated = 0;
3266
3267        if(size > memheap->max_freesize) {
3268                DPRINTK("sisfb: Can't allocate %dk video memory\n",
3269                        (unsigned int) size / 1024);
3270                return NULL;
3271        }
3272
3273        pohThis = memheap->oh_free.poh_next;
3274
3275        while(pohThis != &memheap->oh_free) {
3276                if(size <= pohThis->size) {
3277                        bAllocated = 1;
3278                        break;
3279                }
3280                pohThis = pohThis->poh_next;
3281        }
3282
3283        if(!bAllocated) {
3284                DPRINTK("sisfb: Can't allocate %dk video memory\n",
3285                        (unsigned int) size / 1024);
3286                return NULL;
3287        }
3288
3289        if(size == pohThis->size) {
3290                pohRoot = pohThis;
3291                sisfb_delete_node(pohThis);
3292        } else {
3293                pohRoot = sisfb_poh_new_node(memheap);
3294                if(pohRoot == NULL)
3295                        return NULL;
3296
3297                pohRoot->offset = pohThis->offset;
3298                pohRoot->size = size;
3299
3300                pohThis->offset += size;
3301                pohThis->size -= size;
3302        }
3303
3304        memheap->max_freesize -= size;
3305
3306        pohThis = &memheap->oh_used;
3307        sisfb_insert_node(pohThis, pohRoot);
3308
3309        return pohRoot;
3310}
3311
3312static void
3313sisfb_delete_node(struct SIS_OH *poh)
3314{
3315        poh->poh_prev->poh_next = poh->poh_next;
3316        poh->poh_next->poh_prev = poh->poh_prev;
3317}
3318
3319static void
3320sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3321{
3322        struct SIS_OH *pohTemp = pohList->poh_next;
3323
3324        pohList->poh_next = poh;
3325        pohTemp->poh_prev = poh;
3326
3327        poh->poh_prev = pohList;
3328        poh->poh_next = pohTemp;
3329}
3330
3331static struct SIS_OH *
3332sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3333{
3334        struct SIS_OH *pohThis;
3335        struct SIS_OH *poh_freed;
3336        struct SIS_OH *poh_prev;
3337        struct SIS_OH *poh_next;
3338        u32    ulUpper;
3339        u32    ulLower;
3340        int    foundNode = 0;
3341
3342        poh_freed = memheap->oh_used.poh_next;
3343
3344        while(poh_freed != &memheap->oh_used) {
3345                if(poh_freed->offset == base) {
3346                        foundNode = 1;
3347                        break;
3348                }
3349
3350                poh_freed = poh_freed->poh_next;
3351        }
3352
3353        if(!foundNode)
3354                return NULL;
3355
3356        memheap->max_freesize += poh_freed->size;
3357
3358        poh_prev = poh_next = NULL;
3359        ulUpper = poh_freed->offset + poh_freed->size;
3360        ulLower = poh_freed->offset;
3361
3362        pohThis = memheap->oh_free.poh_next;
3363
3364        while(pohThis != &memheap->oh_free) {
3365                if(pohThis->offset == ulUpper) {
3366                        poh_next = pohThis;
3367                } else if((pohThis->offset + pohThis->size) == ulLower) {
3368                        poh_prev = pohThis;
3369                }
3370                pohThis = pohThis->poh_next;
3371        }
3372
3373        sisfb_delete_node(poh_freed);
3374
3375        if(poh_prev && poh_next) {
3376                poh_prev->size += (poh_freed->size + poh_next->size);
3377                sisfb_delete_node(poh_next);
3378                sisfb_free_node(memheap, poh_freed);
3379                sisfb_free_node(memheap, poh_next);
3380                return poh_prev;
3381        }
3382
3383        if(poh_prev) {
3384                poh_prev->size += poh_freed->size;
3385                sisfb_free_node(memheap, poh_freed);
3386                return poh_prev;
3387        }
3388
3389        if(poh_next) {
3390                poh_next->size += poh_freed->size;
3391                poh_next->offset = poh_freed->offset;
3392                sisfb_free_node(memheap, poh_freed);
3393                return poh_next;
3394        }
3395
3396        sisfb_insert_node(&memheap->oh_free, poh_freed);
3397
3398        return poh_freed;
3399}
3400
3401static void
3402sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3403{
3404        if(poh == NULL)
3405                return;
3406
3407        poh->poh_next = memheap->poh_freelist;
3408        memheap->poh_freelist = poh;
3409}
3410
3411static void
3412sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3413{
3414        struct SIS_OH *poh = NULL;
3415
3416        if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3417                poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3418
3419        if(poh == NULL) {
3420                req->offset = req->size = 0;
3421                DPRINTK("sisfb: Video RAM allocation failed\n");
3422        } else {
3423                req->offset = poh->offset;
3424                req->size = poh->size;
3425                DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3426                        (poh->offset + ivideo->video_vbase));
3427        }
3428}
3429
3430void
3431sis_malloc(struct sis_memreq *req)
3432{
3433        struct sis_video_info *ivideo = sisfb_heap->vinfo;
3434
3435        if(&ivideo->sisfb_heap == sisfb_heap)
3436                sis_int_malloc(ivideo, req);
3437        else
3438                req->offset = req->size = 0;
3439}
3440
3441void
3442sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3443{
3444        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3445
3446        sis_int_malloc(ivideo, req);
3447}
3448
3449/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3450
3451static void
3452sis_int_free(struct sis_video_info *ivideo, u32 base)
3453{
3454        struct SIS_OH *poh;
3455
3456        if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3457                return;
3458
3459        poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3460
3461        if(poh == NULL) {
3462                DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3463                        (unsigned int) base);
3464        }
3465}
3466
3467void
3468sis_free(u32 base)
3469{
3470        struct sis_video_info *ivideo = sisfb_heap->vinfo;
3471
3472        sis_int_free(ivideo, base);
3473}
3474
3475void
3476sis_free_new(struct pci_dev *pdev, u32 base)
3477{
3478        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3479
3480        sis_int_free(ivideo, base);
3481}
3482
3483/* --------------------- SetMode routines ------------------------- */
3484
3485static void
3486sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3487{
3488        u8 cr30, cr31;
3489
3490        /* Check if MMIO and engines are enabled,
3491         * and sync in case they are. Can't use
3492         * ivideo->accel here, as this might have
3493         * been changed before this is called.
3494         */
3495        cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3496        cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3497        /* MMIO and 2D/3D engine enabled? */
3498        if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3499#ifdef CONFIG_FB_SIS_300
3500                if(ivideo->sisvga_engine == SIS_300_VGA) {
3501                        /* Don't care about TurboQueue. It's
3502                         * enough to know that the engines
3503                         * are enabled
3504                         */
3505                        sisfb_syncaccel(ivideo);
3506                }
3507#endif
3508#ifdef CONFIG_FB_SIS_315
3509                if(ivideo->sisvga_engine == SIS_315_VGA) {
3510                        /* Check that any queue mode is
3511                         * enabled, and that the queue
3512                         * is not in the state of "reset"
3513                         */
3514                        cr30 = SiS_GetReg(SISSR, 0x26);
3515                        if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3516                                sisfb_syncaccel(ivideo);
3517                        }
3518                }
3519#endif
3520        }
3521}
3522
3523static void
3524sisfb_pre_setmode(struct sis_video_info *ivideo)
3525{
3526        u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3527        int tvregnum = 0;
3528
3529        ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3530
3531        SiS_SetReg(SISSR, 0x05, 0x86);
3532
3533        cr31 = SiS_GetReg(SISCR, 0x31);
3534        cr31 &= ~0x60;
3535        cr31 |= 0x04;
3536
3537        cr33 = ivideo->rate_idx & 0x0F;
3538
3539#ifdef CONFIG_FB_SIS_315
3540        if(ivideo->sisvga_engine == SIS_315_VGA) {
3541           if(ivideo->chip >= SIS_661) {
3542              cr38 = SiS_GetReg(SISCR, 0x38);
3543              cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
3544           } else {
3545              tvregnum = 0x38;
3546              cr38 = SiS_GetReg(SISCR, tvregnum);
3547              cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
3548           }
3549        }
3550#endif
3551#ifdef CONFIG_FB_SIS_300
3552        if(ivideo->sisvga_engine == SIS_300_VGA) {
3553           tvregnum = 0x35;
3554           cr38 = SiS_GetReg(SISCR, tvregnum);
3555        }
3556#endif
3557
3558        SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3559        SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3560        ivideo->curFSTN = ivideo->curDSTN = 0;
3561
3562        switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3563
3564           case CRT2_TV:
3565              cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
3566              if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3567#ifdef CONFIG_FB_SIS_315
3568                 if(ivideo->chip >= SIS_661) {
3569                    cr38 |= 0x04;
3570                    if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
3571                    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
3572                    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3573                    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3574                    cr35 &= ~0x01;
3575                    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3576                 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3577                    cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3578                    cr38 |= 0x08;
3579                    if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
3580                    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
3581                    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3582                    cr31 &= ~0x01;
3583                    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3584                 }
3585#endif
3586              } else if((ivideo->vbflags & TV_HIVISION) &&
3587                                (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3588                 if(ivideo->chip >= SIS_661) {
3589                    cr38 |= 0x04;
3590                    cr35 |= 0x60;
3591                 } else {
3592                    cr30 |= 0x80;
3593                 }
3594                 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3595                 cr31 |= 0x01;
3596                 cr35 |= 0x01;
3597                 ivideo->currentvbflags |= TV_HIVISION;
3598              } else if(ivideo->vbflags & TV_SCART) {
3599                 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3600                 cr31 |= 0x01;
3601                 cr35 |= 0x01;
3602                 ivideo->currentvbflags |= TV_SCART;
3603              } else {
3604                 if(ivideo->vbflags & TV_SVIDEO) {
3605                    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3606                    ivideo->currentvbflags |= TV_SVIDEO;
3607                 }
3608                 if(ivideo->vbflags & TV_AVIDEO) {
3609                    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3610                    ivideo->currentvbflags |= TV_AVIDEO;
3611                 }
3612              }
3613              cr31 |= SIS_DRIVER_MODE;
3614
3615              if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3616                 if(ivideo->vbflags & TV_PAL) {
3617                    cr31 |= 0x01; cr35 |= 0x01;
3618                    ivideo->currentvbflags |= TV_PAL;
3619                    if(ivideo->vbflags & TV_PALM) {
3620                       cr38 |= 0x40; cr35 |= 0x04;
3621                       ivideo->currentvbflags |= TV_PALM;
3622                    } else if(ivideo->vbflags & TV_PALN) {
3623                       cr38 |= 0x80; cr35 |= 0x08;
3624                       ivideo->currentvbflags |= TV_PALN;
3625                    }
3626                 } else {
3627                    cr31 &= ~0x01; cr35 &= ~0x01;
3628                    ivideo->currentvbflags |= TV_NTSC;
3629                    if(ivideo->vbflags & TV_NTSCJ) {
3630                       cr38 |= 0x40; cr35 |= 0x02;
3631                       ivideo->currentvbflags |= TV_NTSCJ;
3632                    }
3633                 }
3634              }
3635              break;
3636
3637           case CRT2_LCD:
3638              cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3639              cr31 |= SIS_DRIVER_MODE;
3640              SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3641              SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3642              ivideo->curFSTN = ivideo->sisfb_fstn;
3643              ivideo->curDSTN = ivideo->sisfb_dstn;
3644              break;
3645
3646           case CRT2_VGA:
3647              cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3648              cr31 |= SIS_DRIVER_MODE;
3649              if(ivideo->sisfb_nocrt2rate) {
3650                 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3651              } else {
3652                 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3653              }
3654              break;
3655
3656           default:     /* disable CRT2 */
3657              cr30 = 0x00;
3658              cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3659        }
3660
3661        SiS_SetReg(SISCR, 0x30, cr30);
3662        SiS_SetReg(SISCR, 0x33, cr33);
3663
3664        if(ivideo->chip >= SIS_661) {
3665#ifdef CONFIG_FB_SIS_315
3666           cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
3667           SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3668           cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
3669           SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3670#endif
3671        } else if(ivideo->chip != SIS_300) {
3672           SiS_SetReg(SISCR, tvregnum, cr38);
3673        }
3674        SiS_SetReg(SISCR, 0x31, cr31);
3675
3676        ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3677
3678        sisfb_check_engine_and_sync(ivideo);
3679}
3680
3681/* Fix SR11 for 661 and later */
3682#ifdef CONFIG_FB_SIS_315
3683static void
3684sisfb_fixup_SR11(struct sis_video_info *ivideo)
3685{
3686        u8  tmpreg;
3687
3688        if(ivideo->chip >= SIS_661) {
3689                tmpreg = SiS_GetReg(SISSR, 0x11);
3690                if(tmpreg & 0x20) {
3691                        tmpreg = SiS_GetReg(SISSR, 0x3e);
3692                        tmpreg = (tmpreg + 1) & 0xff;
3693                        SiS_SetReg(SISSR, 0x3e, tmpreg);
3694                        tmpreg = SiS_GetReg(SISSR, 0x11);
3695                }
3696                if(tmpreg & 0xf0) {
3697                        SiS_SetRegAND(SISSR, 0x11, 0x0f);
3698                }
3699        }
3700}
3701#endif
3702
3703static void
3704sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3705{
3706        if(val > 32) val = 32;
3707        if(val < -32) val = -32;
3708        ivideo->tvxpos = val;
3709
3710        if(ivideo->sisfblocked) return;
3711        if(!ivideo->modechanged) return;
3712
3713        if(ivideo->currentvbflags & CRT2_TV) {
3714
3715                if(ivideo->vbflags2 & VB2_CHRONTEL) {
3716
3717                        int x = ivideo->tvx;
3718
3719                        switch(ivideo->chronteltype) {
3720                        case 1:
3721                                x += val;
3722                                if(x < 0) x = 0;
3723                                SiS_SetReg(SISSR, 0x05, 0x86);
3724                                SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3725                                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3726                                break;
3727                        case 2:
3728                                /* Not supported by hardware */
3729                                break;
3730                        }
3731
3732                } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3733
3734                        u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3735                        unsigned short temp;
3736
3737                        p2_1f = ivideo->p2_1f;
3738                        p2_20 = ivideo->p2_20;
3739                        p2_2b = ivideo->p2_2b;
3740                        p2_42 = ivideo->p2_42;
3741                        p2_43 = ivideo->p2_43;
3742
3743                        temp = p2_1f | ((p2_20 & 0xf0) << 4);
3744                        temp += (val * 2);
3745                        p2_1f = temp & 0xff;
3746                        p2_20 = (temp & 0xf00) >> 4;
3747                        p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3748                        temp = p2_43 | ((p2_42 & 0xf0) << 4);
3749                        temp += (val * 2);
3750                        p2_43 = temp & 0xff;
3751                        p2_42 = (temp & 0xf00) >> 4;
3752                        SiS_SetReg(SISPART2, 0x1f, p2_1f);
3753                        SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3754                        SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3755                        SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3756                        SiS_SetReg(SISPART2, 0x43, p2_43);
3757                }
3758        }
3759}
3760
3761static void
3762sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3763{
3764        if(val > 32) val = 32;
3765        if(val < -32) val = -32;
3766        ivideo->tvypos = val;
3767
3768        if(ivideo->sisfblocked) return;
3769        if(!ivideo->modechanged) return;
3770
3771        if(ivideo->currentvbflags & CRT2_TV) {
3772
3773                if(ivideo->vbflags2 & VB2_CHRONTEL) {
3774
3775                        int y = ivideo->tvy;
3776
3777                        switch(ivideo->chronteltype) {
3778                        case 1:
3779                                y -= val;
3780                                if(y < 0) y = 0;
3781                                SiS_SetReg(SISSR, 0x05, 0x86);
3782                                SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3783                                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3784                                break;
3785                        case 2:
3786                                /* Not supported by hardware */
3787                                break;
3788                        }
3789
3790                } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3791
3792                        char p2_01, p2_02;
3793                        val /= 2;
3794                        p2_01 = ivideo->p2_01;
3795                        p2_02 = ivideo->p2_02;
3796
3797                        p2_01 += val;
3798                        p2_02 += val;
3799                        if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3800                                while((p2_01 <= 0) || (p2_02 <= 0)) {
3801                                        p2_01 += 2;
3802                                        p2_02 += 2;
3803                                }
3804                        }
3805                        SiS_SetReg(SISPART2, 0x01, p2_01);
3806                        SiS_SetReg(SISPART2, 0x02, p2_02);
3807                }
3808        }
3809}
3810
3811static void
3812sisfb_post_setmode(struct sis_video_info *ivideo)
3813{
3814        bool crt1isoff = false;
3815        bool doit = true;
3816#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3817        u8 reg;
3818#endif
3819#ifdef CONFIG_FB_SIS_315
3820        u8 reg1;
3821#endif
3822
3823        SiS_SetReg(SISSR, 0x05, 0x86);
3824
3825#ifdef CONFIG_FB_SIS_315
3826        sisfb_fixup_SR11(ivideo);
3827#endif
3828
3829        /* Now we actually HAVE changed the display mode */
3830        ivideo->modechanged = 1;
3831
3832        /* We can't switch off CRT1 if bridge is in slave mode */
3833        if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3834                if(sisfb_bridgeisslave(ivideo)) doit = false;
3835        } else
3836                ivideo->sisfb_crt1off = 0;
3837
3838#ifdef CONFIG_FB_SIS_300
3839        if(ivideo->sisvga_engine == SIS_300_VGA) {
3840                if((ivideo->sisfb_crt1off) && (doit)) {
3841                        crt1isoff = true;
3842                        reg = 0x00;
3843                } else {
3844                        crt1isoff = false;
3845                        reg = 0x80;
3846                }
3847                SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3848        }
3849#endif
3850#ifdef CONFIG_FB_SIS_315
3851        if(ivideo->sisvga_engine == SIS_315_VGA) {
3852                if((ivideo->sisfb_crt1off) && (doit)) {
3853                        crt1isoff = true;
3854                        reg  = 0x40;
3855                        reg1 = 0xc0;
3856                } else {
3857                        crt1isoff = false;
3858                        reg  = 0x00;
3859                        reg1 = 0x00;
3860                }
3861                SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3862                SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3863        }
3864#endif
3865
3866        if(crt1isoff) {
3867                ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3868                ivideo->currentvbflags |= VB_SINGLE_MODE;
3869        } else {
3870                ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3871                if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3872                        ivideo->currentvbflags |= VB_MIRROR_MODE;
3873                } else {
3874                        ivideo->currentvbflags |= VB_SINGLE_MODE;
3875                }
3876        }
3877
3878        SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3879
3880        if(ivideo->currentvbflags & CRT2_TV) {
3881                if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3882                        ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3883                        ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3884                        ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3885                        ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3886                        ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3887                        ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3888                        ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3889                } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3890                        if(ivideo->chronteltype == 1) {
3891                                ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3892                                ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3893                                ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3894                                ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3895                        }
3896                }
3897        }
3898
3899        if(ivideo->tvxpos) {
3900                sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3901        }
3902        if(ivideo->tvypos) {
3903                sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3904        }
3905
3906        /* Eventually sync engines */
3907        sisfb_check_engine_and_sync(ivideo);
3908
3909        /* (Re-)Initialize chip engines */
3910        if(ivideo->accel) {
3911                sisfb_engine_init(ivideo);
3912        } else {
3913                ivideo->engineok = 0;
3914        }
3915}
3916
3917static int
3918sisfb_reset_mode(struct sis_video_info *ivideo)
3919{
3920        if(sisfb_set_mode(ivideo, 0))
3921                return 1;
3922
3923        sisfb_set_pitch(ivideo);
3924        sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3925        sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3926
3927        return 0;
3928}
3929
3930static void
3931sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3932{
3933        int mycrt1off;
3934
3935        switch(sisfb_command->sisfb_cmd) {
3936        case SISFB_CMD_GETVBFLAGS:
3937                if(!ivideo->modechanged) {
3938                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3939                } else {
3940                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3941                        sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3942                        sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3943                }
3944                break;
3945        case SISFB_CMD_SWITCHCRT1:
3946                /* arg[0]: 0 = off, 1 = on, 99 = query */
3947                if(!ivideo->modechanged) {
3948                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3949                } else if(sisfb_command->sisfb_arg[0] == 99) {
3950                        /* Query */
3951                        sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3952                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3953                } else if(ivideo->sisfblocked) {
3954                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3955                } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3956                                        (sisfb_command->sisfb_arg[0] == 0)) {
3957                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3958                } else {
3959                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3960                        mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3961                        if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3962                            ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3963                                ivideo->sisfb_crt1off = mycrt1off;
3964                                if(sisfb_reset_mode(ivideo)) {
3965                                        sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3966                                }
3967                        }
3968                        sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3969                }
3970                break;
3971        /* more to come */
3972        default:
3973                sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3974                printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3975                        sisfb_command->sisfb_cmd);
3976        }
3977}
3978
3979#ifndef MODULE
3980static int __init sisfb_setup(char *options)
3981{
3982        char *this_opt;
3983
3984        sisfb_setdefaultparms();
3985
3986        if(!options || !(*options))
3987                return 0;
3988
3989        while((this_opt = strsep(&options, ",")) != NULL) {
3990
3991                if(!(*this_opt)) continue;
3992
3993                if(!strncasecmp(this_opt, "off", 3)) {
3994                        sisfb_off = 1;
3995                } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
3996                        /* Need to check crt2 type first for fstn/dstn */
3997                        sisfb_search_crt2type(this_opt + 14);
3998                } else if(!strncasecmp(this_opt, "tvmode:",7)) {
3999                        sisfb_search_tvstd(this_opt + 7);
4000                } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
4001                        sisfb_search_tvstd(this_opt + 11);
4002                } else if(!strncasecmp(this_opt, "mode:", 5)) {
4003                        sisfb_search_mode(this_opt + 5, false);
4004                } else if(!strncasecmp(this_opt, "vesa:", 5)) {
4005                        sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4006                } else if(!strncasecmp(this_opt, "rate:", 5)) {
4007                        sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4008                } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
4009                        sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4010                } else if(!strncasecmp(this_opt, "mem:",4)) {
4011                        sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4012                } else if(!strncasecmp(this_opt, "pdc:", 4)) {
4013                        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4014                } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
4015                        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4016                } else if(!strncasecmp(this_opt, "noaccel", 7)) {
4017                        sisfb_accel = 0;
4018                } else if(!strncasecmp(this_opt, "accel", 5)) {
4019                        sisfb_accel = -1;
4020                } else if(!strncasecmp(this_opt, "noypan", 6)) {
4021                        sisfb_ypan = 0;
4022                } else if(!strncasecmp(this_opt, "ypan", 4)) {
4023                        sisfb_ypan = -1;
4024                } else if(!strncasecmp(this_opt, "nomax", 5)) {
4025                        sisfb_max = 0;
4026                } else if(!strncasecmp(this_opt, "max", 3)) {
4027                        sisfb_max = -1;
4028                } else if(!strncasecmp(this_opt, "userom:", 7)) {
4029                        sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4030                } else if(!strncasecmp(this_opt, "useoem:", 7)) {
4031                        sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4032                } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
4033                        sisfb_nocrt2rate = 1;
4034                } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
4035                        unsigned long temp = 2;
4036                        temp = simple_strtoul(this_opt + 9, NULL, 0);
4037                        if((temp == 0) || (temp == 1)) {
4038                           sisfb_scalelcd = temp ^ 1;
4039                        }
4040                } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4041                        int temp = 0;
4042                        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4043                        if((temp >= -32) && (temp <= 32)) {
4044                           sisfb_tvxposoffset = temp;
4045                        }
4046                } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4047                        int temp = 0;
4048                        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4049                        if((temp >= -32) && (temp <= 32)) {
4050                           sisfb_tvyposoffset = temp;
4051                        }
4052                } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4053                        sisfb_search_specialtiming(this_opt + 14);
4054                } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4055                        int temp = 4;
4056                        temp = simple_strtoul(this_opt + 7, NULL, 0);
4057                        if((temp >= 0) && (temp <= 3)) {
4058                           sisfb_lvdshl = temp;
4059                        }
4060                } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4061                        sisfb_search_mode(this_opt, true);
4062#if !defined(__i386__) && !defined(__x86_64__)
4063                } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4064                        sisfb_resetcard = 1;
4065                } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4066                        sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4067#endif
4068                } else {
4069                        printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4070                }
4071
4072        }
4073
4074        return 0;
4075}
4076#endif
4077
4078static int sisfb_check_rom(void __iomem *rom_base,
4079                           struct sis_video_info *ivideo)
4080{
4081        void __iomem *rom;
4082        int romptr;
4083
4084        if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4085                return 0;
4086
4087        romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4088        if(romptr > (0x10000 - 8))
4089                return 0;
4090
4091        rom = rom_base + romptr;
4092
4093        if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
4094           (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4095                return 0;
4096
4097        if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4098                return 0;
4099
4100        if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4101                return 0;
4102
4103        return 1;
4104}
4105
4106static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4107{
4108        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4109        void __iomem *rom_base;
4110        unsigned char *myrombase = NULL;
4111        size_t romsize;
4112
4113        /* First, try the official pci ROM functions (except
4114         * on integrated chipsets which have no ROM).
4115         */
4116
4117        if(!ivideo->nbridge) {
4118
4119                if((rom_base = pci_map_rom(pdev, &romsize))) {
4120
4121                        if(sisfb_check_rom(rom_base, ivideo)) {
4122
4123                                if((myrombase = vmalloc(65536))) {
4124                                        memcpy_fromio(myrombase, rom_base,
4125                                                        (romsize > 65536) ? 65536 : romsize);
4126                                }
4127                        }
4128                        pci_unmap_rom(pdev, rom_base);
4129                }
4130        }
4131
4132        if(myrombase) return myrombase;
4133
4134        /* Otherwise do it the conventional way. */
4135
4136#if defined(__i386__) || defined(__x86_64__)
4137        {
4138                u32 temp;
4139
4140                for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4141
4142                        rom_base = ioremap(temp, 65536);
4143                        if (!rom_base)
4144                                continue;
4145
4146                        if (!sisfb_check_rom(rom_base, ivideo)) {
4147                                iounmap(rom_base);
4148                                continue;
4149                        }
4150
4151                        if ((myrombase = vmalloc(65536)))
4152                                memcpy_fromio(myrombase, rom_base, 65536);
4153
4154                        iounmap(rom_base);
4155                        break;
4156
4157                }
4158
4159        }
4160#endif
4161
4162        return myrombase;
4163}
4164
4165static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4166                                unsigned int *mapsize, unsigned int min)
4167{
4168        if (*mapsize < (min << 20))
4169                return;
4170
4171        ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
4172
4173        if(!ivideo->video_vbase) {
4174                printk(KERN_ERR
4175                        "sisfb: Unable to map maximum video RAM for size detection\n");
4176                (*mapsize) >>= 1;
4177                while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
4178                        (*mapsize) >>= 1;
4179                        if((*mapsize) < (min << 20))
4180                                break;
4181                }
4182                if(ivideo->video_vbase) {
4183                        printk(KERN_ERR
4184                                "sisfb: Video RAM size detection limited to %dMB\n",
4185                                (int)((*mapsize) >> 20));
4186                }
4187        }
4188}
4189
4190#ifdef CONFIG_FB_SIS_300
4191static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4192{
4193        void __iomem *FBAddress = ivideo->video_vbase;
4194        unsigned short temp;
4195        unsigned char reg;
4196        int i, j;
4197
4198        SiS_SetRegAND(SISSR, 0x15, 0xFB);
4199        SiS_SetRegOR(SISSR, 0x15, 0x04);
4200        SiS_SetReg(SISSR, 0x13, 0x00);
4201        SiS_SetReg(SISSR, 0x14, 0xBF);
4202
4203        for(i = 0; i < 2; i++) {
4204                temp = 0x1234;
4205                for(j = 0; j < 4; j++) {
4206                        writew(temp, FBAddress);
4207                        if(readw(FBAddress) == temp)
4208                                break;
4209                        SiS_SetRegOR(SISSR, 0x3c, 0x01);
4210                        reg = SiS_GetReg(SISSR, 0x05);
4211                        reg = SiS_GetReg(SISSR, 0x05);
4212                        SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4213                        reg = SiS_GetReg(SISSR, 0x05);
4214                        reg = SiS_GetReg(SISSR, 0x05);
4215                        temp++;
4216                }
4217        }
4218
4219        writel(0x01234567L, FBAddress);
4220        writel(0x456789ABL, (FBAddress + 4));
4221        writel(0x89ABCDEFL, (FBAddress + 8));
4222        writel(0xCDEF0123L, (FBAddress + 12));
4223
4224        reg = SiS_GetReg(SISSR, 0x3b);
4225        if(reg & 0x01) {
4226                if(readl((FBAddress + 12)) == 0xCDEF0123L)
4227                        return 4;       /* Channel A 128bit */
4228        }
4229
4230        if(readl((FBAddress + 4)) == 0x456789ABL)
4231                return 2;               /* Channel B 64bit */
4232
4233        return 1;                       /* 32bit */
4234}
4235
4236static const unsigned short SiS_DRAMType[17][5] = {
4237        {0x0C,0x0A,0x02,0x40,0x39},
4238        {0x0D,0x0A,0x01,0x40,0x48},
4239        {0x0C,0x09,0x02,0x20,0x35},
4240        {0x0D,0x09,0x01,0x20,0x44},
4241        {0x0C,0x08,0x02,0x10,0x31},
4242        {0x0D,0x08,0x01,0x10,0x40},
4243        {0x0C,0x0A,0x01,0x20,0x34},
4244        {0x0C,0x09,0x01,0x08,0x32},
4245        {0x0B,0x08,0x02,0x08,0x21},
4246        {0x0C,0x08,0x01,0x08,0x30},
4247        {0x0A,0x08,0x02,0x04,0x11},
4248        {0x0B,0x0A,0x01,0x10,0x28},
4249        {0x09,0x08,0x02,0x02,0x01},
4250        {0x0B,0x09,0x01,0x08,0x24},
4251        {0x0B,0x08,0x01,0x04,0x20},
4252        {0x0A,0x08,0x01,0x02,0x10},
4253        {0x09,0x08,0x01,0x01,0x00}
4254};
4255
4256static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4257                                 int buswidth, int PseudoRankCapacity,
4258                                 int PseudoAdrPinCount, unsigned int mapsize)
4259{
4260        void __iomem *FBAddr = ivideo->video_vbase;
4261        unsigned short sr14;
4262        unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4263        unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4264
4265         for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4266
4267                RankCapacity = buswidth * SiS_DRAMType[k][3];
4268
4269                if(RankCapacity != PseudoRankCapacity)
4270                        continue;
4271
4272                if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4273                        continue;
4274
4275                BankNumHigh = RankCapacity * 16 * iteration - 1;
4276                if(iteration == 3) {             /* Rank No */
4277                        BankNumMid  = RankCapacity * 16 - 1;
4278                } else {
4279                        BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
4280                }
4281
4282                PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4283                PhysicalAdrHigh = BankNumHigh;
4284                PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4285                PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4286
4287                SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4288                SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
4289                sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4290                if(buswidth == 4)      sr14 |= 0x80;
4291                else if(buswidth == 2) sr14 |= 0x40;
4292                SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4293                SiS_SetReg(SISSR, 0x14, sr14);
4294
4295                BankNumHigh <<= 16;
4296                BankNumMid <<= 16;
4297
4298                if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
4299                   (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
4300                   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
4301                   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4302                        continue;
4303
4304                /* Write data */
4305                writew(((unsigned short)PhysicalAdrHigh),
4306                                (FBAddr + BankNumHigh + PhysicalAdrHigh));
4307                writew(((unsigned short)BankNumMid),
4308                                (FBAddr + BankNumMid  + PhysicalAdrHigh));
4309                writew(((unsigned short)PhysicalAdrHalfPage),
4310                                (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4311                writew(((unsigned short)PhysicalAdrOtherPage),
4312                                (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4313
4314                /* Read data */
4315                if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4316                        return 1;
4317        }
4318
4319        return 0;
4320}
4321
4322static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4323{
4324        struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
4325        int     i, j, buswidth;
4326        int     PseudoRankCapacity, PseudoAdrPinCount;
4327
4328        buswidth = sisfb_post_300_buswidth(ivideo);
4329
4330        for(i = 6; i >= 0; i--) {
4331                PseudoRankCapacity = 1 << i;
4332                for(j = 4; j >= 1; j--) {
4333                        PseudoAdrPinCount = 15 - j;
4334                        if((PseudoRankCapacity * j) <= 64) {
4335                                if(sisfb_post_300_rwtest(ivideo,
4336                                                j,
4337                                                buswidth,
4338                                                PseudoRankCapacity,
4339                                                PseudoAdrPinCount,
4340                                                mapsize))
4341                                        return;
4342                        }
4343                }
4344        }
4345}
4346
4347static void sisfb_post_sis300(struct pci_dev *pdev)
4348{
4349        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4350        unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4351        u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
4352        u16 index, rindex, memtype = 0;
4353        unsigned int mapsize;
4354
4355        if(!ivideo->SiS_Pr.UseROM)
4356                bios = NULL;
4357
4358        SiS_SetReg(SISSR, 0x05, 0x86);
4359
4360        if(bios) {
4361                if(bios[0x52] & 0x80) {
4362                        memtype = bios[0x52];
4363                } else {
4364                        memtype = SiS_GetReg(SISSR, 0x3a);
4365                }
4366                memtype &= 0x07;
4367        }
4368
4369        v3 = 0x80; v6 = 0x80;
4370        if(ivideo->revision_id <= 0x13) {
4371                v1 = 0x44; v2 = 0x42;
4372                v4 = 0x44; v5 = 0x42;
4373        } else {
4374                v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4375                v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4376                if(bios) {
4377                        index = memtype * 5;
4378                        rindex = index + 0x54;
4379                        v1 = bios[rindex++];
4380                        v2 = bios[rindex++];
4381                        v3 = bios[rindex++];
4382                        rindex = index + 0x7c;
4383                        v4 = bios[rindex++];
4384                        v5 = bios[rindex++];
4385                        v6 = bios[rindex++];
4386                }
4387        }
4388        SiS_SetReg(SISSR, 0x28, v1);
4389        SiS_SetReg(SISSR, 0x29, v2);
4390        SiS_SetReg(SISSR, 0x2a, v3);
4391        SiS_SetReg(SISSR, 0x2e, v4);
4392        SiS_SetReg(SISSR, 0x2f, v5);
4393        SiS_SetReg(SISSR, 0x30, v6);
4394
4395        v1 = 0x10;
4396        if(bios)
4397                v1 = bios[0xa4];
4398        SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
4399
4400        SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
4401
4402        v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4403        v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4404        if(bios) {
4405                memtype += 0xa5;
4406                v1 = bios[memtype];
4407                v2 = bios[memtype + 8];
4408                v3 = bios[memtype + 16];
4409                v4 = bios[memtype + 24];
4410                v5 = bios[memtype + 32];
4411                v6 = bios[memtype + 40];
4412                v7 = bios[memtype + 48];
4413                v8 = bios[memtype + 56];
4414        }
4415        if(ivideo->revision_id >= 0x80)
4416                v3 &= 0xfd;
4417        SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4418        SiS_SetReg(SISSR, 0x16, v2);
4419        SiS_SetReg(SISSR, 0x17, v3);
4420        SiS_SetReg(SISSR, 0x18, v4);
4421        SiS_SetReg(SISSR, 0x19, v5);
4422        SiS_SetReg(SISSR, 0x1a, v6);
4423        SiS_SetReg(SISSR, 0x1b, v7);
4424        SiS_SetReg(SISSR, 0x1c, v8);       /* ---- */
4425        SiS_SetRegAND(SISSR, 0x15, 0xfb);
4426        SiS_SetRegOR(SISSR, 0x15, 0x04);
4427        if(bios) {
4428                if(bios[0x53] & 0x02) {
4429                        SiS_SetRegOR(SISSR, 0x19, 0x20);
4430                }
4431        }
4432        v1 = 0x04;                         /* DAC pedestal (BIOS 0xe5) */
4433        if(ivideo->revision_id >= 0x80)
4434                v1 |= 0x01;
4435        SiS_SetReg(SISSR, 0x1f, v1);
4436        SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
4437        v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4438        if(bios) {
4439                v1 = bios[0xe8];
4440                v2 = bios[0xe9];
4441                v3 = bios[0xea];
4442        }
4443        SiS_SetReg(SISSR, 0x23, v1);
4444        SiS_SetReg(SISSR, 0x24, v2);
4445        SiS_SetReg(SISSR, 0x25, v3);
4446        SiS_SetReg(SISSR, 0x21, 0x84);
4447        SiS_SetReg(SISSR, 0x22, 0x00);
4448        SiS_SetReg(SISCR, 0x37, 0x00);
4449        SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
4450        SiS_SetReg(SISPART1, 0x00, 0x00);
4451        v1 = 0x40; v2 = 0x11;
4452        if(bios) {
4453                v1 = bios[0xec];
4454                v2 = bios[0xeb];
4455        }
4456        SiS_SetReg(SISPART1, 0x02, v1);
4457
4458        if(ivideo->revision_id >= 0x80)
4459                v2 &= ~0x01;
4460
4461        reg = SiS_GetReg(SISPART4, 0x00);
4462        if((reg == 1) || (reg == 2)) {
4463                SiS_SetReg(SISCR, 0x37, 0x02);
4464                SiS_SetReg(SISPART2, 0x00, 0x1c);
4465                v4 = 0x00; v5 = 0x00; v6 = 0x10;
4466                if(ivideo->SiS_Pr.UseROM) {
4467                        v4 = bios[0xf5];
4468                        v5 = bios[0xf6];
4469                        v6 = bios[0xf7];
4470                }
4471                SiS_SetReg(SISPART4, 0x0d, v4);
4472                SiS_SetReg(SISPART4, 0x0e, v5);
4473                SiS_SetReg(SISPART4, 0x10, v6);
4474                SiS_SetReg(SISPART4, 0x0f, 0x3f);
4475                reg = SiS_GetReg(SISPART4, 0x01);
4476                if(reg >= 0xb0) {
4477                        reg = SiS_GetReg(SISPART4, 0x23);
4478                        reg &= 0x20;
4479                        reg <<= 1;
4480                        SiS_SetReg(SISPART4, 0x23, reg);
4481                }
4482        } else {
4483                v2 &= ~0x10;
4484        }
4485        SiS_SetReg(SISSR, 0x32, v2);
4486
4487        SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
4488
4489        reg = SiS_GetReg(SISSR, 0x16);
4490        reg &= 0xc3;
4491        SiS_SetReg(SISCR, 0x35, reg);
4492        SiS_SetReg(SISCR, 0x83, 0x00);
4493#if !defined(__i386__) && !defined(__x86_64__)
4494        if(sisfb_videoram) {
4495                SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
4496                reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4497                SiS_SetReg(SISSR, 0x14, reg);
4498        } else {
4499#endif
4500                /* Need to map max FB size for finding out about RAM size */
4501                mapsize = ivideo->video_size;
4502                sisfb_post_map_vram(ivideo, &mapsize, 4);
4503
4504                if(ivideo->video_vbase) {
4505                        sisfb_post_300_ramsize(pdev, mapsize);
4506                        iounmap(ivideo->video_vbase);
4507                } else {
4508                        printk(KERN_DEBUG
4509                                "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4510                        SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
4511                        SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
4512                }
4513#if !defined(__i386__) && !defined(__x86_64__)
4514        }
4515#endif
4516        if(bios) {
4517                v1 = bios[0xe6];
4518                v2 = bios[0xe7];
4519        } else {
4520                reg = SiS_GetReg(SISSR, 0x3a);
4521                if((reg & 0x30) == 0x30) {
4522                        v1 = 0x04; /* PCI */
4523                        v2 = 0x92;
4524                } else {
4525                        v1 = 0x14; /* AGP */
4526                        v2 = 0xb2;
4527                }
4528        }
4529        SiS_SetReg(SISSR, 0x21, v1);
4530        SiS_SetReg(SISSR, 0x22, v2);
4531
4532        /* Sense CRT1 */
4533        sisfb_sense_crt1(ivideo);
4534
4535        /* Set default mode, don't clear screen */
4536        ivideo->SiS_Pr.SiS_UseOEM = false;
4537        SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4538        SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4539        ivideo->curFSTN = ivideo->curDSTN = 0;
4540        ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4541        SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4542
4543        SiS_SetReg(SISSR, 0x05, 0x86);
4544
4545        /* Display off */
4546        SiS_SetRegOR(SISSR, 0x01, 0x20);
4547
4548        /* Save mode number in CR34 */
4549        SiS_SetReg(SISCR, 0x34, 0x2e);
4550
4551        /* Let everyone know what the current mode is */
4552        ivideo->modeprechange = 0x2e;
4553}
4554#endif
4555
4556#ifdef CONFIG_FB_SIS_315
4557#if 0
4558static void sisfb_post_sis315330(struct pci_dev *pdev)
4559{
4560        /* TODO */
4561}
4562#endif
4563
4564static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4565{
4566        return ivideo->chip_real_id == XGI_21;
4567}
4568
4569static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4570{
4571        unsigned int i;
4572        u8 reg;
4573
4574        for(i = 0; i <= (delay * 10 * 36); i++) {
4575                reg = SiS_GetReg(SISSR, 0x05);
4576                reg++;
4577        }
4578}
4579
4580static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4581                                  struct pci_dev *mypdev,
4582                                  unsigned short pcivendor)
4583{
4584        struct pci_dev *pdev = NULL;
4585        unsigned short temp;
4586        int ret = 0;
4587
4588        while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4589                temp = pdev->vendor;
4590                if(temp == pcivendor) {
4591                        ret = 1;
4592                        pci_dev_put(pdev);
4593                        break;
4594                }
4595        }
4596
4597        return ret;
4598}
4599
4600static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4601                                 unsigned int enda, unsigned int mapsize)
4602{
4603        unsigned int pos;
4604        int i;
4605
4606        writel(0, ivideo->video_vbase);
4607
4608        for(i = starta; i <= enda; i++) {
4609                pos = 1 << i;
4610                if(pos < mapsize)
4611                        writel(pos, ivideo->video_vbase + pos);
4612        }
4613
4614        sisfb_post_xgi_delay(ivideo, 150);
4615
4616        if(readl(ivideo->video_vbase) != 0)
4617                return 0;
4618
4619        for(i = starta; i <= enda; i++) {
4620                pos = 1 << i;
4621                if(pos < mapsize) {
4622                        if(readl(ivideo->video_vbase + pos) != pos)
4623                                return 0;
4624                } else
4625                        return 0;
4626        }
4627
4628        return 1;
4629}
4630
4631static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4632{
4633        unsigned int buswidth, ranksize, channelab, mapsize;
4634        int i, j, k, l, status;
4635        u8 reg, sr14;
4636        static const u8 dramsr13[12 * 5] = {
4637                0x02, 0x0e, 0x0b, 0x80, 0x5d,
4638                0x02, 0x0e, 0x0a, 0x40, 0x59,
4639                0x02, 0x0d, 0x0b, 0x40, 0x4d,
4640                0x02, 0x0e, 0x09, 0x20, 0x55,
4641                0x02, 0x0d, 0x0a, 0x20, 0x49,
4642                0x02, 0x0c, 0x0b, 0x20, 0x3d,
4643                0x02, 0x0e, 0x08, 0x10, 0x51,
4644                0x02, 0x0d, 0x09, 0x10, 0x45,
4645                0x02, 0x0c, 0x0a, 0x10, 0x39,
4646                0x02, 0x0d, 0x08, 0x08, 0x41,
4647                0x02, 0x0c, 0x09, 0x08, 0x35,
4648                0x02, 0x0c, 0x08, 0x04, 0x31
4649        };
4650        static const u8 dramsr13_4[4 * 5] = {
4651                0x02, 0x0d, 0x09, 0x40, 0x45,
4652                0x02, 0x0c, 0x09, 0x20, 0x35,
4653                0x02, 0x0c, 0x08, 0x10, 0x31,
4654                0x02, 0x0b, 0x08, 0x08, 0x21
4655        };
4656
4657        /* Enable linear mode, disable 0xa0000 address decoding */
4658        /* We disable a0000 address decoding, because
4659         * - if running on x86, if the card is disabled, it means
4660         *   that another card is in the system. We don't want
4661         *   to interphere with that primary card's textmode.
4662         * - if running on non-x86, there usually is no VGA window
4663         *   at a0000.
4664         */
4665        SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4666
4667        /* Need to map max FB size for finding out about RAM size */
4668        mapsize = ivideo->video_size;
4669        sisfb_post_map_vram(ivideo, &mapsize, 32);
4670
4671        if(!ivideo->video_vbase) {
4672                printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4673                SiS_SetReg(SISSR, 0x13, 0x35);
4674                SiS_SetReg(SISSR, 0x14, 0x41);
4675                /* TODO */
4676                return -ENOMEM;
4677        }
4678
4679        /* Non-interleaving */
4680        SiS_SetReg(SISSR, 0x15, 0x00);
4681        /* No tiling */
4682        SiS_SetReg(SISSR, 0x1c, 0x00);
4683
4684        if(ivideo->chip == XGI_20) {
4685
4686                channelab = 1;
4687                reg = SiS_GetReg(SISCR, 0x97);
4688                if(!(reg & 0x01)) {     /* Single 32/16 */
4689                        buswidth = 32;
4690                        SiS_SetReg(SISSR, 0x13, 0xb1);
4691                        SiS_SetReg(SISSR, 0x14, 0x52);
4692                        sisfb_post_xgi_delay(ivideo, 1);
4693                        sr14 = 0x02;
4694                        if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4695                                goto bail_out;
4696
4697                        SiS_SetReg(SISSR, 0x13, 0x31);
4698                        SiS_SetReg(SISSR, 0x14, 0x42);
4699                        sisfb_post_xgi_delay(ivideo, 1);
4700                        if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4701                                goto bail_out;
4702
4703                        buswidth = 16;
4704                        SiS_SetReg(SISSR, 0x13, 0xb1);
4705                        SiS_SetReg(SISSR, 0x14, 0x41);
4706                        sisfb_post_xgi_delay(ivideo, 1);
4707                        sr14 = 0x01;
4708                        if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4709                                goto bail_out;
4710                        else
4711                                SiS_SetReg(SISSR, 0x13, 0x31);
4712                } else {                /* Dual 16/8 */
4713                        buswidth = 16;
4714                        SiS_SetReg(SISSR, 0x13, 0xb1);
4715                        SiS_SetReg(SISSR, 0x14, 0x41);
4716                        sisfb_post_xgi_delay(ivideo, 1);
4717                        sr14 = 0x01;
4718                        if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4719                                goto bail_out;
4720
4721                        SiS_SetReg(SISSR, 0x13, 0x31);
4722                        SiS_SetReg(SISSR, 0x14, 0x31);
4723                        sisfb_post_xgi_delay(ivideo, 1);
4724                        if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4725                                goto bail_out;
4726
4727                        buswidth = 8;
4728                        SiS_SetReg(SISSR, 0x13, 0xb1);
4729                        SiS_SetReg(SISSR, 0x14, 0x30);
4730                        sisfb_post_xgi_delay(ivideo, 1);
4731                        sr14 = 0x00;
4732                        if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4733                                goto bail_out;
4734                        else
4735                                SiS_SetReg(SISSR, 0x13, 0x31);
4736                }
4737
4738        } else {        /* XGI_40 */
4739
4740                reg = SiS_GetReg(SISCR, 0x97);
4741                if(!(reg & 0x10)) {
4742                        reg = SiS_GetReg(SISSR, 0x39);
4743                        reg >>= 1;
4744                }
4745
4746                if(reg & 0x01) {        /* DDRII */
4747                        buswidth = 32;
4748                        if(ivideo->revision_id == 2) {
4749                                channelab = 2;
4750                                SiS_SetReg(SISSR, 0x13, 0xa1);
4751                                SiS_SetReg(SISSR, 0x14, 0x44);
4752                                sr14 = 0x04;
4753                                sisfb_post_xgi_delay(ivideo, 1);
4754                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4755                                        goto bail_out;
4756
4757                                SiS_SetReg(SISSR, 0x13, 0x21);
4758                                SiS_SetReg(SISSR, 0x14, 0x34);
4759                                if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4760                                        goto bail_out;
4761
4762                                channelab = 1;
4763                                SiS_SetReg(SISSR, 0x13, 0xa1);
4764                                SiS_SetReg(SISSR, 0x14, 0x40);
4765                                sr14 = 0x00;
4766                                if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4767                                        goto bail_out;
4768
4769                                SiS_SetReg(SISSR, 0x13, 0x21);
4770                                SiS_SetReg(SISSR, 0x14, 0x30);
4771                        } else {
4772                                channelab = 3;
4773                                SiS_SetReg(SISSR, 0x13, 0xa1);
4774                                SiS_SetReg(SISSR, 0x14, 0x4c);
4775                                sr14 = 0x0c;
4776                                sisfb_post_xgi_delay(ivideo, 1);
4777                                if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4778                                        goto bail_out;
4779
4780                                channelab = 2;
4781                                SiS_SetReg(SISSR, 0x14, 0x48);
4782                                sisfb_post_xgi_delay(ivideo, 1);
4783                                sr14 = 0x08;
4784                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4785                                        goto bail_out;
4786
4787                                SiS_SetReg(SISSR, 0x13, 0x21);
4788                                SiS_SetReg(SISSR, 0x14, 0x3c);
4789                                sr14 = 0x0c;
4790
4791                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4792                                        channelab = 3;
4793                                } else {
4794                                        channelab = 2;
4795                                        SiS_SetReg(SISSR, 0x14, 0x38);
4796                                        sr14 = 0x08;
4797                                }
4798                        }
4799                        sisfb_post_xgi_delay(ivideo, 1);
4800
4801                } else {        /* DDR */
4802
4803                        buswidth = 64;
4804                        if(ivideo->revision_id == 2) {
4805                                channelab = 1;
4806                                SiS_SetReg(SISSR, 0x13, 0xa1);
4807                                SiS_SetReg(SISSR, 0x14, 0x52);
4808                                sisfb_post_xgi_delay(ivideo, 1);
4809                                sr14 = 0x02;
4810                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4811                                        goto bail_out;
4812
4813                                SiS_SetReg(SISSR, 0x13, 0x21);
4814                                SiS_SetReg(SISSR, 0x14, 0x42);
4815                        } else {
4816                                channelab = 2;
4817                                SiS_SetReg(SISSR, 0x13, 0xa1);
4818                                SiS_SetReg(SISSR, 0x14, 0x5a);
4819                                sisfb_post_xgi_delay(ivideo, 1);
4820                                sr14 = 0x0a;
4821                                if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4822                                        goto bail_out;
4823
4824                                SiS_SetReg(SISSR, 0x13, 0x21);
4825                                SiS_SetReg(SISSR, 0x14, 0x4a);
4826                        }
4827                        sisfb_post_xgi_delay(ivideo, 1);
4828
4829                }
4830        }
4831
4832bail_out:
4833        SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4834        sisfb_post_xgi_delay(ivideo, 1);
4835
4836        j = (ivideo->chip == XGI_20) ? 5 : 9;
4837        k = (ivideo->chip == XGI_20) ? 12 : 4;
4838        status = -EIO;
4839
4840        for(i = 0; i < k; i++) {
4841
4842                reg = (ivideo->chip == XGI_20) ?
4843                                dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4844                SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4845                sisfb_post_xgi_delay(ivideo, 50);
4846
4847                ranksize = (ivideo->chip == XGI_20) ?
4848                                dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4849
4850                reg = SiS_GetReg(SISSR, 0x13);
4851                if(reg & 0x80) ranksize <<= 1;
4852
4853                if(ivideo->chip == XGI_20) {
4854                        if(buswidth == 16)      ranksize <<= 1;
4855                        else if(buswidth == 32) ranksize <<= 2;
4856                } else {
4857                        if(buswidth == 64)      ranksize <<= 1;
4858                }
4859
4860                reg = 0;
4861                l = channelab;
4862                if(l == 3) l = 4;
4863                if((ranksize * l) <= 256) {
4864                        while((ranksize >>= 1)) reg += 0x10;
4865                }
4866
4867                if(!reg) continue;
4868
4869                SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4870                sisfb_post_xgi_delay(ivideo, 1);
4871
4872                if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4873                        status = 0;
4874                        break;
4875                }
4876        }
4877
4878        iounmap(ivideo->video_vbase);
4879
4880        return status;
4881}
4882
4883static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4884{
4885        u8 v1, v2, v3;
4886        int index;
4887        static const u8 cs90[8 * 3] = {
4888                0x16, 0x01, 0x01,
4889                0x3e, 0x03, 0x01,
4890                0x7c, 0x08, 0x01,
4891                0x79, 0x06, 0x01,
4892                0x29, 0x01, 0x81,
4893                0x5c, 0x23, 0x01,
4894                0x5c, 0x23, 0x01,
4895                0x5c, 0x23, 0x01
4896        };
4897        static const u8 csb8[8 * 3] = {
4898                0x5c, 0x23, 0x01,
4899                0x29, 0x01, 0x01,
4900                0x7c, 0x08, 0x01,
4901                0x79, 0x06, 0x01,
4902                0x29, 0x01, 0x81,
4903                0x5c, 0x23, 0x01,
4904                0x5c, 0x23, 0x01,
4905                0x5c, 0x23, 0x01
4906        };
4907
4908        regb = 0;  /* ! */
4909
4910        index = regb * 3;
4911        v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4912        if(ivideo->haveXGIROM) {
4913                v1 = ivideo->bios_abase[0x90 + index];
4914                v2 = ivideo->bios_abase[0x90 + index + 1];
4915                v3 = ivideo->bios_abase[0x90 + index + 2];
4916        }
4917        SiS_SetReg(SISSR, 0x28, v1);
4918        SiS_SetReg(SISSR, 0x29, v2);
4919        SiS_SetReg(SISSR, 0x2a, v3);
4920        sisfb_post_xgi_delay(ivideo, 0x43);
4921        sisfb_post_xgi_delay(ivideo, 0x43);
4922        sisfb_post_xgi_delay(ivideo, 0x43);
4923        index = regb * 3;
4924        v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4925        if(ivideo->haveXGIROM) {
4926                v1 = ivideo->bios_abase[0xb8 + index];
4927                v2 = ivideo->bios_abase[0xb8 + index + 1];
4928                v3 = ivideo->bios_abase[0xb8 + index + 2];
4929        }
4930        SiS_SetReg(SISSR, 0x2e, v1);
4931        SiS_SetReg(SISSR, 0x2f, v2);
4932        SiS_SetReg(SISSR, 0x30, v3);
4933        sisfb_post_xgi_delay(ivideo, 0x43);
4934        sisfb_post_xgi_delay(ivideo, 0x43);
4935        sisfb_post_xgi_delay(ivideo, 0x43);
4936}
4937
4938static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4939                                            u8 regb)
4940{
4941        unsigned char *bios = ivideo->bios_abase;
4942        u8 v1;
4943
4944        SiS_SetReg(SISSR, 0x28, 0x64);
4945        SiS_SetReg(SISSR, 0x29, 0x63);
4946        sisfb_post_xgi_delay(ivideo, 15);
4947        SiS_SetReg(SISSR, 0x18, 0x00);
4948        SiS_SetReg(SISSR, 0x19, 0x20);
4949        SiS_SetReg(SISSR, 0x16, 0x00);
4950        SiS_SetReg(SISSR, 0x16, 0x80);
4951        SiS_SetReg(SISSR, 0x18, 0xc5);
4952        SiS_SetReg(SISSR, 0x19, 0x23);
4953        SiS_SetReg(SISSR, 0x16, 0x00);
4954        SiS_SetReg(SISSR, 0x16, 0x80);
4955        sisfb_post_xgi_delay(ivideo, 1);
4956        SiS_SetReg(SISCR, 0x97, 0x11);
4957        sisfb_post_xgi_setclocks(ivideo, regb);
4958        sisfb_post_xgi_delay(ivideo, 0x46);
4959        SiS_SetReg(SISSR, 0x18, 0xc5);
4960        SiS_SetReg(SISSR, 0x19, 0x23);
4961        SiS_SetReg(SISSR, 0x16, 0x00);
4962        SiS_SetReg(SISSR, 0x16, 0x80);
4963        sisfb_post_xgi_delay(ivideo, 1);
4964        SiS_SetReg(SISSR, 0x1b, 0x04);
4965        sisfb_post_xgi_delay(ivideo, 1);
4966        SiS_SetReg(SISSR, 0x1b, 0x00);
4967        sisfb_post_xgi_delay(ivideo, 1);
4968        v1 = 0x31;
4969        if (ivideo->haveXGIROM) {
4970                v1 = bios[0xf0];
4971        }
4972        SiS_SetReg(SISSR, 0x18, v1);
4973        SiS_SetReg(SISSR, 0x19, 0x06);
4974        SiS_SetReg(SISSR, 0x16, 0x04);
4975        SiS_SetReg(SISSR, 0x16, 0x84);
4976        sisfb_post_xgi_delay(ivideo, 1);
4977}
4978
4979static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4980{
4981        sisfb_post_xgi_setclocks(ivideo, 1);
4982
4983        SiS_SetReg(SISCR, 0x97, 0x11);
4984        sisfb_post_xgi_delay(ivideo, 0x46);
4985
4986        SiS_SetReg(SISSR, 0x18, 0x00);  /* EMRS2 */
4987        SiS_SetReg(SISSR, 0x19, 0x80);
4988        SiS_SetReg(SISSR, 0x16, 0x05);
4989        SiS_SetReg(SISSR, 0x16, 0x85);
4990
4991        SiS_SetReg(SISSR, 0x18, 0x00);  /* EMRS3 */
4992        SiS_SetReg(SISSR, 0x19, 0xc0);
4993        SiS_SetReg(SISSR, 0x16, 0x05);
4994        SiS_SetReg(SISSR, 0x16, 0x85);
4995
4996        SiS_SetReg(SISSR, 0x18, 0x00);  /* EMRS1 */
4997        SiS_SetReg(SISSR, 0x19, 0x40);
4998        SiS_SetReg(SISSR, 0x16, 0x05);
4999        SiS_SetReg(SISSR, 0x16, 0x85);
5000
5001        SiS_SetReg(SISSR, 0x18, 0x42);  /* MRS1 */
5002        SiS_SetReg(SISSR, 0x19, 0x02);
5003        SiS_SetReg(SISSR, 0x16, 0x05);
5004        SiS_SetReg(SISSR, 0x16, 0x85);
5005        sisfb_post_xgi_delay(ivideo, 1);
5006
5007        SiS_SetReg(SISSR, 0x1b, 0x04);
5008        sisfb_post_xgi_delay(ivideo, 1);
5009
5010        SiS_SetReg(SISSR, 0x1b, 0x00);
5011        sisfb_post_xgi_delay(ivideo, 1);
5012
5013        SiS_SetReg(SISSR, 0x18, 0x42);  /* MRS1 */
5014        SiS_SetReg(SISSR, 0x19, 0x00);
5015        SiS_SetReg(SISSR, 0x16, 0x05);
5016        SiS_SetReg(SISSR, 0x16, 0x85);
5017        sisfb_post_xgi_delay(ivideo, 1);
5018}
5019
5020static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5021{
5022        unsigned char *bios = ivideo->bios_abase;
5023        static const u8 cs158[8] = {
5024                0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5025        };
5026        static const u8 cs160[8] = {
5027                0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5028        };
5029        static const u8 cs168[8] = {
5030                0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5031        };
5032        u8 reg;
5033        u8 v1;
5034        u8 v2;
5035        u8 v3;
5036
5037        SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5038        SiS_SetReg(SISCR, 0x82, 0x77);
5039        SiS_SetReg(SISCR, 0x86, 0x00);
5040        reg = SiS_GetReg(SISCR, 0x86);
5041        SiS_SetReg(SISCR, 0x86, 0x88);
5042        reg = SiS_GetReg(SISCR, 0x86);
5043        v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5044        if (ivideo->haveXGIROM) {
5045                v1 = bios[regb + 0x168];
5046                v2 = bios[regb + 0x160];
5047                v3 = bios[regb + 0x158];
5048        }
5049        SiS_SetReg(SISCR, 0x86, v1);
5050        SiS_SetReg(SISCR, 0x82, 0x77);
5051        SiS_SetReg(SISCR, 0x85, 0x00);
5052        reg = SiS_GetReg(SISCR, 0x85);
5053        SiS_SetReg(SISCR, 0x85, 0x88);
5054        reg = SiS_GetReg(SISCR, 0x85);
5055        SiS_SetReg(SISCR, 0x85, v2);
5056        SiS_SetReg(SISCR, 0x82, v3);
5057        SiS_SetReg(SISCR, 0x98, 0x01);
5058        SiS_SetReg(SISCR, 0x9a, 0x02);
5059        if (sisfb_xgi_is21(ivideo))
5060                sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5061        else
5062                sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5063}
5064
5065static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5066{
5067        unsigned char *bios = ivideo->bios_abase;
5068        u8 ramtype;
5069        u8 reg;
5070        u8 v1;
5071
5072        ramtype = 0x00; v1 = 0x10;
5073        if (ivideo->haveXGIROM) {
5074                ramtype = bios[0x62];
5075                v1 = bios[0x1d2];
5076        }
5077        if (!(ramtype & 0x80)) {
5078                if (sisfb_xgi_is21(ivideo)) {
5079                        SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5080                        SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
5081                        reg = SiS_GetReg(SISCR, 0x48);
5082                        SiS_SetRegOR(SISCR, 0xb4, 0x02);
5083                        ramtype = reg & 0x01;             /* GPIOH */
5084                } else if (ivideo->chip == XGI_20) {
5085                        SiS_SetReg(SISCR, 0x97, v1);
5086                        reg = SiS_GetReg(SISCR, 0x97);
5087                        if (reg & 0x10) {
5088                                ramtype = (reg & 0x01) << 1;
5089                        }
5090                } else {
5091                        reg = SiS_GetReg(SISSR, 0x39);
5092                        ramtype = reg & 0x02;
5093                        if (!(ramtype)) {
5094                                reg = SiS_GetReg(SISSR, 0x3a);
5095                                ramtype = (reg >> 1) & 0x01;
5096                        }
5097                }
5098        }
5099        ramtype &= 0x07;
5100
5101        return ramtype;
5102}
5103
5104static int sisfb_post_xgi(struct pci_dev *pdev)
5105{
5106        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5107        unsigned char *bios = ivideo->bios_abase;
5108        struct pci_dev *mypdev = NULL;
5109        const u8 *ptr, *ptr2;
5110        u8 v1, v2, v3, v4, v5, reg, ramtype;
5111        u32 rega, regb, regd;
5112        int i, j, k, index;
5113        static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5114        static const u8 cs76[2] = { 0xa3, 0xfb };
5115        static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5116        static const u8 cs158[8] = {
5117                0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5118        };
5119        static const u8 cs160[8] = {
5120                0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5121        };
5122        static const u8 cs168[8] = {
5123                0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5124        };
5125        static const u8 cs128[3 * 8] = {
5126                0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5127                0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5128                0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5129        };
5130        static const u8 cs148[2 * 8] = {
5131                0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5132                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5133        };
5134        static const u8 cs31a[8 * 4] = {
5135                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5136                0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5137                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5138                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5139        };
5140        static const u8 cs33a[8 * 4] = {
5141                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5142                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5143                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5144                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5145        };
5146        static const u8 cs45a[8 * 2] = {
5147                0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5148                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5149        };
5150        static const u8 cs170[7 * 8] = {
5151                0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5152                0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5153                0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5154                0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5155                0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5156                0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5157                0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5158        };
5159        static const u8 cs1a8[3 * 8] = {
5160                0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5161                0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5162                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5163        };
5164        static const u8 cs100[2 * 8] = {
5165                0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5166                0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5167        };
5168
5169        /* VGA enable */
5170        reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5171        SiS_SetRegByte(SISVGAENABLE, reg);
5172
5173        /* Misc */
5174        reg = SiS_GetRegByte(SISMISCR) | 0x01;
5175        SiS_SetRegByte(SISMISCW, reg);
5176
5177        /* Unlock SR */
5178        SiS_SetReg(SISSR, 0x05, 0x86);
5179        reg = SiS_GetReg(SISSR, 0x05);
5180        if(reg != 0xa1)
5181                return 0;
5182
5183        /* Clear some regs */
5184        for(i = 0; i < 0x22; i++) {
5185                if(0x06 + i == 0x20) continue;
5186                SiS_SetReg(SISSR, 0x06 + i, 0x00);
5187        }
5188        for(i = 0; i < 0x0b; i++) {
5189                SiS_SetReg(SISSR, 0x31 + i, 0x00);
5190        }
5191        for(i = 0; i < 0x10; i++) {
5192                SiS_SetReg(SISCR, 0x30 + i, 0x00);
5193        }
5194
5195        ptr = cs78;
5196        if(ivideo->haveXGIROM) {
5197                ptr = (const u8 *)&bios[0x78];
5198        }
5199        for(i = 0; i < 3; i++) {
5200                SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5201        }
5202
5203        ptr = cs76;
5204        if(ivideo->haveXGIROM) {
5205                ptr = (const u8 *)&bios[0x76];
5206        }
5207        for(i = 0; i < 2; i++) {
5208                SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5209        }
5210
5211        v1 = 0x18; v2 = 0x00;
5212        if(ivideo->haveXGIROM) {
5213                v1 = bios[0x74];
5214                v2 = bios[0x75];
5215        }
5216        SiS_SetReg(SISSR, 0x07, v1);
5217        SiS_SetReg(SISSR, 0x11, 0x0f);
5218        SiS_SetReg(SISSR, 0x1f, v2);
5219        /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5220        SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5221        SiS_SetReg(SISSR, 0x27, 0x74);
5222
5223        ptr = cs7b;
5224        if(ivideo->haveXGIROM) {
5225                ptr = (const u8 *)&bios[0x7b];
5226        }
5227        for(i = 0; i < 3; i++) {
5228                SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5229        }
5230
5231        if(ivideo->chip == XGI_40) {
5232                if(ivideo->revision_id == 2) {
5233                        SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5234                }
5235                SiS_SetReg(SISCR, 0x7d, 0xfe);
5236                SiS_SetReg(SISCR, 0x7e, 0x0f);
5237        }
5238        if(ivideo->revision_id == 0) {  /* 40 *and* 20? */
5239                SiS_SetRegAND(SISCR, 0x58, 0xd7);
5240                reg = SiS_GetReg(SISCR, 0xcb);
5241                if(reg & 0x20) {
5242                        SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5243                }
5244        }
5245
5246        reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5247        SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5248
5249        if(ivideo->chip == XGI_20) {
5250                SiS_SetReg(SISSR, 0x36, 0x70);
5251        } else {
5252                SiS_SetReg(SISVID, 0x00, 0x86);
5253                SiS_SetReg(SISVID, 0x32, 0x00);
5254                SiS_SetReg(SISVID, 0x30, 0x00);
5255                SiS_SetReg(SISVID, 0x32, 0x01);
5256                SiS_SetReg(SISVID, 0x30, 0x00);
5257                SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5258                SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5259
5260                SiS_SetReg(SISPART1, 0x2f, 0x01);
5261                SiS_SetReg(SISPART1, 0x00, 0x00);
5262                SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5263                SiS_SetReg(SISPART1, 0x2e, 0x08);
5264                SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5265                SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5266
5267                reg = SiS_GetReg(SISPART4, 0x00);
5268                if(reg == 1 || reg == 2) {
5269                        SiS_SetReg(SISPART2, 0x00, 0x1c);
5270                        SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5271                        SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5272                        SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5273                        SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5274
5275                        reg = SiS_GetReg(SISPART4, 0x01);
5276                        if((reg & 0xf0) >= 0xb0) {
5277                                reg = SiS_GetReg(SISPART4, 0x23);
5278                                if(reg & 0x20) reg |= 0x40;
5279                                SiS_SetReg(SISPART4, 0x23, reg);
5280                                reg = (reg & 0x20) ? 0x02 : 0x00;
5281                                SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5282                        }
5283                }
5284
5285                v1 = bios[0x77];
5286
5287                reg = SiS_GetReg(SISSR, 0x3b);
5288                if(reg & 0x02) {
5289                        reg = SiS_GetReg(SISSR, 0x3a);
5290                        v2 = (reg & 0x30) >> 3;
5291                        if(!(v2 & 0x04)) v2 ^= 0x02;
5292                        reg = SiS_GetReg(SISSR, 0x39);
5293                        if(reg & 0x80) v2 |= 0x80;
5294                        v2 |= 0x01;
5295
5296                        if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5297                                pci_dev_put(mypdev);
5298                                if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5299                                        v2 &= 0xf9;
5300                                v2 |= 0x08;
5301                                v1 &= 0xfe;
5302                        } else {
5303                                mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5304                                if(!mypdev)
5305                                        mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5306                                if(!mypdev)
5307                                        mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5308                                if(mypdev) {
5309                                        pci_read_config_dword(mypdev, 0x94, &regd);
5310                                        regd &= 0xfffffeff;
5311                                        pci_write_config_dword(mypdev, 0x94, regd);
5312                                        v1 &= 0xfe;
5313                                        pci_dev_put(mypdev);
5314                                } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5315                                        v1 &= 0xfe;
5316                                } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5317                                          sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5318                                          sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5319                                          sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5320                                        if((v2 & 0x06) == 4)
5321                                                v2 ^= 0x06;
5322                                        v2 |= 0x08;
5323                                }
5324                        }
5325                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5326                }
5327                SiS_SetReg(SISSR, 0x22, v1);
5328
5329                if(ivideo->revision_id == 2) {
5330                        v1 = SiS_GetReg(SISSR, 0x3b);
5331                        v2 = SiS_GetReg(SISSR, 0x3a);
5332                        regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5333                        if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5334                                SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5335
5336                        if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5337                                /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5338                                 * of nforce 2 ROM
5339                                 */
5340                                if(0)
5341                                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5342                                pci_dev_put(mypdev);
5343                        }
5344                }
5345
5346                v1 = 0x30;
5347                reg = SiS_GetReg(SISSR, 0x3b);
5348                v2 = SiS_GetReg(SISCR, 0x5f);
5349                if((!(reg & 0x02)) && (v2 & 0x0e))
5350                        v1 |= 0x08;
5351                SiS_SetReg(SISSR, 0x27, v1);
5352
5353                if(bios[0x64] & 0x01) {
5354                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5355                }
5356
5357                v1 = bios[0x4f7];
5358                pci_read_config_dword(pdev, 0x50, &regd);
5359                regd = (regd >> 20) & 0x0f;
5360                if(regd == 1) {
5361                        v1 &= 0xfc;
5362                        SiS_SetRegOR(SISCR, 0x5f, 0x08);
5363                }
5364                SiS_SetReg(SISCR, 0x48, v1);
5365
5366                SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5367                SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5368                SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5369                SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5370                SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5371                SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5372                SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5373                SiS_SetReg(SISCR, 0x74, 0xd0);
5374                SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5375                SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5376                SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5377                v1 = bios[0x501];
5378                if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5379                        v1 = 0xf0;
5380                        pci_dev_put(mypdev);
5381                }
5382                SiS_SetReg(SISCR, 0x77, v1);
5383        }
5384
5385        /* RAM type:
5386         *
5387         * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5388         *
5389         * The code seems to written so that regb should equal ramtype,
5390         * however, so far it has been hardcoded to 0. Enable other values only
5391         * on XGI Z9, as it passes the POST, and add a warning for others.
5392         */
5393        ramtype = sisfb_post_xgi_ramtype(ivideo);
5394        if (!sisfb_xgi_is21(ivideo) && ramtype) {
5395                dev_warn(&pdev->dev,
5396                         "RAM type something else than expected: %d\n",
5397                         ramtype);
5398                regb = 0;
5399        } else {
5400                regb = ramtype;
5401        }
5402
5403        v1 = 0xff;
5404        if(ivideo->haveXGIROM) {
5405                v1 = bios[0x140 + regb];
5406        }
5407        SiS_SetReg(SISCR, 0x6d, v1);
5408
5409        ptr = cs128;
5410        if(ivideo->haveXGIROM) {
5411                ptr = (const u8 *)&bios[0x128];
5412        }
5413        for(i = 0, j = 0; i < 3; i++, j += 8) {
5414                SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5415        }
5416
5417        ptr  = cs31a;
5418        ptr2 = cs33a;
5419        if(ivideo->haveXGIROM) {
5420                index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5421                ptr  = (const u8 *)&bios[index];
5422                ptr2 = (const u8 *)&bios[index + 0x20];
5423        }
5424        for(i = 0; i < 2; i++) {
5425                if(i == 0) {
5426                        regd = le32_to_cpu(((u32 *)ptr)[regb]);
5427                        rega = 0x6b;
5428                } else {
5429                        regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5430                        rega = 0x6e;
5431                }
5432                reg = 0x00;
5433                for(j = 0; j < 16; j++) {
5434                        reg &= 0xf3;
5435                        if(regd & 0x01) reg |= 0x04;
5436                        if(regd & 0x02) reg |= 0x08;
5437                        regd >>= 2;
5438                        SiS_SetReg(SISCR, rega, reg);
5439                        reg = SiS_GetReg(SISCR, rega);
5440                        reg = SiS_GetReg(SISCR, rega);
5441                        reg += 0x10;
5442                }
5443        }
5444
5445        SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5446
5447        ptr  = NULL;
5448        if(ivideo->haveXGIROM) {
5449                index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5450                ptr  = (const u8 *)&bios[index];
5451        }
5452        for(i = 0; i < 4; i++) {
5453                SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5454                reg = 0x00;
5455                for(j = 0; j < 2; j++) {
5456                        regd = 0;
5457                        if(ptr) {
5458                                regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5459                                ptr += 4;
5460                        }
5461                        /* reg = 0x00; */
5462                        for(k = 0; k < 16; k++) {
5463                                reg &= 0xfc;
5464                                if(regd & 0x01) reg |= 0x01;
5465                                if(regd & 0x02) reg |= 0x02;
5466                                regd >>= 2;
5467                                SiS_SetReg(SISCR, 0x6f, reg);
5468                                reg = SiS_GetReg(SISCR, 0x6f);
5469                                reg = SiS_GetReg(SISCR, 0x6f);
5470                                reg += 0x08;
5471                        }
5472                }
5473        }
5474
5475        ptr  = cs148;
5476        if(ivideo->haveXGIROM) {
5477                ptr  = (const u8 *)&bios[0x148];
5478        }
5479        for(i = 0, j = 0; i < 2; i++, j += 8) {
5480                SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5481        }
5482
5483        SiS_SetRegAND(SISCR, 0x89, 0x8f);
5484
5485        ptr  = cs45a;
5486        if(ivideo->haveXGIROM) {
5487                index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5488                ptr  = (const u8 *)&bios[index];
5489        }
5490        regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5491        reg = 0x80;
5492        for(i = 0; i < 5; i++) {
5493                reg &= 0xfc;
5494                if(regd & 0x01) reg |= 0x01;
5495                if(regd & 0x02) reg |= 0x02;
5496                regd >>= 2;
5497                SiS_SetReg(SISCR, 0x89, reg);
5498                reg = SiS_GetReg(SISCR, 0x89);
5499                reg = SiS_GetReg(SISCR, 0x89);
5500                reg += 0x10;
5501        }
5502
5503        v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5504        if(ivideo->haveXGIROM) {
5505                v1 = bios[0x118 + regb];
5506                v2 = bios[0xf8 + regb];
5507                v3 = bios[0x120 + regb];
5508                v4 = bios[0x1ca];
5509        }
5510        SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5511        SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5512        SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5513        SiS_SetReg(SISCR, 0x41, v2);
5514
5515        ptr  = cs170;
5516        if(ivideo->haveXGIROM) {
5517                ptr  = (const u8 *)&bios[0x170];
5518        }
5519        for(i = 0, j = 0; i < 7; i++, j += 8) {
5520                SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5521        }
5522
5523        SiS_SetReg(SISCR, 0x59, v3);
5524
5525        ptr  = cs1a8;
5526        if(ivideo->haveXGIROM) {
5527                ptr  = (const u8 *)&bios[0x1a8];
5528        }
5529        for(i = 0, j = 0; i < 3; i++, j += 8) {
5530                SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5531        }
5532
5533        ptr  = cs100;
5534        if(ivideo->haveXGIROM) {
5535                ptr  = (const u8 *)&bios[0x100];
5536        }
5537        for(i = 0, j = 0; i < 2; i++, j += 8) {
5538                SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5539        }
5540
5541        SiS_SetReg(SISCR, 0xcf, v4);
5542
5543        SiS_SetReg(SISCR, 0x83, 0x09);
5544        SiS_SetReg(SISCR, 0x87, 0x00);
5545
5546        if(ivideo->chip == XGI_40) {
5547                if( (ivideo->revision_id == 1) ||
5548                    (ivideo->revision_id == 2) ) {
5549                        SiS_SetReg(SISCR, 0x8c, 0x87);
5550                }
5551        }
5552
5553        if (regb == 1)
5554                SiS_SetReg(SISSR, 0x17, 0x80);          /* DDR2 */
5555        else
5556                SiS_SetReg(SISSR, 0x17, 0x00);          /* DDR1 */
5557        SiS_SetReg(SISSR, 0x1a, 0x87);
5558
5559        if(ivideo->chip == XGI_20) {
5560                SiS_SetReg(SISSR, 0x15, 0x00);
5561                SiS_SetReg(SISSR, 0x1c, 0x00);
5562        }
5563
5564        switch(ramtype) {
5565        case 0:
5566                sisfb_post_xgi_setclocks(ivideo, regb);
5567                if((ivideo->chip == XGI_20) ||
5568                   (ivideo->revision_id == 1)   ||
5569                   (ivideo->revision_id == 2)) {
5570                        v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5571                        if(ivideo->haveXGIROM) {
5572                                v1 = bios[regb + 0x158];
5573                                v2 = bios[regb + 0x160];
5574                                v3 = bios[regb + 0x168];
5575                        }
5576                        SiS_SetReg(SISCR, 0x82, v1);
5577                        SiS_SetReg(SISCR, 0x85, v2);
5578                        SiS_SetReg(SISCR, 0x86, v3);
5579                } else {
5580                        SiS_SetReg(SISCR, 0x82, 0x88);
5581                        SiS_SetReg(SISCR, 0x86, 0x00);
5582                        reg = SiS_GetReg(SISCR, 0x86);
5583                        SiS_SetReg(SISCR, 0x86, 0x88);
5584                        reg = SiS_GetReg(SISCR, 0x86);
5585                        SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5586                        SiS_SetReg(SISCR, 0x82, 0x77);
5587                        SiS_SetReg(SISCR, 0x85, 0x00);
5588                        reg = SiS_GetReg(SISCR, 0x85);
5589                        SiS_SetReg(SISCR, 0x85, 0x88);
5590                        reg = SiS_GetReg(SISCR, 0x85);
5591                        SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5592                        SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5593                }
5594                if(ivideo->chip == XGI_40) {
5595                        SiS_SetReg(SISCR, 0x97, 0x00);
5596                }
5597                SiS_SetReg(SISCR, 0x98, 0x01);
5598                SiS_SetReg(SISCR, 0x9a, 0x02);
5599
5600                SiS_SetReg(SISSR, 0x18, 0x01);
5601                if((ivideo->chip == XGI_20) ||
5602                   (ivideo->revision_id == 2)) {
5603                        SiS_SetReg(SISSR, 0x19, 0x40);
5604                } else {
5605                        SiS_SetReg(SISSR, 0x19, 0x20);
5606                }
5607                SiS_SetReg(SISSR, 0x16, 0x00);
5608                SiS_SetReg(SISSR, 0x16, 0x80);
5609                if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5610                        sisfb_post_xgi_delay(ivideo, 0x43);
5611                        sisfb_post_xgi_delay(ivideo, 0x43);
5612                        sisfb_post_xgi_delay(ivideo, 0x43);
5613                        SiS_SetReg(SISSR, 0x18, 0x00);
5614                        if((ivideo->chip == XGI_20) ||
5615                           (ivideo->revision_id == 2)) {
5616                                SiS_SetReg(SISSR, 0x19, 0x40);
5617                        } else {
5618                                SiS_SetReg(SISSR, 0x19, 0x20);
5619                        }
5620                } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5621                        /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5622                }
5623                SiS_SetReg(SISSR, 0x16, 0x00);
5624                SiS_SetReg(SISSR, 0x16, 0x80);
5625                sisfb_post_xgi_delay(ivideo, 4);
5626                v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5627                if(ivideo->haveXGIROM) {
5628                        v1 = bios[0xf0];
5629                        index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5630                        v2 = bios[index];
5631                        v3 = bios[index + 1];
5632                        v4 = bios[index + 2];
5633                        v5 = bios[index + 3];
5634                }
5635                SiS_SetReg(SISSR, 0x18, v1);
5636                SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5637                SiS_SetReg(SISSR, 0x16, v2);
5638                SiS_SetReg(SISSR, 0x16, v3);
5639                sisfb_post_xgi_delay(ivideo, 0x43);
5640                SiS_SetReg(SISSR, 0x1b, 0x03);
5641                sisfb_post_xgi_delay(ivideo, 0x22);
5642                SiS_SetReg(SISSR, 0x18, v1);
5643                SiS_SetReg(SISSR, 0x19, 0x00);
5644                SiS_SetReg(SISSR, 0x16, v4);
5645                SiS_SetReg(SISSR, 0x16, v5);
5646                SiS_SetReg(SISSR, 0x1b, 0x00);
5647                break;
5648        case 1:
5649                sisfb_post_xgi_ddr2(ivideo, regb);
5650                break;
5651        default:
5652                sisfb_post_xgi_setclocks(ivideo, regb);
5653                if((ivideo->chip == XGI_40) &&
5654                   ((ivideo->revision_id == 1) ||
5655                    (ivideo->revision_id == 2))) {
5656                        SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5657                        SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5658                        SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5659                } else {
5660                        SiS_SetReg(SISCR, 0x82, 0x88);
5661                        SiS_SetReg(SISCR, 0x86, 0x00);
5662                        reg = SiS_GetReg(SISCR, 0x86);
5663                        SiS_SetReg(SISCR, 0x86, 0x88);
5664                        SiS_SetReg(SISCR, 0x82, 0x77);
5665                        SiS_SetReg(SISCR, 0x85, 0x00);
5666                        reg = SiS_GetReg(SISCR, 0x85);
5667                        SiS_SetReg(SISCR, 0x85, 0x88);
5668                        reg = SiS_GetReg(SISCR, 0x85);
5669                        v1 = cs160[regb]; v2 = cs158[regb];
5670                        if(ivideo->haveXGIROM) {
5671                                v1 = bios[regb + 0x160];
5672                                v2 = bios[regb + 0x158];
5673                        }
5674                        SiS_SetReg(SISCR, 0x85, v1);
5675                        SiS_SetReg(SISCR, 0x82, v2);
5676                }
5677                if(ivideo->chip == XGI_40) {
5678                        SiS_SetReg(SISCR, 0x97, 0x11);
5679                }
5680                if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5681                        SiS_SetReg(SISCR, 0x98, 0x01);
5682                } else {
5683                        SiS_SetReg(SISCR, 0x98, 0x03);
5684                }
5685                SiS_SetReg(SISCR, 0x9a, 0x02);
5686
5687                if(ivideo->chip == XGI_40) {
5688                        SiS_SetReg(SISSR, 0x18, 0x01);
5689                } else {
5690                        SiS_SetReg(SISSR, 0x18, 0x00);
5691                }
5692                SiS_SetReg(SISSR, 0x19, 0x40);
5693                SiS_SetReg(SISSR, 0x16, 0x00);
5694                SiS_SetReg(SISSR, 0x16, 0x80);
5695                if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5696                        sisfb_post_xgi_delay(ivideo, 0x43);
5697                        sisfb_post_xgi_delay(ivideo, 0x43);
5698                        sisfb_post_xgi_delay(ivideo, 0x43);
5699                        SiS_SetReg(SISSR, 0x18, 0x00);
5700                        SiS_SetReg(SISSR, 0x19, 0x40);
5701                        SiS_SetReg(SISSR, 0x16, 0x00);
5702                        SiS_SetReg(SISSR, 0x16, 0x80);
5703                }
5704                sisfb_post_xgi_delay(ivideo, 4);
5705                v1 = 0x31;
5706                if(ivideo->haveXGIROM) {
5707                        v1 = bios[0xf0];
5708                }
5709                SiS_SetReg(SISSR, 0x18, v1);
5710                SiS_SetReg(SISSR, 0x19, 0x01);
5711                if(ivideo->chip == XGI_40) {
5712                        SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5713                        SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5714                } else {
5715                        SiS_SetReg(SISSR, 0x16, 0x05);
5716                        SiS_SetReg(SISSR, 0x16, 0x85);
5717                }
5718                sisfb_post_xgi_delay(ivideo, 0x43);
5719                if(ivideo->chip == XGI_40) {
5720                        SiS_SetReg(SISSR, 0x1b, 0x01);
5721                } else {
5722                        SiS_SetReg(SISSR, 0x1b, 0x03);
5723                }
5724                sisfb_post_xgi_delay(ivideo, 0x22);
5725                SiS_SetReg(SISSR, 0x18, v1);
5726                SiS_SetReg(SISSR, 0x19, 0x00);
5727                if(ivideo->chip == XGI_40) {
5728                        SiS_SetReg(SISSR, 0x16, bios[0x540]);
5729                        SiS_SetReg(SISSR, 0x16, bios[0x541]);
5730                } else {
5731                        SiS_SetReg(SISSR, 0x16, 0x05);
5732                        SiS_SetReg(SISSR, 0x16, 0x85);
5733                }
5734                SiS_SetReg(SISSR, 0x1b, 0x00);
5735        }
5736
5737        regb = 0;       /* ! */
5738        v1 = 0x03;
5739        if(ivideo->haveXGIROM) {
5740                v1 = bios[0x110 + regb];
5741        }
5742        SiS_SetReg(SISSR, 0x1b, v1);
5743
5744        /* RAM size */
5745        v1 = 0x00; v2 = 0x00;
5746        if(ivideo->haveXGIROM) {
5747                v1 = bios[0x62];
5748                v2 = bios[0x63];
5749        }
5750        regb = 0;       /* ! */
5751        regd = 1 << regb;
5752        if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5753
5754                SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5755                SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5756
5757        } else {
5758                int err;
5759
5760                /* Set default mode, don't clear screen */
5761                ivideo->SiS_Pr.SiS_UseOEM = false;
5762                SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5763                SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5764                ivideo->curFSTN = ivideo->curDSTN = 0;
5765                ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5766                SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5767
5768                SiS_SetReg(SISSR, 0x05, 0x86);
5769
5770                /* Disable read-cache */
5771                SiS_SetRegAND(SISSR, 0x21, 0xdf);
5772                err = sisfb_post_xgi_ramsize(ivideo);
5773                /* Enable read-cache */
5774                SiS_SetRegOR(SISSR, 0x21, 0x20);
5775
5776                if (err) {
5777                        dev_err(&pdev->dev,
5778                                "%s: RAM size detection failed: %d\n",
5779                                __func__, err);
5780                        return 0;
5781                }
5782        }
5783
5784#if 0
5785        printk(KERN_DEBUG "-----------------\n");
5786        for(i = 0; i < 0xff; i++) {
5787                reg = SiS_GetReg(SISCR, i);
5788                printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5789        }
5790        for(i = 0; i < 0x40; i++) {
5791                reg = SiS_GetReg(SISSR, i);
5792                printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5793        }
5794        printk(KERN_DEBUG "-----------------\n");
5795#endif
5796
5797        /* Sense CRT1 */
5798        if(ivideo->chip == XGI_20) {
5799                SiS_SetRegOR(SISCR, 0x32, 0x20);
5800        } else {
5801                reg = SiS_GetReg(SISPART4, 0x00);
5802                if((reg == 1) || (reg == 2)) {
5803                        sisfb_sense_crt1(ivideo);
5804                } else {
5805                        SiS_SetRegOR(SISCR, 0x32, 0x20);
5806                }
5807        }
5808
5809        /* Set default mode, don't clear screen */
5810        ivideo->SiS_Pr.SiS_UseOEM = false;
5811        SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5812        SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5813        ivideo->curFSTN = ivideo->curDSTN = 0;
5814        SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5815
5816        SiS_SetReg(SISSR, 0x05, 0x86);
5817
5818        /* Display off */
5819        SiS_SetRegOR(SISSR, 0x01, 0x20);
5820
5821        /* Save mode number in CR34 */
5822        SiS_SetReg(SISCR, 0x34, 0x2e);
5823
5824        /* Let everyone know what the current mode is */
5825        ivideo->modeprechange = 0x2e;
5826
5827        if(ivideo->chip == XGI_40) {
5828                reg = SiS_GetReg(SISCR, 0xca);
5829                v1 = SiS_GetReg(SISCR, 0xcc);
5830                if((reg & 0x10) && (!(v1 & 0x04))) {
5831                        printk(KERN_ERR
5832                                "sisfb: Please connect power to the card.\n");
5833                        return 0;
5834                }
5835        }
5836
5837        return 1;
5838}
5839#endif
5840
5841static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5842{
5843        struct sisfb_chip_info  *chipinfo = &sisfb_chip_info[ent->driver_data];
5844        struct sis_video_info   *ivideo = NULL;
5845        struct fb_info          *sis_fb_info = NULL;
5846        u16 reg16;
5847        u8  reg;
5848        int i, ret;
5849
5850        if(sisfb_off)
5851                return -ENXIO;
5852
5853        sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5854        if(!sis_fb_info)
5855                return -ENOMEM;
5856
5857        ivideo = (struct sis_video_info *)sis_fb_info->par;
5858        ivideo->memyselfandi = sis_fb_info;
5859
5860        ivideo->sisfb_id = SISFB_ID;
5861
5862        if(card_list == NULL) {
5863                ivideo->cardnumber = 0;
5864        } else {
5865                struct sis_video_info *countvideo = card_list;
5866                ivideo->cardnumber = 1;
5867                while((countvideo = countvideo->next) != NULL)
5868                        ivideo->cardnumber++;
5869        }
5870
5871        strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5872
5873        ivideo->warncount = 0;
5874        ivideo->chip_id = pdev->device;
5875        ivideo->chip_vendor = pdev->vendor;
5876        ivideo->revision_id = pdev->revision;
5877        ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5878        pci_read_config_word(pdev, PCI_COMMAND, &reg16);
5879        ivideo->sisvga_enabled = reg16 & 0x01;
5880        ivideo->pcibus = pdev->bus->number;
5881        ivideo->pcislot = PCI_SLOT(pdev->devfn);
5882        ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5883        ivideo->subsysvendor = pdev->subsystem_vendor;
5884        ivideo->subsysdevice = pdev->subsystem_device;
5885
5886#ifndef MODULE
5887        if(sisfb_mode_idx == -1) {
5888                sisfb_get_vga_mode_from_kernel();
5889        }
5890#endif
5891
5892        ivideo->chip = chipinfo->chip;
5893        ivideo->chip_real_id = chipinfo->chip;
5894        ivideo->sisvga_engine = chipinfo->vgaengine;
5895        ivideo->hwcursor_size = chipinfo->hwcursor_size;
5896        ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5897        ivideo->mni = chipinfo->mni;
5898
5899        ivideo->detectedpdc  = 0xff;
5900        ivideo->detectedpdca = 0xff;
5901        ivideo->detectedlcda = 0xff;
5902
5903        ivideo->sisfb_thismonitor.datavalid = false;
5904
5905        ivideo->current_base = 0;
5906
5907        ivideo->engineok = 0;
5908
5909        ivideo->sisfb_was_boot_device = 0;
5910
5911        if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5912                if(ivideo->sisvga_enabled)
5913                        ivideo->sisfb_was_boot_device = 1;
5914                else {
5915                        printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5916                                "but marked as boot video device ???\n");
5917                        printk(KERN_DEBUG "sisfb: I will not accept this "
5918                                "as the primary VGA device\n");
5919                }
5920        }
5921
5922        ivideo->sisfb_parm_mem = sisfb_parm_mem;
5923        ivideo->sisfb_accel = sisfb_accel;
5924        ivideo->sisfb_ypan = sisfb_ypan;
5925        ivideo->sisfb_max = sisfb_max;
5926        ivideo->sisfb_userom = sisfb_userom;
5927        ivideo->sisfb_useoem = sisfb_useoem;
5928        ivideo->sisfb_mode_idx = sisfb_mode_idx;
5929        ivideo->sisfb_parm_rate = sisfb_parm_rate;
5930        ivideo->sisfb_crt1off = sisfb_crt1off;
5931        ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5932        ivideo->sisfb_crt2type = sisfb_crt2type;
5933        ivideo->sisfb_crt2flags = sisfb_crt2flags;
5934        /* pdc(a), scalelcd, special timing, lvdshl handled below */
5935        ivideo->sisfb_dstn = sisfb_dstn;
5936        ivideo->sisfb_fstn = sisfb_fstn;
5937        ivideo->sisfb_tvplug = sisfb_tvplug;
5938        ivideo->sisfb_tvstd = sisfb_tvstd;
5939        ivideo->tvxpos = sisfb_tvxposoffset;
5940        ivideo->tvypos = sisfb_tvyposoffset;
5941        ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5942        ivideo->refresh_rate = 0;
5943        if(ivideo->sisfb_parm_rate != -1) {
5944                ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5945        }
5946
5947        ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5948        ivideo->SiS_Pr.CenterScreen = -1;
5949        ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5950        ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5951
5952        ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5953        ivideo->SiS_Pr.SiS_CHOverScan = -1;
5954        ivideo->SiS_Pr.SiS_ChSW = false;
5955        ivideo->SiS_Pr.SiS_UseLCDA = false;
5956        ivideo->SiS_Pr.HaveEMI = false;
5957        ivideo->SiS_Pr.HaveEMILCD = false;
5958        ivideo->SiS_Pr.OverruleEMI = false;
5959        ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5960        ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5961        ivideo->SiS_Pr.PDC  = -1;
5962        ivideo->SiS_Pr.PDCA = -1;
5963        ivideo->SiS_Pr.DDCPortMixup = false;
5964#ifdef CONFIG_FB_SIS_315
5965        if(ivideo->chip >= SIS_330) {
5966                ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5967                if(ivideo->chip >= SIS_661) {
5968                        ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5969                }
5970        }
5971#endif
5972
5973        memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5974
5975        pci_set_drvdata(pdev, ivideo);
5976
5977        /* Patch special cases */
5978        if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5979                switch(ivideo->nbridge->device) {
5980#ifdef CONFIG_FB_SIS_300
5981                case PCI_DEVICE_ID_SI_730:
5982                        ivideo->chip = SIS_730;
5983                        strcpy(ivideo->myid, "SiS 730");
5984                        break;
5985#endif
5986#ifdef CONFIG_FB_SIS_315
5987                case PCI_DEVICE_ID_SI_651:
5988                        /* ivideo->chip is ok */
5989                        strcpy(ivideo->myid, "SiS 651");
5990                        break;
5991                case PCI_DEVICE_ID_SI_740:
5992                        ivideo->chip = SIS_740;
5993                        strcpy(ivideo->myid, "SiS 740");
5994                        break;
5995                case PCI_DEVICE_ID_SI_661:
5996                        ivideo->chip = SIS_661;
5997                        strcpy(ivideo->myid, "SiS 661");
5998                        break;
5999                case PCI_DEVICE_ID_SI_741:
6000                        ivideo->chip = SIS_741;
6001                        strcpy(ivideo->myid, "SiS 741");
6002                        break;
6003                case PCI_DEVICE_ID_SI_760:
6004                        ivideo->chip = SIS_760;
6005                        strcpy(ivideo->myid, "SiS 760");
6006                        break;
6007                case PCI_DEVICE_ID_SI_761:
6008                        ivideo->chip = SIS_761;
6009                        strcpy(ivideo->myid, "SiS 761");
6010                        break;
6011#endif
6012                default:
6013                        break;
6014                }
6015        }
6016
6017        ivideo->SiS_Pr.ChipType = ivideo->chip;
6018
6019        ivideo->SiS_Pr.ivideo = (void *)ivideo;
6020
6021#ifdef CONFIG_FB_SIS_315
6022        if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6023           (ivideo->SiS_Pr.ChipType == SIS_315)) {
6024                ivideo->SiS_Pr.ChipType = SIS_315H;
6025        }
6026#endif
6027
6028        if(!ivideo->sisvga_enabled) {
6029                if(pci_enable_device(pdev)) {
6030                        pci_dev_put(ivideo->nbridge);
6031                        framebuffer_release(sis_fb_info);
6032                        return -EIO;
6033                }
6034        }
6035
6036        ivideo->video_base = pci_resource_start(pdev, 0);
6037        ivideo->video_size = pci_resource_len(pdev, 0);
6038        ivideo->mmio_base  = pci_resource_start(pdev, 1);
6039        ivideo->mmio_size  = pci_resource_len(pdev, 1);
6040        ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6041        ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6042
6043        SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6044
6045#ifdef CONFIG_FB_SIS_300
6046        /* Find PCI systems for Chrontel/GPIO communication setup */
6047        if(ivideo->chip == SIS_630) {
6048                i = 0;
6049                do {
6050                        if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6051                           mychswtable[i].subsysCard   == ivideo->subsysdevice) {
6052                                ivideo->SiS_Pr.SiS_ChSW = true;
6053                                printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6054                                        "requiring Chrontel/GPIO setup\n",
6055                                        mychswtable[i].vendorName,
6056                                        mychswtable[i].cardName);
6057                                ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6058                                break;
6059                        }
6060                        i++;
6061                } while(mychswtable[i].subsysVendor != 0);
6062        }
6063#endif
6064
6065#ifdef CONFIG_FB_SIS_315
6066        if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6067                ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6068        }
6069#endif
6070
6071        SiS_SetReg(SISSR, 0x05, 0x86);
6072
6073        if( (!ivideo->sisvga_enabled)
6074#if !defined(__i386__) && !defined(__x86_64__)
6075                              || (sisfb_resetcard)
6076#endif
6077                                                   ) {
6078                for(i = 0x30; i <= 0x3f; i++) {
6079                        SiS_SetReg(SISCR, i, 0x00);
6080                }
6081        }
6082
6083        /* Find out about current video mode */
6084        ivideo->modeprechange = 0x03;
6085        reg = SiS_GetReg(SISCR, 0x34);
6086        if(reg & 0x7f) {
6087                ivideo->modeprechange = reg & 0x7f;
6088        } else if(ivideo->sisvga_enabled) {
6089#if defined(__i386__) || defined(__x86_64__)
6090                unsigned char __iomem *tt = ioremap(0x400, 0x100);
6091                if(tt) {
6092                        ivideo->modeprechange = readb(tt + 0x49);
6093                        iounmap(tt);
6094                }
6095#endif
6096        }
6097
6098        /* Search and copy ROM image */
6099        ivideo->bios_abase = NULL;
6100        ivideo->SiS_Pr.VirtualRomBase = NULL;
6101        ivideo->SiS_Pr.UseROM = false;
6102        ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6103        if(ivideo->sisfb_userom) {
6104                ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6105                ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6106                ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6107                printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6108                        ivideo->SiS_Pr.UseROM ? "" : "not ");
6109                if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6110                   ivideo->SiS_Pr.UseROM = false;
6111                   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6112                   if( (ivideo->revision_id == 2) &&
6113                       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6114                        ivideo->SiS_Pr.DDCPortMixup = true;
6115                   }
6116                }
6117        } else {
6118                printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6119        }
6120
6121        /* Find systems for special custom timing */
6122        if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6123                sisfb_detect_custom_timing(ivideo);
6124        }
6125
6126#ifdef CONFIG_FB_SIS_315
6127        if (ivideo->chip == XGI_20) {
6128                /* Check if our Z7 chip is actually Z9 */
6129                SiS_SetRegOR(SISCR, 0x4a, 0x40);        /* GPIOG EN */
6130                reg = SiS_GetReg(SISCR, 0x48);
6131                if (reg & 0x02) {                       /* GPIOG */
6132                        ivideo->chip_real_id = XGI_21;
6133                        dev_info(&pdev->dev, "Z9 detected\n");
6134                }
6135        }
6136#endif
6137
6138        /* POST card in case this has not been done by the BIOS */
6139        if( (!ivideo->sisvga_enabled)
6140#if !defined(__i386__) && !defined(__x86_64__)
6141                             || (sisfb_resetcard)
6142#endif
6143                                                 ) {
6144#ifdef CONFIG_FB_SIS_300
6145                if(ivideo->sisvga_engine == SIS_300_VGA) {
6146                        if(ivideo->chip == SIS_300) {
6147                                sisfb_post_sis300(pdev);
6148                                ivideo->sisfb_can_post = 1;
6149                        }
6150                }
6151#endif
6152
6153#ifdef CONFIG_FB_SIS_315
6154                if(ivideo->sisvga_engine == SIS_315_VGA) {
6155                        int result = 1;
6156                /*      if((ivideo->chip == SIS_315H)   ||
6157                           (ivideo->chip == SIS_315)    ||
6158                           (ivideo->chip == SIS_315PRO) ||
6159                           (ivideo->chip == SIS_330)) {
6160                                sisfb_post_sis315330(pdev);
6161                        } else */ if(ivideo->chip == XGI_20) {
6162                                result = sisfb_post_xgi(pdev);
6163                                ivideo->sisfb_can_post = 1;
6164                        } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6165                                result = sisfb_post_xgi(pdev);
6166                                ivideo->sisfb_can_post = 1;
6167                        } else {
6168                                printk(KERN_INFO "sisfb: Card is not "
6169                                        "POSTed and sisfb can't do this either.\n");
6170                        }
6171                        if(!result) {
6172                                printk(KERN_ERR "sisfb: Failed to POST card\n");
6173                                ret = -ENODEV;
6174                                goto error_3;
6175                        }
6176                }
6177#endif
6178        }
6179
6180        ivideo->sisfb_card_posted = 1;
6181
6182        /* Find out about RAM size */
6183        if(sisfb_get_dram_size(ivideo)) {
6184                printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6185                ret = -ENODEV;
6186                goto error_3;
6187        }
6188
6189
6190        /* Enable PCI addressing and MMIO */
6191        if((ivideo->sisfb_mode_idx < 0) ||
6192           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6193                /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
6194                SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6195                /* Enable 2D accelerator engine */
6196                SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6197        }
6198
6199        if(sisfb_pdc != 0xff) {
6200                if(ivideo->sisvga_engine == SIS_300_VGA)
6201                        sisfb_pdc &= 0x3c;
6202                else
6203                        sisfb_pdc &= 0x1f;
6204                ivideo->SiS_Pr.PDC = sisfb_pdc;
6205        }
6206#ifdef CONFIG_FB_SIS_315
6207        if(ivideo->sisvga_engine == SIS_315_VGA) {
6208                if(sisfb_pdca != 0xff)
6209                        ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6210        }
6211#endif
6212
6213        if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6214                printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6215                                (int)(ivideo->video_size >> 20));
6216                printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6217                ret = -ENODEV;
6218                goto error_3;
6219        }
6220
6221        if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6222                printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6223                ret = -ENODEV;
6224                goto error_2;
6225        }
6226
6227        ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6228        ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6229        if(!ivideo->video_vbase) {
6230                printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6231                ret = -ENODEV;
6232                goto error_1;
6233        }
6234
6235        ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6236        if(!ivideo->mmio_vbase) {
6237                printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6238                ret = -ENODEV;
6239error_0:        iounmap(ivideo->video_vbase);
6240error_1:        release_mem_region(ivideo->video_base, ivideo->video_size);
6241error_2:        release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6242error_3:        vfree(ivideo->bios_abase);
6243                pci_dev_put(ivideo->lpcdev);
6244                pci_dev_put(ivideo->nbridge);
6245                if(!ivideo->sisvga_enabled)
6246                        pci_disable_device(pdev);
6247                framebuffer_release(sis_fb_info);
6248                return ret;
6249        }
6250
6251        printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6252                ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6253
6254        if(ivideo->video_offset) {
6255                printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6256                        ivideo->video_offset / 1024);
6257        }
6258
6259        printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6260                ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6261
6262
6263        /* Determine the size of the command queue */
6264        if(ivideo->sisvga_engine == SIS_300_VGA) {
6265                ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6266        } else {
6267                if(ivideo->chip == XGI_20) {
6268                        ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6269                } else {
6270                        ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6271                }
6272        }
6273
6274        /* Engines are no longer initialized here; this is
6275         * now done after the first mode-switch (if the
6276         * submitted var has its acceleration flags set).
6277         */
6278
6279        /* Calculate the base of the (unused) hw cursor */
6280        ivideo->hwcursor_vbase = ivideo->video_vbase
6281                                 + ivideo->video_size
6282                                 - ivideo->cmdQueueSize
6283                                 - ivideo->hwcursor_size;
6284        ivideo->caps |= HW_CURSOR_CAP;
6285
6286        /* Initialize offscreen memory manager */
6287        if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6288                printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6289        }
6290
6291        /* Used for clearing the screen only, therefore respect our mem limit */
6292        ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6293        ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6294
6295        ivideo->vbflags = 0;
6296        ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6297        ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
6298        ivideo->defmodeidx    = DEFAULT_MODE;
6299
6300        ivideo->newrom = 0;
6301        if(ivideo->chip < XGI_20) {
6302                if(ivideo->bios_abase) {
6303                        ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6304                }
6305        }
6306
6307        if((ivideo->sisfb_mode_idx < 0) ||
6308           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6309
6310                sisfb_sense_crt1(ivideo);
6311
6312                sisfb_get_VB_type(ivideo);
6313
6314                if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6315                        sisfb_detect_VB_connect(ivideo);
6316                }
6317
6318                ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6319
6320                /* Decide on which CRT2 device to use */
6321                if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6322                        if(ivideo->sisfb_crt2type != -1) {
6323                                if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6324                                   (ivideo->vbflags & CRT2_LCD)) {
6325                                        ivideo->currentvbflags |= CRT2_LCD;
6326                                } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6327                                        ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6328                                }
6329                        } else {
6330                                /* Chrontel 700x TV detection often unreliable, therefore
6331                                 * use a different default order on such machines
6332                                 */
6333                                if((ivideo->sisvga_engine == SIS_300_VGA) &&
6334                                   (ivideo->vbflags2 & VB2_CHRONTEL)) {
6335                                        if(ivideo->vbflags & CRT2_LCD)
6336                                                ivideo->currentvbflags |= CRT2_LCD;
6337                                        else if(ivideo->vbflags & CRT2_TV)
6338                                                ivideo->currentvbflags |= CRT2_TV;
6339                                        else if(ivideo->vbflags & CRT2_VGA)
6340                                                ivideo->currentvbflags |= CRT2_VGA;
6341                                } else {
6342                                        if(ivideo->vbflags & CRT2_TV)
6343                                                ivideo->currentvbflags |= CRT2_TV;
6344                                        else if(ivideo->vbflags & CRT2_LCD)
6345                                                ivideo->currentvbflags |= CRT2_LCD;
6346                                        else if(ivideo->vbflags & CRT2_VGA)
6347                                                ivideo->currentvbflags |= CRT2_VGA;
6348                                }
6349                        }
6350                }
6351
6352                if(ivideo->vbflags & CRT2_LCD) {
6353                        sisfb_detect_lcd_type(ivideo);
6354                }
6355
6356                sisfb_save_pdc_emi(ivideo);
6357
6358                if(!ivideo->sisfb_crt1off) {
6359                        sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6360                } else {
6361                        if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6362                           (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6363                                sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6364                        }
6365                }
6366
6367                if(ivideo->sisfb_mode_idx >= 0) {
6368                        int bu = ivideo->sisfb_mode_idx;
6369                        ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6370                                        ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6371                        if(bu != ivideo->sisfb_mode_idx) {
6372                                printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6373                                        sisbios_mode[bu].xres,
6374                                        sisbios_mode[bu].yres,
6375                                        sisbios_mode[bu].bpp);
6376                        }
6377                }
6378
6379                if(ivideo->sisfb_mode_idx < 0) {
6380                        switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6381                           case CRT2_LCD:
6382                                ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6383                                break;
6384                           case CRT2_TV:
6385                                ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6386                                break;
6387                           default:
6388                                ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6389                                break;
6390                        }
6391                }
6392
6393                ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6394
6395                if(ivideo->refresh_rate != 0) {
6396                        sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6397                                                ivideo->sisfb_mode_idx);
6398                }
6399
6400                if(ivideo->rate_idx == 0) {
6401                        ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6402                        ivideo->refresh_rate = 60;
6403                }
6404
6405                if(ivideo->sisfb_thismonitor.datavalid) {
6406                        if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6407                                                ivideo->sisfb_mode_idx,
6408                                                ivideo->rate_idx,
6409                                                ivideo->refresh_rate)) {
6410                                printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6411                                                        "exceeds monitor specs!\n");
6412                        }
6413                }
6414
6415                ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6416                ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6417                ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6418
6419                sisfb_set_vparms(ivideo);
6420
6421                printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6422                        ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6423                        ivideo->refresh_rate);
6424
6425                /* Set up the default var according to chosen default display mode */
6426                ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6427                ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6428                ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6429
6430                sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6431
6432                ivideo->default_var.pixclock = (u32) (1000000000 /
6433                        sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6434
6435                if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6436                                                ivideo->rate_idx, &ivideo->default_var)) {
6437                        if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6438                                ivideo->default_var.pixclock <<= 1;
6439                        }
6440                }
6441
6442                if(ivideo->sisfb_ypan) {
6443                        /* Maximize regardless of sisfb_max at startup */
6444                        ivideo->default_var.yres_virtual =
6445                                sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6446                        if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6447                                ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6448                        }
6449                }
6450
6451                sisfb_calc_pitch(ivideo, &ivideo->default_var);
6452
6453                ivideo->accel = 0;
6454                if(ivideo->sisfb_accel) {
6455                        ivideo->accel = -1;
6456#ifdef STUPID_ACCELF_TEXT_SHIT
6457                        ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6458#endif
6459                }
6460                sisfb_initaccel(ivideo);
6461
6462#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6463                sis_fb_info->flags = FBINFO_DEFAULT             |
6464                                     FBINFO_HWACCEL_YPAN        |
6465                                     FBINFO_HWACCEL_XPAN        |
6466                                     FBINFO_HWACCEL_COPYAREA    |
6467                                     FBINFO_HWACCEL_FILLRECT    |
6468                                     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6469#else
6470                sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6471#endif
6472                sis_fb_info->var = ivideo->default_var;
6473                sis_fb_info->fix = ivideo->sisfb_fix;
6474                sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6475                sis_fb_info->fbops = &sisfb_ops;
6476                sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6477
6478                fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6479
6480                printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6481
6482                ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6483                                                     ivideo->video_size);
6484                if(register_framebuffer(sis_fb_info) < 0) {
6485                        printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6486                        ret = -EINVAL;
6487                        iounmap(ivideo->mmio_vbase);
6488                        goto error_0;
6489                }
6490
6491                ivideo->registered = 1;
6492
6493                /* Enlist us */
6494                ivideo->next = card_list;
6495                card_list = ivideo;
6496
6497                printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6498                        ivideo->sisfb_accel ? "enabled" : "disabled",
6499                        ivideo->sisfb_ypan  ?
6500                                (ivideo->sisfb_max ? "enabled (auto-max)" :
6501                                                "enabled (no auto-max)") :
6502                                                                        "disabled");
6503
6504
6505                fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6506                        ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6507
6508                printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6509
6510        }       /* if mode = "none" */
6511
6512        return 0;
6513}
6514
6515/*****************************************************/
6516/*                PCI DEVICE HANDLING                */
6517/*****************************************************/
6518
6519static void sisfb_remove(struct pci_dev *pdev)
6520{
6521        struct sis_video_info   *ivideo = pci_get_drvdata(pdev);
6522        struct fb_info          *sis_fb_info = ivideo->memyselfandi;
6523        int                     registered = ivideo->registered;
6524        int                     modechanged = ivideo->modechanged;
6525
6526        /* Unmap */
6527        iounmap(ivideo->mmio_vbase);
6528        iounmap(ivideo->video_vbase);
6529
6530        /* Release mem regions */
6531        release_mem_region(ivideo->video_base, ivideo->video_size);
6532        release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6533
6534        vfree(ivideo->bios_abase);
6535
6536        pci_dev_put(ivideo->lpcdev);
6537
6538        pci_dev_put(ivideo->nbridge);
6539
6540        arch_phys_wc_del(ivideo->wc_cookie);
6541
6542        /* If device was disabled when starting, disable
6543         * it when quitting.
6544         */
6545        if(!ivideo->sisvga_enabled)
6546                pci_disable_device(pdev);
6547
6548        /* Unregister the framebuffer */
6549        if(ivideo->registered) {
6550                unregister_framebuffer(sis_fb_info);
6551                framebuffer_release(sis_fb_info);
6552        }
6553
6554        /* OK, our ivideo is gone for good from here. */
6555
6556        /* TODO: Restore the initial mode
6557         * This sounds easy but is as good as impossible
6558         * on many machines with SiS chip and video bridge
6559         * since text modes are always set up differently
6560         * from machine to machine. Depends on the type
6561         * of integration between chipset and bridge.
6562         */
6563        if(registered && modechanged)
6564                printk(KERN_INFO
6565                        "sisfb: Restoring of text mode not supported yet\n");
6566};
6567
6568static struct pci_driver sisfb_driver = {
6569        .name           = "sisfb",
6570        .id_table       = sisfb_pci_table,
6571        .probe          = sisfb_probe,
6572        .remove         = sisfb_remove,
6573};
6574
6575static int __init sisfb_init(void)
6576{
6577#ifndef MODULE
6578        char *options = NULL;
6579
6580        if(fb_get_options("sisfb", &options))
6581                return -ENODEV;
6582
6583        sisfb_setup(options);
6584#endif
6585        return pci_register_driver(&sisfb_driver);
6586}
6587
6588#ifndef MODULE
6589module_init(sisfb_init);
6590#endif
6591
6592/*****************************************************/
6593/*                      MODULE                       */
6594/*****************************************************/
6595
6596#ifdef MODULE
6597
6598static char             *mode = NULL;
6599static int              vesa = -1;
6600static unsigned int     rate = 0;
6601static unsigned int     crt1off = 1;
6602static unsigned int     mem = 0;
6603static char             *forcecrt2type = NULL;
6604static int              forcecrt1 = -1;
6605static int              pdc = -1;
6606static int              pdc1 = -1;
6607static int              noaccel = -1;
6608static int              noypan  = -1;
6609static int              nomax = -1;
6610static int              userom = -1;
6611static int              useoem = -1;
6612static char             *tvstandard = NULL;
6613static int              nocrt2rate = 0;
6614static int              scalelcd = -1;
6615static char             *specialtiming = NULL;
6616static int              lvdshl = -1;
6617static int              tvxposoffset = 0, tvyposoffset = 0;
6618#if !defined(__i386__) && !defined(__x86_64__)
6619static int              resetcard = 0;
6620static int              videoram = 0;
6621#endif
6622
6623static int __init sisfb_init_module(void)
6624{
6625        sisfb_setdefaultparms();
6626
6627        if(rate)
6628                sisfb_parm_rate = rate;
6629
6630        if((scalelcd == 0) || (scalelcd == 1))
6631                sisfb_scalelcd = scalelcd ^ 1;
6632
6633        /* Need to check crt2 type first for fstn/dstn */
6634
6635        if(forcecrt2type)
6636                sisfb_search_crt2type(forcecrt2type);
6637
6638        if(tvstandard)
6639                sisfb_search_tvstd(tvstandard);
6640
6641        if(mode)
6642                sisfb_search_mode(mode, false);
6643        else if(vesa != -1)
6644                sisfb_search_vesamode(vesa, false);
6645
6646        sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6647
6648        sisfb_forcecrt1 = forcecrt1;
6649        if(forcecrt1 == 1)
6650                sisfb_crt1off = 0;
6651        else if(forcecrt1 == 0)
6652                sisfb_crt1off = 1;
6653
6654        if(noaccel == 1)
6655                sisfb_accel = 0;
6656        else if(noaccel == 0)
6657                sisfb_accel = 1;
6658
6659        if(noypan == 1)
6660                sisfb_ypan = 0;
6661        else if(noypan == 0)
6662                sisfb_ypan = 1;
6663
6664        if(nomax == 1)
6665                sisfb_max = 0;
6666        else if(nomax == 0)
6667                sisfb_max = 1;
6668
6669        if(mem)
6670                sisfb_parm_mem = mem;
6671
6672        if(userom != -1)
6673                sisfb_userom = userom;
6674
6675        if(useoem != -1)
6676                sisfb_useoem = useoem;
6677
6678        if(pdc != -1)
6679                sisfb_pdc  = (pdc  & 0x7f);
6680
6681        if(pdc1 != -1)
6682                sisfb_pdca = (pdc1 & 0x1f);
6683
6684        sisfb_nocrt2rate = nocrt2rate;
6685
6686        if(specialtiming)
6687                sisfb_search_specialtiming(specialtiming);
6688
6689        if((lvdshl >= 0) && (lvdshl <= 3))
6690                sisfb_lvdshl = lvdshl;
6691
6692        sisfb_tvxposoffset = tvxposoffset;
6693        sisfb_tvyposoffset = tvyposoffset;
6694
6695#if !defined(__i386__) && !defined(__x86_64__)
6696        sisfb_resetcard = (resetcard) ? 1 : 0;
6697        if(videoram)
6698                sisfb_videoram = videoram;
6699#endif
6700
6701        return sisfb_init();
6702}
6703
6704static void __exit sisfb_remove_module(void)
6705{
6706        pci_unregister_driver(&sisfb_driver);
6707        printk(KERN_DEBUG "sisfb: Module unloaded\n");
6708}
6709
6710module_init(sisfb_init_module);
6711module_exit(sisfb_remove_module);
6712
6713MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6714MODULE_LICENSE("GPL");
6715MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6716
6717module_param(mem, int, 0);
6718module_param(noaccel, int, 0);
6719module_param(noypan, int, 0);
6720module_param(nomax, int, 0);
6721module_param(userom, int, 0);
6722module_param(useoem, int, 0);
6723module_param(mode, charp, 0);
6724module_param(vesa, int, 0);
6725module_param(rate, int, 0);
6726module_param(forcecrt1, int, 0);
6727module_param(forcecrt2type, charp, 0);
6728module_param(scalelcd, int, 0);
6729module_param(pdc, int, 0);
6730module_param(pdc1, int, 0);
6731module_param(specialtiming, charp, 0);
6732module_param(lvdshl, int, 0);
6733module_param(tvstandard, charp, 0);
6734module_param(tvxposoffset, int, 0);
6735module_param(tvyposoffset, int, 0);
6736module_param(nocrt2rate, int, 0);
6737#if !defined(__i386__) && !defined(__x86_64__)
6738module_param(resetcard, int, 0);
6739module_param(videoram, int, 0);
6740#endif
6741
6742MODULE_PARM_DESC(mem,
6743        "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6744          "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6745          "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6746          "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6747          "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6748          "The value is to be specified without 'KB'.\n");
6749
6750MODULE_PARM_DESC(noaccel,
6751        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6752          "(default: 0)\n");
6753
6754MODULE_PARM_DESC(noypan,
6755        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6756          "will be performed by redrawing the screen. (default: 0)\n");
6757
6758MODULE_PARM_DESC(nomax,
6759        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6760          "memory for the virtual screen in order to optimize scrolling performance. If\n"
6761          "this is set to anything other than 0, sisfb will not do this and thereby \n"
6762          "enable the user to positively specify a virtual Y size of the screen using\n"
6763          "fbset. (default: 0)\n");
6764
6765MODULE_PARM_DESC(mode,
6766        "\nSelects the desired default display mode in the format XxYxDepth,\n"
6767         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6768         "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6769         "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6770
6771MODULE_PARM_DESC(vesa,
6772        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6773         "0x117 (default: 0x0103)\n");
6774
6775MODULE_PARM_DESC(rate,
6776        "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6777          "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6778          "will be ignored (default: 60)\n");
6779
6780MODULE_PARM_DESC(forcecrt1,
6781        "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6782          "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6783          "0=CRT1 OFF) (default: [autodetected])\n");
6784
6785MODULE_PARM_DESC(forcecrt2type,
6786        "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6787          "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6788          "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6789          "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6790          "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6791          "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6792          "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6793          "depends on the very hardware in use. (default: [autodetected])\n");
6794
6795MODULE_PARM_DESC(scalelcd,
6796        "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6797          "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6798          "show black bars around the image, TMDS panels will probably do the scaling\n"
6799          "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6800
6801MODULE_PARM_DESC(pdc,
6802        "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6803          "should detect this correctly in most cases; however, sometimes this is not\n"
6804          "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6805          "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6806          "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6807          "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6808
6809#ifdef CONFIG_FB_SIS_315
6810MODULE_PARM_DESC(pdc1,
6811        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6812          "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6813          "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6814          "implemented yet.\n");
6815#endif
6816
6817MODULE_PARM_DESC(specialtiming,
6818        "\nPlease refer to documentation for more information on this option.\n");
6819
6820MODULE_PARM_DESC(lvdshl,
6821        "\nPlease refer to documentation for more information on this option.\n");
6822
6823MODULE_PARM_DESC(tvstandard,
6824        "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6825          "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6826
6827MODULE_PARM_DESC(tvxposoffset,
6828        "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6829          "Default: 0\n");
6830
6831MODULE_PARM_DESC(tvyposoffset,
6832        "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6833          "Default: 0\n");
6834
6835MODULE_PARM_DESC(nocrt2rate,
6836        "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6837          "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6838
6839#if !defined(__i386__) && !defined(__x86_64__)
6840#ifdef CONFIG_FB_SIS_300
6841MODULE_PARM_DESC(resetcard,
6842        "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6843          "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6844          "currently). Default: 0\n");
6845
6846MODULE_PARM_DESC(videoram,
6847        "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6848          "some non-x86 architectures where the memory auto detection fails. Only\n"
6849          "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6850#endif
6851#endif
6852
6853#endif     /*  /MODULE  */
6854
6855/* _GPL only for new symbols. */
6856EXPORT_SYMBOL(sis_malloc);
6857EXPORT_SYMBOL(sis_free);
6858EXPORT_SYMBOL_GPL(sis_malloc_new);
6859EXPORT_SYMBOL_GPL(sis_free_new);
6860
6861
6862
6863