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                fallthrough;
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                fallthrough;
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                fallthrough;
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                fallthrough;
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 const 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 v1;
5033        u8 v2;
5034        u8 v3;
5035
5036        SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5037        SiS_SetReg(SISCR, 0x82, 0x77);
5038        SiS_SetReg(SISCR, 0x86, 0x00);
5039        SiS_GetReg(SISCR, 0x86);
5040        SiS_SetReg(SISCR, 0x86, 0x88);
5041        SiS_GetReg(SISCR, 0x86);
5042        v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5043        if (ivideo->haveXGIROM) {
5044                v1 = bios[regb + 0x168];
5045                v2 = bios[regb + 0x160];
5046                v3 = bios[regb + 0x158];
5047        }
5048        SiS_SetReg(SISCR, 0x86, v1);
5049        SiS_SetReg(SISCR, 0x82, 0x77);
5050        SiS_SetReg(SISCR, 0x85, 0x00);
5051        SiS_GetReg(SISCR, 0x85);
5052        SiS_SetReg(SISCR, 0x85, 0x88);
5053        SiS_GetReg(SISCR, 0x85);
5054        SiS_SetReg(SISCR, 0x85, v2);
5055        SiS_SetReg(SISCR, 0x82, v3);
5056        SiS_SetReg(SISCR, 0x98, 0x01);
5057        SiS_SetReg(SISCR, 0x9a, 0x02);
5058        if (sisfb_xgi_is21(ivideo))
5059                sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5060        else
5061                sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5062}
5063
5064static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5065{
5066        unsigned char *bios = ivideo->bios_abase;
5067        u8 ramtype;
5068        u8 reg;
5069        u8 v1;
5070
5071        ramtype = 0x00; v1 = 0x10;
5072        if (ivideo->haveXGIROM) {
5073                ramtype = bios[0x62];
5074                v1 = bios[0x1d2];
5075        }
5076        if (!(ramtype & 0x80)) {
5077                if (sisfb_xgi_is21(ivideo)) {
5078                        SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5079                        SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
5080                        reg = SiS_GetReg(SISCR, 0x48);
5081                        SiS_SetRegOR(SISCR, 0xb4, 0x02);
5082                        ramtype = reg & 0x01;             /* GPIOH */
5083                } else if (ivideo->chip == XGI_20) {
5084                        SiS_SetReg(SISCR, 0x97, v1);
5085                        reg = SiS_GetReg(SISCR, 0x97);
5086                        if (reg & 0x10) {
5087                                ramtype = (reg & 0x01) << 1;
5088                        }
5089                } else {
5090                        reg = SiS_GetReg(SISSR, 0x39);
5091                        ramtype = reg & 0x02;
5092                        if (!(ramtype)) {
5093                                reg = SiS_GetReg(SISSR, 0x3a);
5094                                ramtype = (reg >> 1) & 0x01;
5095                        }
5096                }
5097        }
5098        ramtype &= 0x07;
5099
5100        return ramtype;
5101}
5102
5103static int sisfb_post_xgi(struct pci_dev *pdev)
5104{
5105        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5106        unsigned char *bios = ivideo->bios_abase;
5107        struct pci_dev *mypdev = NULL;
5108        const u8 *ptr, *ptr2;
5109        u8 v1, v2, v3, v4, v5, reg, ramtype;
5110        u32 rega, regb, regd;
5111        int i, j, k, index;
5112        static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5113        static const u8 cs76[2] = { 0xa3, 0xfb };
5114        static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5115        static const u8 cs158[8] = {
5116                0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5117        };
5118        static const u8 cs160[8] = {
5119                0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5120        };
5121        static const u8 cs168[8] = {
5122                0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5123        };
5124        static const u8 cs128[3 * 8] = {
5125                0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5126                0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5127                0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5128        };
5129        static const u8 cs148[2 * 8] = {
5130                0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5131                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5132        };
5133        static const u8 cs31a[8 * 4] = {
5134                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5135                0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5136                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5137                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5138        };
5139        static const u8 cs33a[8 * 4] = {
5140                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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        };
5145        static const u8 cs45a[8 * 2] = {
5146                0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5147                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5148        };
5149        static const u8 cs170[7 * 8] = {
5150                0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5151                0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5152                0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5153                0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5154                0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5155                0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5156                0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5157        };
5158        static const u8 cs1a8[3 * 8] = {
5159                0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5160                0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5161                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5162        };
5163        static const u8 cs100[2 * 8] = {
5164                0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5165                0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5166        };
5167
5168        /* VGA enable */
5169        reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5170        SiS_SetRegByte(SISVGAENABLE, reg);
5171
5172        /* Misc */
5173        reg = SiS_GetRegByte(SISMISCR) | 0x01;
5174        SiS_SetRegByte(SISMISCW, reg);
5175
5176        /* Unlock SR */
5177        SiS_SetReg(SISSR, 0x05, 0x86);
5178        reg = SiS_GetReg(SISSR, 0x05);
5179        if(reg != 0xa1)
5180                return 0;
5181
5182        /* Clear some regs */
5183        for(i = 0; i < 0x22; i++) {
5184                if(0x06 + i == 0x20) continue;
5185                SiS_SetReg(SISSR, 0x06 + i, 0x00);
5186        }
5187        for(i = 0; i < 0x0b; i++) {
5188                SiS_SetReg(SISSR, 0x31 + i, 0x00);
5189        }
5190        for(i = 0; i < 0x10; i++) {
5191                SiS_SetReg(SISCR, 0x30 + i, 0x00);
5192        }
5193
5194        ptr = cs78;
5195        if(ivideo->haveXGIROM) {
5196                ptr = (const u8 *)&bios[0x78];
5197        }
5198        for(i = 0; i < 3; i++) {
5199                SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5200        }
5201
5202        ptr = cs76;
5203        if(ivideo->haveXGIROM) {
5204                ptr = (const u8 *)&bios[0x76];
5205        }
5206        for(i = 0; i < 2; i++) {
5207                SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5208        }
5209
5210        v1 = 0x18; v2 = 0x00;
5211        if(ivideo->haveXGIROM) {
5212                v1 = bios[0x74];
5213                v2 = bios[0x75];
5214        }
5215        SiS_SetReg(SISSR, 0x07, v1);
5216        SiS_SetReg(SISSR, 0x11, 0x0f);
5217        SiS_SetReg(SISSR, 0x1f, v2);
5218        /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5219        SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5220        SiS_SetReg(SISSR, 0x27, 0x74);
5221
5222        ptr = cs7b;
5223        if(ivideo->haveXGIROM) {
5224                ptr = (const u8 *)&bios[0x7b];
5225        }
5226        for(i = 0; i < 3; i++) {
5227                SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5228        }
5229
5230        if(ivideo->chip == XGI_40) {
5231                if(ivideo->revision_id == 2) {
5232                        SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5233                }
5234                SiS_SetReg(SISCR, 0x7d, 0xfe);
5235                SiS_SetReg(SISCR, 0x7e, 0x0f);
5236        }
5237        if(ivideo->revision_id == 0) {  /* 40 *and* 20? */
5238                SiS_SetRegAND(SISCR, 0x58, 0xd7);
5239                reg = SiS_GetReg(SISCR, 0xcb);
5240                if(reg & 0x20) {
5241                        SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5242                }
5243        }
5244
5245        reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5246        SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5247
5248        if(ivideo->chip == XGI_20) {
5249                SiS_SetReg(SISSR, 0x36, 0x70);
5250        } else {
5251                SiS_SetReg(SISVID, 0x00, 0x86);
5252                SiS_SetReg(SISVID, 0x32, 0x00);
5253                SiS_SetReg(SISVID, 0x30, 0x00);
5254                SiS_SetReg(SISVID, 0x32, 0x01);
5255                SiS_SetReg(SISVID, 0x30, 0x00);
5256                SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5257                SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5258
5259                SiS_SetReg(SISPART1, 0x2f, 0x01);
5260                SiS_SetReg(SISPART1, 0x00, 0x00);
5261                SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5262                SiS_SetReg(SISPART1, 0x2e, 0x08);
5263                SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5264                SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5265
5266                reg = SiS_GetReg(SISPART4, 0x00);
5267                if(reg == 1 || reg == 2) {
5268                        SiS_SetReg(SISPART2, 0x00, 0x1c);
5269                        SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5270                        SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5271                        SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5272                        SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5273
5274                        reg = SiS_GetReg(SISPART4, 0x01);
5275                        if((reg & 0xf0) >= 0xb0) {
5276                                reg = SiS_GetReg(SISPART4, 0x23);
5277                                if(reg & 0x20) reg |= 0x40;
5278                                SiS_SetReg(SISPART4, 0x23, reg);
5279                                reg = (reg & 0x20) ? 0x02 : 0x00;
5280                                SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5281                        }
5282                }
5283
5284                v1 = bios[0x77];
5285
5286                reg = SiS_GetReg(SISSR, 0x3b);
5287                if(reg & 0x02) {
5288                        reg = SiS_GetReg(SISSR, 0x3a);
5289                        v2 = (reg & 0x30) >> 3;
5290                        if(!(v2 & 0x04)) v2 ^= 0x02;
5291                        reg = SiS_GetReg(SISSR, 0x39);
5292                        if(reg & 0x80) v2 |= 0x80;
5293                        v2 |= 0x01;
5294
5295                        if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5296                                pci_dev_put(mypdev);
5297                                if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5298                                        v2 &= 0xf9;
5299                                v2 |= 0x08;
5300                                v1 &= 0xfe;
5301                        } else {
5302                                mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5303                                if(!mypdev)
5304                                        mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5305                                if(!mypdev)
5306                                        mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5307                                if(mypdev) {
5308                                        pci_read_config_dword(mypdev, 0x94, &regd);
5309                                        regd &= 0xfffffeff;
5310                                        pci_write_config_dword(mypdev, 0x94, regd);
5311                                        v1 &= 0xfe;
5312                                        pci_dev_put(mypdev);
5313                                } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5314                                        v1 &= 0xfe;
5315                                } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5316                                          sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5317                                          sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5318                                          sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5319                                        if((v2 & 0x06) == 4)
5320                                                v2 ^= 0x06;
5321                                        v2 |= 0x08;
5322                                }
5323                        }
5324                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5325                }
5326                SiS_SetReg(SISSR, 0x22, v1);
5327
5328                if(ivideo->revision_id == 2) {
5329                        v1 = SiS_GetReg(SISSR, 0x3b);
5330                        v2 = SiS_GetReg(SISSR, 0x3a);
5331                        regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5332                        if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5333                                SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5334
5335                        if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5336                                /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5337                                 * of nforce 2 ROM
5338                                 */
5339                                if(0)
5340                                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5341                                pci_dev_put(mypdev);
5342                        }
5343                }
5344
5345                v1 = 0x30;
5346                reg = SiS_GetReg(SISSR, 0x3b);
5347                v2 = SiS_GetReg(SISCR, 0x5f);
5348                if((!(reg & 0x02)) && (v2 & 0x0e))
5349                        v1 |= 0x08;
5350                SiS_SetReg(SISSR, 0x27, v1);
5351
5352                if(bios[0x64] & 0x01) {
5353                        SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5354                }
5355
5356                v1 = bios[0x4f7];
5357                pci_read_config_dword(pdev, 0x50, &regd);
5358                regd = (regd >> 20) & 0x0f;
5359                if(regd == 1) {
5360                        v1 &= 0xfc;
5361                        SiS_SetRegOR(SISCR, 0x5f, 0x08);
5362                }
5363                SiS_SetReg(SISCR, 0x48, v1);
5364
5365                SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5366                SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5367                SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5368                SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5369                SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5370                SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5371                SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5372                SiS_SetReg(SISCR, 0x74, 0xd0);
5373                SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5374                SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5375                SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5376                v1 = bios[0x501];
5377                if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5378                        v1 = 0xf0;
5379                        pci_dev_put(mypdev);
5380                }
5381                SiS_SetReg(SISCR, 0x77, v1);
5382        }
5383
5384        /* RAM type:
5385         *
5386         * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5387         *
5388         * The code seems to written so that regb should equal ramtype,
5389         * however, so far it has been hardcoded to 0. Enable other values only
5390         * on XGI Z9, as it passes the POST, and add a warning for others.
5391         */
5392        ramtype = sisfb_post_xgi_ramtype(ivideo);
5393        if (!sisfb_xgi_is21(ivideo) && ramtype) {
5394                dev_warn(&pdev->dev,
5395                         "RAM type something else than expected: %d\n",
5396                         ramtype);
5397                regb = 0;
5398        } else {
5399                regb = ramtype;
5400        }
5401
5402        v1 = 0xff;
5403        if(ivideo->haveXGIROM) {
5404                v1 = bios[0x140 + regb];
5405        }
5406        SiS_SetReg(SISCR, 0x6d, v1);
5407
5408        ptr = cs128;
5409        if(ivideo->haveXGIROM) {
5410                ptr = (const u8 *)&bios[0x128];
5411        }
5412        for(i = 0, j = 0; i < 3; i++, j += 8) {
5413                SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5414        }
5415
5416        ptr  = cs31a;
5417        ptr2 = cs33a;
5418        if(ivideo->haveXGIROM) {
5419                index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5420                ptr  = (const u8 *)&bios[index];
5421                ptr2 = (const u8 *)&bios[index + 0x20];
5422        }
5423        for(i = 0; i < 2; i++) {
5424                if(i == 0) {
5425                        regd = le32_to_cpu(((u32 *)ptr)[regb]);
5426                        rega = 0x6b;
5427                } else {
5428                        regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5429                        rega = 0x6e;
5430                }
5431                reg = 0x00;
5432                for(j = 0; j < 16; j++) {
5433                        reg &= 0xf3;
5434                        if(regd & 0x01) reg |= 0x04;
5435                        if(regd & 0x02) reg |= 0x08;
5436                        regd >>= 2;
5437                        SiS_SetReg(SISCR, rega, reg);
5438                        reg = SiS_GetReg(SISCR, rega);
5439                        reg = SiS_GetReg(SISCR, rega);
5440                        reg += 0x10;
5441                }
5442        }
5443
5444        SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5445
5446        ptr  = NULL;
5447        if(ivideo->haveXGIROM) {
5448                index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5449                ptr  = (const u8 *)&bios[index];
5450        }
5451        for(i = 0; i < 4; i++) {
5452                SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5453                reg = 0x00;
5454                for(j = 0; j < 2; j++) {
5455                        regd = 0;
5456                        if(ptr) {
5457                                regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5458                                ptr += 4;
5459                        }
5460                        /* reg = 0x00; */
5461                        for(k = 0; k < 16; k++) {
5462                                reg &= 0xfc;
5463                                if(regd & 0x01) reg |= 0x01;
5464                                if(regd & 0x02) reg |= 0x02;
5465                                regd >>= 2;
5466                                SiS_SetReg(SISCR, 0x6f, reg);
5467                                reg = SiS_GetReg(SISCR, 0x6f);
5468                                reg = SiS_GetReg(SISCR, 0x6f);
5469                                reg += 0x08;
5470                        }
5471                }
5472        }
5473
5474        ptr  = cs148;
5475        if(ivideo->haveXGIROM) {
5476                ptr  = (const u8 *)&bios[0x148];
5477        }
5478        for(i = 0, j = 0; i < 2; i++, j += 8) {
5479                SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5480        }
5481
5482        SiS_SetRegAND(SISCR, 0x89, 0x8f);
5483
5484        ptr  = cs45a;
5485        if(ivideo->haveXGIROM) {
5486                index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5487                ptr  = (const u8 *)&bios[index];
5488        }
5489        regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5490        reg = 0x80;
5491        for(i = 0; i < 5; i++) {
5492                reg &= 0xfc;
5493                if(regd & 0x01) reg |= 0x01;
5494                if(regd & 0x02) reg |= 0x02;
5495                regd >>= 2;
5496                SiS_SetReg(SISCR, 0x89, reg);
5497                reg = SiS_GetReg(SISCR, 0x89);
5498                reg = SiS_GetReg(SISCR, 0x89);
5499                reg += 0x10;
5500        }
5501
5502        v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5503        if(ivideo->haveXGIROM) {
5504                v1 = bios[0x118 + regb];
5505                v2 = bios[0xf8 + regb];
5506                v3 = bios[0x120 + regb];
5507                v4 = bios[0x1ca];
5508        }
5509        SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5510        SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5511        SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5512        SiS_SetReg(SISCR, 0x41, v2);
5513
5514        ptr  = cs170;
5515        if(ivideo->haveXGIROM) {
5516                ptr  = (const u8 *)&bios[0x170];
5517        }
5518        for(i = 0, j = 0; i < 7; i++, j += 8) {
5519                SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5520        }
5521
5522        SiS_SetReg(SISCR, 0x59, v3);
5523
5524        ptr  = cs1a8;
5525        if(ivideo->haveXGIROM) {
5526                ptr  = (const u8 *)&bios[0x1a8];
5527        }
5528        for(i = 0, j = 0; i < 3; i++, j += 8) {
5529                SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5530        }
5531
5532        ptr  = cs100;
5533        if(ivideo->haveXGIROM) {
5534                ptr  = (const u8 *)&bios[0x100];
5535        }
5536        for(i = 0, j = 0; i < 2; i++, j += 8) {
5537                SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5538        }
5539
5540        SiS_SetReg(SISCR, 0xcf, v4);
5541
5542        SiS_SetReg(SISCR, 0x83, 0x09);
5543        SiS_SetReg(SISCR, 0x87, 0x00);
5544
5545        if(ivideo->chip == XGI_40) {
5546                if( (ivideo->revision_id == 1) ||
5547                    (ivideo->revision_id == 2) ) {
5548                        SiS_SetReg(SISCR, 0x8c, 0x87);
5549                }
5550        }
5551
5552        if (regb == 1)
5553                SiS_SetReg(SISSR, 0x17, 0x80);          /* DDR2 */
5554        else
5555                SiS_SetReg(SISSR, 0x17, 0x00);          /* DDR1 */
5556        SiS_SetReg(SISSR, 0x1a, 0x87);
5557
5558        if(ivideo->chip == XGI_20) {
5559                SiS_SetReg(SISSR, 0x15, 0x00);
5560                SiS_SetReg(SISSR, 0x1c, 0x00);
5561        }
5562
5563        switch(ramtype) {
5564        case 0:
5565                sisfb_post_xgi_setclocks(ivideo, regb);
5566                if((ivideo->chip == XGI_20) ||
5567                   (ivideo->revision_id == 1)   ||
5568                   (ivideo->revision_id == 2)) {
5569                        v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5570                        if(ivideo->haveXGIROM) {
5571                                v1 = bios[regb + 0x158];
5572                                v2 = bios[regb + 0x160];
5573                                v3 = bios[regb + 0x168];
5574                        }
5575                        SiS_SetReg(SISCR, 0x82, v1);
5576                        SiS_SetReg(SISCR, 0x85, v2);
5577                        SiS_SetReg(SISCR, 0x86, v3);
5578                } else {
5579                        SiS_SetReg(SISCR, 0x82, 0x88);
5580                        SiS_SetReg(SISCR, 0x86, 0x00);
5581                        reg = SiS_GetReg(SISCR, 0x86);
5582                        SiS_SetReg(SISCR, 0x86, 0x88);
5583                        reg = SiS_GetReg(SISCR, 0x86);
5584                        SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5585                        SiS_SetReg(SISCR, 0x82, 0x77);
5586                        SiS_SetReg(SISCR, 0x85, 0x00);
5587                        reg = SiS_GetReg(SISCR, 0x85);
5588                        SiS_SetReg(SISCR, 0x85, 0x88);
5589                        reg = SiS_GetReg(SISCR, 0x85);
5590                        SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5591                        SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5592                }
5593                if(ivideo->chip == XGI_40) {
5594                        SiS_SetReg(SISCR, 0x97, 0x00);
5595                }
5596                SiS_SetReg(SISCR, 0x98, 0x01);
5597                SiS_SetReg(SISCR, 0x9a, 0x02);
5598
5599                SiS_SetReg(SISSR, 0x18, 0x01);
5600                if((ivideo->chip == XGI_20) ||
5601                   (ivideo->revision_id == 2)) {
5602                        SiS_SetReg(SISSR, 0x19, 0x40);
5603                } else {
5604                        SiS_SetReg(SISSR, 0x19, 0x20);
5605                }
5606                SiS_SetReg(SISSR, 0x16, 0x00);
5607                SiS_SetReg(SISSR, 0x16, 0x80);
5608                if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5609                        sisfb_post_xgi_delay(ivideo, 0x43);
5610                        sisfb_post_xgi_delay(ivideo, 0x43);
5611                        sisfb_post_xgi_delay(ivideo, 0x43);
5612                        SiS_SetReg(SISSR, 0x18, 0x00);
5613                        if((ivideo->chip == XGI_20) ||
5614                           (ivideo->revision_id == 2)) {
5615                                SiS_SetReg(SISSR, 0x19, 0x40);
5616                        } else {
5617                                SiS_SetReg(SISSR, 0x19, 0x20);
5618                        }
5619                } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5620                        /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5621                }
5622                SiS_SetReg(SISSR, 0x16, 0x00);
5623                SiS_SetReg(SISSR, 0x16, 0x80);
5624                sisfb_post_xgi_delay(ivideo, 4);
5625                v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5626                if(ivideo->haveXGIROM) {
5627                        v1 = bios[0xf0];
5628                        index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5629                        v2 = bios[index];
5630                        v3 = bios[index + 1];
5631                        v4 = bios[index + 2];
5632                        v5 = bios[index + 3];
5633                }
5634                SiS_SetReg(SISSR, 0x18, v1);
5635                SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5636                SiS_SetReg(SISSR, 0x16, v2);
5637                SiS_SetReg(SISSR, 0x16, v3);
5638                sisfb_post_xgi_delay(ivideo, 0x43);
5639                SiS_SetReg(SISSR, 0x1b, 0x03);
5640                sisfb_post_xgi_delay(ivideo, 0x22);
5641                SiS_SetReg(SISSR, 0x18, v1);
5642                SiS_SetReg(SISSR, 0x19, 0x00);
5643                SiS_SetReg(SISSR, 0x16, v4);
5644                SiS_SetReg(SISSR, 0x16, v5);
5645                SiS_SetReg(SISSR, 0x1b, 0x00);
5646                break;
5647        case 1:
5648                sisfb_post_xgi_ddr2(ivideo, regb);
5649                break;
5650        default:
5651                sisfb_post_xgi_setclocks(ivideo, regb);
5652                if((ivideo->chip == XGI_40) &&
5653                   ((ivideo->revision_id == 1) ||
5654                    (ivideo->revision_id == 2))) {
5655                        SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5656                        SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5657                        SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5658                } else {
5659                        SiS_SetReg(SISCR, 0x82, 0x88);
5660                        SiS_SetReg(SISCR, 0x86, 0x00);
5661                        reg = SiS_GetReg(SISCR, 0x86);
5662                        SiS_SetReg(SISCR, 0x86, 0x88);
5663                        SiS_SetReg(SISCR, 0x82, 0x77);
5664                        SiS_SetReg(SISCR, 0x85, 0x00);
5665                        reg = SiS_GetReg(SISCR, 0x85);
5666                        SiS_SetReg(SISCR, 0x85, 0x88);
5667                        reg = SiS_GetReg(SISCR, 0x85);
5668                        v1 = cs160[regb]; v2 = cs158[regb];
5669                        if(ivideo->haveXGIROM) {
5670                                v1 = bios[regb + 0x160];
5671                                v2 = bios[regb + 0x158];
5672                        }
5673                        SiS_SetReg(SISCR, 0x85, v1);
5674                        SiS_SetReg(SISCR, 0x82, v2);
5675                }
5676                if(ivideo->chip == XGI_40) {
5677                        SiS_SetReg(SISCR, 0x97, 0x11);
5678                }
5679                if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5680                        SiS_SetReg(SISCR, 0x98, 0x01);
5681                } else {
5682                        SiS_SetReg(SISCR, 0x98, 0x03);
5683                }
5684                SiS_SetReg(SISCR, 0x9a, 0x02);
5685
5686                if(ivideo->chip == XGI_40) {
5687                        SiS_SetReg(SISSR, 0x18, 0x01);
5688                } else {
5689                        SiS_SetReg(SISSR, 0x18, 0x00);
5690                }
5691                SiS_SetReg(SISSR, 0x19, 0x40);
5692                SiS_SetReg(SISSR, 0x16, 0x00);
5693                SiS_SetReg(SISSR, 0x16, 0x80);
5694                if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5695                        sisfb_post_xgi_delay(ivideo, 0x43);
5696                        sisfb_post_xgi_delay(ivideo, 0x43);
5697                        sisfb_post_xgi_delay(ivideo, 0x43);
5698                        SiS_SetReg(SISSR, 0x18, 0x00);
5699                        SiS_SetReg(SISSR, 0x19, 0x40);
5700                        SiS_SetReg(SISSR, 0x16, 0x00);
5701                        SiS_SetReg(SISSR, 0x16, 0x80);
5702                }
5703                sisfb_post_xgi_delay(ivideo, 4);
5704                v1 = 0x31;
5705                if(ivideo->haveXGIROM) {
5706                        v1 = bios[0xf0];
5707                }
5708                SiS_SetReg(SISSR, 0x18, v1);
5709                SiS_SetReg(SISSR, 0x19, 0x01);
5710                if(ivideo->chip == XGI_40) {
5711                        SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5712                        SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5713                } else {
5714                        SiS_SetReg(SISSR, 0x16, 0x05);
5715                        SiS_SetReg(SISSR, 0x16, 0x85);
5716                }
5717                sisfb_post_xgi_delay(ivideo, 0x43);
5718                if(ivideo->chip == XGI_40) {
5719                        SiS_SetReg(SISSR, 0x1b, 0x01);
5720                } else {
5721                        SiS_SetReg(SISSR, 0x1b, 0x03);
5722                }
5723                sisfb_post_xgi_delay(ivideo, 0x22);
5724                SiS_SetReg(SISSR, 0x18, v1);
5725                SiS_SetReg(SISSR, 0x19, 0x00);
5726                if(ivideo->chip == XGI_40) {
5727                        SiS_SetReg(SISSR, 0x16, bios[0x540]);
5728                        SiS_SetReg(SISSR, 0x16, bios[0x541]);
5729                } else {
5730                        SiS_SetReg(SISSR, 0x16, 0x05);
5731                        SiS_SetReg(SISSR, 0x16, 0x85);
5732                }
5733                SiS_SetReg(SISSR, 0x1b, 0x00);
5734        }
5735
5736        regb = 0;       /* ! */
5737        v1 = 0x03;
5738        if(ivideo->haveXGIROM) {
5739                v1 = bios[0x110 + regb];
5740        }
5741        SiS_SetReg(SISSR, 0x1b, v1);
5742
5743        /* RAM size */
5744        v1 = 0x00; v2 = 0x00;
5745        if(ivideo->haveXGIROM) {
5746                v1 = bios[0x62];
5747                v2 = bios[0x63];
5748        }
5749        regb = 0;       /* ! */
5750        regd = 1 << regb;
5751        if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5752
5753                SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5754                SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5755
5756        } else {
5757                int err;
5758
5759                /* Set default mode, don't clear screen */
5760                ivideo->SiS_Pr.SiS_UseOEM = false;
5761                SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5762                SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5763                ivideo->curFSTN = ivideo->curDSTN = 0;
5764                ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5765                SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5766
5767                SiS_SetReg(SISSR, 0x05, 0x86);
5768
5769                /* Disable read-cache */
5770                SiS_SetRegAND(SISSR, 0x21, 0xdf);
5771                err = sisfb_post_xgi_ramsize(ivideo);
5772                /* Enable read-cache */
5773                SiS_SetRegOR(SISSR, 0x21, 0x20);
5774
5775                if (err) {
5776                        dev_err(&pdev->dev,
5777                                "%s: RAM size detection failed: %d\n",
5778                                __func__, err);
5779                        return 0;
5780                }
5781        }
5782
5783#if 0
5784        printk(KERN_DEBUG "-----------------\n");
5785        for(i = 0; i < 0xff; i++) {
5786                reg = SiS_GetReg(SISCR, i);
5787                printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5788        }
5789        for(i = 0; i < 0x40; i++) {
5790                reg = SiS_GetReg(SISSR, i);
5791                printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5792        }
5793        printk(KERN_DEBUG "-----------------\n");
5794#endif
5795
5796        /* Sense CRT1 */
5797        if(ivideo->chip == XGI_20) {
5798                SiS_SetRegOR(SISCR, 0x32, 0x20);
5799        } else {
5800                reg = SiS_GetReg(SISPART4, 0x00);
5801                if((reg == 1) || (reg == 2)) {
5802                        sisfb_sense_crt1(ivideo);
5803                } else {
5804                        SiS_SetRegOR(SISCR, 0x32, 0x20);
5805                }
5806        }
5807
5808        /* Set default mode, don't clear screen */
5809        ivideo->SiS_Pr.SiS_UseOEM = false;
5810        SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5811        SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5812        ivideo->curFSTN = ivideo->curDSTN = 0;
5813        SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5814
5815        SiS_SetReg(SISSR, 0x05, 0x86);
5816
5817        /* Display off */
5818        SiS_SetRegOR(SISSR, 0x01, 0x20);
5819
5820        /* Save mode number in CR34 */
5821        SiS_SetReg(SISCR, 0x34, 0x2e);
5822
5823        /* Let everyone know what the current mode is */
5824        ivideo->modeprechange = 0x2e;
5825
5826        if(ivideo->chip == XGI_40) {
5827                reg = SiS_GetReg(SISCR, 0xca);
5828                v1 = SiS_GetReg(SISCR, 0xcc);
5829                if((reg & 0x10) && (!(v1 & 0x04))) {
5830                        printk(KERN_ERR
5831                                "sisfb: Please connect power to the card.\n");
5832                        return 0;
5833                }
5834        }
5835
5836        return 1;
5837}
5838#endif
5839
5840static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5841{
5842        struct sisfb_chip_info  *chipinfo = &sisfb_chip_info[ent->driver_data];
5843        struct sis_video_info   *ivideo = NULL;
5844        struct fb_info          *sis_fb_info = NULL;
5845        u16 reg16;
5846        u8  reg;
5847        int i, ret;
5848
5849        if(sisfb_off)
5850                return -ENXIO;
5851
5852        sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5853        if(!sis_fb_info)
5854                return -ENOMEM;
5855
5856        ivideo = (struct sis_video_info *)sis_fb_info->par;
5857        ivideo->memyselfandi = sis_fb_info;
5858
5859        ivideo->sisfb_id = SISFB_ID;
5860
5861        if(card_list == NULL) {
5862                ivideo->cardnumber = 0;
5863        } else {
5864                struct sis_video_info *countvideo = card_list;
5865                ivideo->cardnumber = 1;
5866                while((countvideo = countvideo->next) != NULL)
5867                        ivideo->cardnumber++;
5868        }
5869
5870        strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5871
5872        ivideo->warncount = 0;
5873        ivideo->chip_id = pdev->device;
5874        ivideo->chip_vendor = pdev->vendor;
5875        ivideo->revision_id = pdev->revision;
5876        ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5877        pci_read_config_word(pdev, PCI_COMMAND, &reg16);
5878        ivideo->sisvga_enabled = reg16 & 0x01;
5879        ivideo->pcibus = pdev->bus->number;
5880        ivideo->pcislot = PCI_SLOT(pdev->devfn);
5881        ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5882        ivideo->subsysvendor = pdev->subsystem_vendor;
5883        ivideo->subsysdevice = pdev->subsystem_device;
5884
5885#ifndef MODULE
5886        if(sisfb_mode_idx == -1) {
5887                sisfb_get_vga_mode_from_kernel();
5888        }
5889#endif
5890
5891        ivideo->chip = chipinfo->chip;
5892        ivideo->chip_real_id = chipinfo->chip;
5893        ivideo->sisvga_engine = chipinfo->vgaengine;
5894        ivideo->hwcursor_size = chipinfo->hwcursor_size;
5895        ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5896        ivideo->mni = chipinfo->mni;
5897
5898        ivideo->detectedpdc  = 0xff;
5899        ivideo->detectedpdca = 0xff;
5900        ivideo->detectedlcda = 0xff;
5901
5902        ivideo->sisfb_thismonitor.datavalid = false;
5903
5904        ivideo->current_base = 0;
5905
5906        ivideo->engineok = 0;
5907
5908        ivideo->sisfb_was_boot_device = 0;
5909
5910        if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5911                if(ivideo->sisvga_enabled)
5912                        ivideo->sisfb_was_boot_device = 1;
5913                else {
5914                        printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5915                                "but marked as boot video device ???\n");
5916                        printk(KERN_DEBUG "sisfb: I will not accept this "
5917                                "as the primary VGA device\n");
5918                }
5919        }
5920
5921        ivideo->sisfb_parm_mem = sisfb_parm_mem;
5922        ivideo->sisfb_accel = sisfb_accel;
5923        ivideo->sisfb_ypan = sisfb_ypan;
5924        ivideo->sisfb_max = sisfb_max;
5925        ivideo->sisfb_userom = sisfb_userom;
5926        ivideo->sisfb_useoem = sisfb_useoem;
5927        ivideo->sisfb_mode_idx = sisfb_mode_idx;
5928        ivideo->sisfb_parm_rate = sisfb_parm_rate;
5929        ivideo->sisfb_crt1off = sisfb_crt1off;
5930        ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5931        ivideo->sisfb_crt2type = sisfb_crt2type;
5932        ivideo->sisfb_crt2flags = sisfb_crt2flags;
5933        /* pdc(a), scalelcd, special timing, lvdshl handled below */
5934        ivideo->sisfb_dstn = sisfb_dstn;
5935        ivideo->sisfb_fstn = sisfb_fstn;
5936        ivideo->sisfb_tvplug = sisfb_tvplug;
5937        ivideo->sisfb_tvstd = sisfb_tvstd;
5938        ivideo->tvxpos = sisfb_tvxposoffset;
5939        ivideo->tvypos = sisfb_tvyposoffset;
5940        ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5941        ivideo->refresh_rate = 0;
5942        if(ivideo->sisfb_parm_rate != -1) {
5943                ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5944        }
5945
5946        ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5947        ivideo->SiS_Pr.CenterScreen = -1;
5948        ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5949        ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5950
5951        ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5952        ivideo->SiS_Pr.SiS_CHOverScan = -1;
5953        ivideo->SiS_Pr.SiS_ChSW = false;
5954        ivideo->SiS_Pr.SiS_UseLCDA = false;
5955        ivideo->SiS_Pr.HaveEMI = false;
5956        ivideo->SiS_Pr.HaveEMILCD = false;
5957        ivideo->SiS_Pr.OverruleEMI = false;
5958        ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5959        ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5960        ivideo->SiS_Pr.PDC  = -1;
5961        ivideo->SiS_Pr.PDCA = -1;
5962        ivideo->SiS_Pr.DDCPortMixup = false;
5963#ifdef CONFIG_FB_SIS_315
5964        if(ivideo->chip >= SIS_330) {
5965                ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5966                if(ivideo->chip >= SIS_661) {
5967                        ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5968                }
5969        }
5970#endif
5971
5972        memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5973
5974        pci_set_drvdata(pdev, ivideo);
5975
5976        /* Patch special cases */
5977        if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5978                switch(ivideo->nbridge->device) {
5979#ifdef CONFIG_FB_SIS_300
5980                case PCI_DEVICE_ID_SI_730:
5981                        ivideo->chip = SIS_730;
5982                        strcpy(ivideo->myid, "SiS 730");
5983                        break;
5984#endif
5985#ifdef CONFIG_FB_SIS_315
5986                case PCI_DEVICE_ID_SI_651:
5987                        /* ivideo->chip is ok */
5988                        strcpy(ivideo->myid, "SiS 651");
5989                        break;
5990                case PCI_DEVICE_ID_SI_740:
5991                        ivideo->chip = SIS_740;
5992                        strcpy(ivideo->myid, "SiS 740");
5993                        break;
5994                case PCI_DEVICE_ID_SI_661:
5995                        ivideo->chip = SIS_661;
5996                        strcpy(ivideo->myid, "SiS 661");
5997                        break;
5998                case PCI_DEVICE_ID_SI_741:
5999                        ivideo->chip = SIS_741;
6000                        strcpy(ivideo->myid, "SiS 741");
6001                        break;
6002                case PCI_DEVICE_ID_SI_760:
6003                        ivideo->chip = SIS_760;
6004                        strcpy(ivideo->myid, "SiS 760");
6005                        break;
6006                case PCI_DEVICE_ID_SI_761:
6007                        ivideo->chip = SIS_761;
6008                        strcpy(ivideo->myid, "SiS 761");
6009                        break;
6010#endif
6011                default:
6012                        break;
6013                }
6014        }
6015
6016        ivideo->SiS_Pr.ChipType = ivideo->chip;
6017
6018        ivideo->SiS_Pr.ivideo = (void *)ivideo;
6019
6020#ifdef CONFIG_FB_SIS_315
6021        if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6022           (ivideo->SiS_Pr.ChipType == SIS_315)) {
6023                ivideo->SiS_Pr.ChipType = SIS_315H;
6024        }
6025#endif
6026
6027        if(!ivideo->sisvga_enabled) {
6028                if(pci_enable_device(pdev)) {
6029                        pci_dev_put(ivideo->nbridge);
6030                        framebuffer_release(sis_fb_info);
6031                        return -EIO;
6032                }
6033        }
6034
6035        ivideo->video_base = pci_resource_start(pdev, 0);
6036        ivideo->video_size = pci_resource_len(pdev, 0);
6037        ivideo->mmio_base  = pci_resource_start(pdev, 1);
6038        ivideo->mmio_size  = pci_resource_len(pdev, 1);
6039        ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6040        ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6041
6042        SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6043
6044#ifdef CONFIG_FB_SIS_300
6045        /* Find PCI systems for Chrontel/GPIO communication setup */
6046        if(ivideo->chip == SIS_630) {
6047                i = 0;
6048                do {
6049                        if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6050                           mychswtable[i].subsysCard   == ivideo->subsysdevice) {
6051                                ivideo->SiS_Pr.SiS_ChSW = true;
6052                                printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6053                                        "requiring Chrontel/GPIO setup\n",
6054                                        mychswtable[i].vendorName,
6055                                        mychswtable[i].cardName);
6056                                ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6057                                break;
6058                        }
6059                        i++;
6060                } while(mychswtable[i].subsysVendor != 0);
6061        }
6062#endif
6063
6064#ifdef CONFIG_FB_SIS_315
6065        if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6066                ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6067        }
6068#endif
6069
6070        SiS_SetReg(SISSR, 0x05, 0x86);
6071
6072        if( (!ivideo->sisvga_enabled)
6073#if !defined(__i386__) && !defined(__x86_64__)
6074                              || (sisfb_resetcard)
6075#endif
6076                                                   ) {
6077                for(i = 0x30; i <= 0x3f; i++) {
6078                        SiS_SetReg(SISCR, i, 0x00);
6079                }
6080        }
6081
6082        /* Find out about current video mode */
6083        ivideo->modeprechange = 0x03;
6084        reg = SiS_GetReg(SISCR, 0x34);
6085        if(reg & 0x7f) {
6086                ivideo->modeprechange = reg & 0x7f;
6087        } else if(ivideo->sisvga_enabled) {
6088#if defined(__i386__) || defined(__x86_64__)
6089                unsigned char __iomem *tt = ioremap(0x400, 0x100);
6090                if(tt) {
6091                        ivideo->modeprechange = readb(tt + 0x49);
6092                        iounmap(tt);
6093                }
6094#endif
6095        }
6096
6097        /* Search and copy ROM image */
6098        ivideo->bios_abase = NULL;
6099        ivideo->SiS_Pr.VirtualRomBase = NULL;
6100        ivideo->SiS_Pr.UseROM = false;
6101        ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6102        if(ivideo->sisfb_userom) {
6103                ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6104                ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6105                ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6106                printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6107                        ivideo->SiS_Pr.UseROM ? "" : "not ");
6108                if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6109                   ivideo->SiS_Pr.UseROM = false;
6110                   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6111                   if( (ivideo->revision_id == 2) &&
6112                       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6113                        ivideo->SiS_Pr.DDCPortMixup = true;
6114                   }
6115                }
6116        } else {
6117                printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6118        }
6119
6120        /* Find systems for special custom timing */
6121        if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6122                sisfb_detect_custom_timing(ivideo);
6123        }
6124
6125#ifdef CONFIG_FB_SIS_315
6126        if (ivideo->chip == XGI_20) {
6127                /* Check if our Z7 chip is actually Z9 */
6128                SiS_SetRegOR(SISCR, 0x4a, 0x40);        /* GPIOG EN */
6129                reg = SiS_GetReg(SISCR, 0x48);
6130                if (reg & 0x02) {                       /* GPIOG */
6131                        ivideo->chip_real_id = XGI_21;
6132                        dev_info(&pdev->dev, "Z9 detected\n");
6133                }
6134        }
6135#endif
6136
6137        /* POST card in case this has not been done by the BIOS */
6138        if( (!ivideo->sisvga_enabled)
6139#if !defined(__i386__) && !defined(__x86_64__)
6140                             || (sisfb_resetcard)
6141#endif
6142                                                 ) {
6143#ifdef CONFIG_FB_SIS_300
6144                if(ivideo->sisvga_engine == SIS_300_VGA) {
6145                        if(ivideo->chip == SIS_300) {
6146                                sisfb_post_sis300(pdev);
6147                                ivideo->sisfb_can_post = 1;
6148                        }
6149                }
6150#endif
6151
6152#ifdef CONFIG_FB_SIS_315
6153                if(ivideo->sisvga_engine == SIS_315_VGA) {
6154                        int result = 1;
6155                /*      if((ivideo->chip == SIS_315H)   ||
6156                           (ivideo->chip == SIS_315)    ||
6157                           (ivideo->chip == SIS_315PRO) ||
6158                           (ivideo->chip == SIS_330)) {
6159                                sisfb_post_sis315330(pdev);
6160                        } else */ if(ivideo->chip == XGI_20) {
6161                                result = sisfb_post_xgi(pdev);
6162                                ivideo->sisfb_can_post = 1;
6163                        } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6164                                result = sisfb_post_xgi(pdev);
6165                                ivideo->sisfb_can_post = 1;
6166                        } else {
6167                                printk(KERN_INFO "sisfb: Card is not "
6168                                        "POSTed and sisfb can't do this either.\n");
6169                        }
6170                        if(!result) {
6171                                printk(KERN_ERR "sisfb: Failed to POST card\n");
6172                                ret = -ENODEV;
6173                                goto error_3;
6174                        }
6175                }
6176#endif
6177        }
6178
6179        ivideo->sisfb_card_posted = 1;
6180
6181        /* Find out about RAM size */
6182        if(sisfb_get_dram_size(ivideo)) {
6183                printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6184                ret = -ENODEV;
6185                goto error_3;
6186        }
6187
6188
6189        /* Enable PCI addressing and MMIO */
6190        if((ivideo->sisfb_mode_idx < 0) ||
6191           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6192                /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
6193                SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6194                /* Enable 2D accelerator engine */
6195                SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6196        }
6197
6198        if(sisfb_pdc != 0xff) {
6199                if(ivideo->sisvga_engine == SIS_300_VGA)
6200                        sisfb_pdc &= 0x3c;
6201                else
6202                        sisfb_pdc &= 0x1f;
6203                ivideo->SiS_Pr.PDC = sisfb_pdc;
6204        }
6205#ifdef CONFIG_FB_SIS_315
6206        if(ivideo->sisvga_engine == SIS_315_VGA) {
6207                if(sisfb_pdca != 0xff)
6208                        ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6209        }
6210#endif
6211
6212        if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6213                printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6214                                (int)(ivideo->video_size >> 20));
6215                printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6216                ret = -ENODEV;
6217                goto error_3;
6218        }
6219
6220        if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6221                printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6222                ret = -ENODEV;
6223                goto error_2;
6224        }
6225
6226        ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6227        ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6228        if(!ivideo->video_vbase) {
6229                printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6230                ret = -ENODEV;
6231                goto error_1;
6232        }
6233
6234        ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6235        if(!ivideo->mmio_vbase) {
6236                printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6237                ret = -ENODEV;
6238error_0:        iounmap(ivideo->video_vbase);
6239error_1:        release_mem_region(ivideo->video_base, ivideo->video_size);
6240error_2:        release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6241error_3:        vfree(ivideo->bios_abase);
6242                pci_dev_put(ivideo->lpcdev);
6243                pci_dev_put(ivideo->nbridge);
6244                if(!ivideo->sisvga_enabled)
6245                        pci_disable_device(pdev);
6246                framebuffer_release(sis_fb_info);
6247                return ret;
6248        }
6249
6250        printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6251                ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6252
6253        if(ivideo->video_offset) {
6254                printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6255                        ivideo->video_offset / 1024);
6256        }
6257
6258        printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6259                ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6260
6261
6262        /* Determine the size of the command queue */
6263        if(ivideo->sisvga_engine == SIS_300_VGA) {
6264                ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6265        } else {
6266                if(ivideo->chip == XGI_20) {
6267                        ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6268                } else {
6269                        ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6270                }
6271        }
6272
6273        /* Engines are no longer initialized here; this is
6274         * now done after the first mode-switch (if the
6275         * submitted var has its acceleration flags set).
6276         */
6277
6278        /* Calculate the base of the (unused) hw cursor */
6279        ivideo->hwcursor_vbase = ivideo->video_vbase
6280                                 + ivideo->video_size
6281                                 - ivideo->cmdQueueSize
6282                                 - ivideo->hwcursor_size;
6283        ivideo->caps |= HW_CURSOR_CAP;
6284
6285        /* Initialize offscreen memory manager */
6286        if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6287                printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6288        }
6289
6290        /* Used for clearing the screen only, therefore respect our mem limit */
6291        ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6292        ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6293
6294        ivideo->vbflags = 0;
6295        ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6296        ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
6297        ivideo->defmodeidx    = DEFAULT_MODE;
6298
6299        ivideo->newrom = 0;
6300        if(ivideo->chip < XGI_20) {
6301                if(ivideo->bios_abase) {
6302                        ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6303                }
6304        }
6305
6306        if((ivideo->sisfb_mode_idx < 0) ||
6307           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6308
6309                sisfb_sense_crt1(ivideo);
6310
6311                sisfb_get_VB_type(ivideo);
6312
6313                if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6314                        sisfb_detect_VB_connect(ivideo);
6315                }
6316
6317                ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6318
6319                /* Decide on which CRT2 device to use */
6320                if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6321                        if(ivideo->sisfb_crt2type != -1) {
6322                                if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6323                                   (ivideo->vbflags & CRT2_LCD)) {
6324                                        ivideo->currentvbflags |= CRT2_LCD;
6325                                } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6326                                        ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6327                                }
6328                        } else {
6329                                /* Chrontel 700x TV detection often unreliable, therefore
6330                                 * use a different default order on such machines
6331                                 */
6332                                if((ivideo->sisvga_engine == SIS_300_VGA) &&
6333                                   (ivideo->vbflags2 & VB2_CHRONTEL)) {
6334                                        if(ivideo->vbflags & CRT2_LCD)
6335                                                ivideo->currentvbflags |= CRT2_LCD;
6336                                        else if(ivideo->vbflags & CRT2_TV)
6337                                                ivideo->currentvbflags |= CRT2_TV;
6338                                        else if(ivideo->vbflags & CRT2_VGA)
6339                                                ivideo->currentvbflags |= CRT2_VGA;
6340                                } else {
6341                                        if(ivideo->vbflags & CRT2_TV)
6342                                                ivideo->currentvbflags |= CRT2_TV;
6343                                        else if(ivideo->vbflags & CRT2_LCD)
6344                                                ivideo->currentvbflags |= CRT2_LCD;
6345                                        else if(ivideo->vbflags & CRT2_VGA)
6346                                                ivideo->currentvbflags |= CRT2_VGA;
6347                                }
6348                        }
6349                }
6350
6351                if(ivideo->vbflags & CRT2_LCD) {
6352                        sisfb_detect_lcd_type(ivideo);
6353                }
6354
6355                sisfb_save_pdc_emi(ivideo);
6356
6357                if(!ivideo->sisfb_crt1off) {
6358                        sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6359                } else {
6360                        if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6361                           (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6362                                sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6363                        }
6364                }
6365
6366                if(ivideo->sisfb_mode_idx >= 0) {
6367                        int bu = ivideo->sisfb_mode_idx;
6368                        ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6369                                        ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6370                        if(bu != ivideo->sisfb_mode_idx) {
6371                                printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6372                                        sisbios_mode[bu].xres,
6373                                        sisbios_mode[bu].yres,
6374                                        sisbios_mode[bu].bpp);
6375                        }
6376                }
6377
6378                if(ivideo->sisfb_mode_idx < 0) {
6379                        switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6380                           case CRT2_LCD:
6381                                ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6382                                break;
6383                           case CRT2_TV:
6384                                ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6385                                break;
6386                           default:
6387                                ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6388                                break;
6389                        }
6390                }
6391
6392                ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6393
6394                if(ivideo->refresh_rate != 0) {
6395                        sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6396                                                ivideo->sisfb_mode_idx);
6397                }
6398
6399                if(ivideo->rate_idx == 0) {
6400                        ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6401                        ivideo->refresh_rate = 60;
6402                }
6403
6404                if(ivideo->sisfb_thismonitor.datavalid) {
6405                        if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6406                                                ivideo->sisfb_mode_idx,
6407                                                ivideo->rate_idx,
6408                                                ivideo->refresh_rate)) {
6409                                printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6410                                                        "exceeds monitor specs!\n");
6411                        }
6412                }
6413
6414                ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6415                ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6416                ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6417
6418                sisfb_set_vparms(ivideo);
6419
6420                printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6421                        ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6422                        ivideo->refresh_rate);
6423
6424                /* Set up the default var according to chosen default display mode */
6425                ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6426                ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6427                ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6428
6429                sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6430
6431                ivideo->default_var.pixclock = (u32) (1000000000 /
6432                        sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6433
6434                if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6435                                                ivideo->rate_idx, &ivideo->default_var)) {
6436                        if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6437                                ivideo->default_var.pixclock <<= 1;
6438                        }
6439                }
6440
6441                if(ivideo->sisfb_ypan) {
6442                        /* Maximize regardless of sisfb_max at startup */
6443                        ivideo->default_var.yres_virtual =
6444                                sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6445                        if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6446                                ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6447                        }
6448                }
6449
6450                sisfb_calc_pitch(ivideo, &ivideo->default_var);
6451
6452                ivideo->accel = 0;
6453                if(ivideo->sisfb_accel) {
6454                        ivideo->accel = -1;
6455#ifdef STUPID_ACCELF_TEXT_SHIT
6456                        ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6457#endif
6458                }
6459                sisfb_initaccel(ivideo);
6460
6461#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6462                sis_fb_info->flags = FBINFO_DEFAULT             |
6463                                     FBINFO_HWACCEL_YPAN        |
6464                                     FBINFO_HWACCEL_XPAN        |
6465                                     FBINFO_HWACCEL_COPYAREA    |
6466                                     FBINFO_HWACCEL_FILLRECT    |
6467                                     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6468#else
6469                sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6470#endif
6471                sis_fb_info->var = ivideo->default_var;
6472                sis_fb_info->fix = ivideo->sisfb_fix;
6473                sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6474                sis_fb_info->fbops = &sisfb_ops;
6475                sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6476
6477                fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6478
6479                printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6480
6481                ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6482                                                     ivideo->video_size);
6483                if(register_framebuffer(sis_fb_info) < 0) {
6484                        printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6485                        ret = -EINVAL;
6486                        iounmap(ivideo->mmio_vbase);
6487                        goto error_0;
6488                }
6489
6490                ivideo->registered = 1;
6491
6492                /* Enlist us */
6493                ivideo->next = card_list;
6494                card_list = ivideo;
6495
6496                printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6497                        ivideo->sisfb_accel ? "enabled" : "disabled",
6498                        ivideo->sisfb_ypan  ?
6499                                (ivideo->sisfb_max ? "enabled (auto-max)" :
6500                                                "enabled (no auto-max)") :
6501                                                                        "disabled");
6502
6503
6504                fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6505                        ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6506
6507                printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6508
6509        }       /* if mode = "none" */
6510
6511        return 0;
6512}
6513
6514/*****************************************************/
6515/*                PCI DEVICE HANDLING                */
6516/*****************************************************/
6517
6518static void sisfb_remove(struct pci_dev *pdev)
6519{
6520        struct sis_video_info   *ivideo = pci_get_drvdata(pdev);
6521        struct fb_info          *sis_fb_info = ivideo->memyselfandi;
6522        int                     registered = ivideo->registered;
6523        int                     modechanged = ivideo->modechanged;
6524
6525        /* Unmap */
6526        iounmap(ivideo->mmio_vbase);
6527        iounmap(ivideo->video_vbase);
6528
6529        /* Release mem regions */
6530        release_mem_region(ivideo->video_base, ivideo->video_size);
6531        release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6532
6533        vfree(ivideo->bios_abase);
6534
6535        pci_dev_put(ivideo->lpcdev);
6536
6537        pci_dev_put(ivideo->nbridge);
6538
6539        arch_phys_wc_del(ivideo->wc_cookie);
6540
6541        /* If device was disabled when starting, disable
6542         * it when quitting.
6543         */
6544        if(!ivideo->sisvga_enabled)
6545                pci_disable_device(pdev);
6546
6547        /* Unregister the framebuffer */
6548        if(ivideo->registered) {
6549                unregister_framebuffer(sis_fb_info);
6550                framebuffer_release(sis_fb_info);
6551        }
6552
6553        /* OK, our ivideo is gone for good from here. */
6554
6555        /* TODO: Restore the initial mode
6556         * This sounds easy but is as good as impossible
6557         * on many machines with SiS chip and video bridge
6558         * since text modes are always set up differently
6559         * from machine to machine. Depends on the type
6560         * of integration between chipset and bridge.
6561         */
6562        if(registered && modechanged)
6563                printk(KERN_INFO
6564                        "sisfb: Restoring of text mode not supported yet\n");
6565};
6566
6567static struct pci_driver sisfb_driver = {
6568        .name           = "sisfb",
6569        .id_table       = sisfb_pci_table,
6570        .probe          = sisfb_probe,
6571        .remove         = sisfb_remove,
6572};
6573
6574static int __init sisfb_init(void)
6575{
6576#ifndef MODULE
6577        char *options = NULL;
6578
6579        if(fb_get_options("sisfb", &options))
6580                return -ENODEV;
6581
6582        sisfb_setup(options);
6583#endif
6584        return pci_register_driver(&sisfb_driver);
6585}
6586
6587#ifndef MODULE
6588module_init(sisfb_init);
6589#endif
6590
6591/*****************************************************/
6592/*                      MODULE                       */
6593/*****************************************************/
6594
6595#ifdef MODULE
6596
6597static char             *mode = NULL;
6598static int              vesa = -1;
6599static unsigned int     rate = 0;
6600static unsigned int     crt1off = 1;
6601static unsigned int     mem = 0;
6602static char             *forcecrt2type = NULL;
6603static int              forcecrt1 = -1;
6604static int              pdc = -1;
6605static int              pdc1 = -1;
6606static int              noaccel = -1;
6607static int              noypan  = -1;
6608static int              nomax = -1;
6609static int              userom = -1;
6610static int              useoem = -1;
6611static char             *tvstandard = NULL;
6612static int              nocrt2rate = 0;
6613static int              scalelcd = -1;
6614static char             *specialtiming = NULL;
6615static int              lvdshl = -1;
6616static int              tvxposoffset = 0, tvyposoffset = 0;
6617#if !defined(__i386__) && !defined(__x86_64__)
6618static int              resetcard = 0;
6619static int              videoram = 0;
6620#endif
6621
6622static int __init sisfb_init_module(void)
6623{
6624        sisfb_setdefaultparms();
6625
6626        if(rate)
6627                sisfb_parm_rate = rate;
6628
6629        if((scalelcd == 0) || (scalelcd == 1))
6630                sisfb_scalelcd = scalelcd ^ 1;
6631
6632        /* Need to check crt2 type first for fstn/dstn */
6633
6634        if(forcecrt2type)
6635                sisfb_search_crt2type(forcecrt2type);
6636
6637        if(tvstandard)
6638                sisfb_search_tvstd(tvstandard);
6639
6640        if(mode)
6641                sisfb_search_mode(mode, false);
6642        else if(vesa != -1)
6643                sisfb_search_vesamode(vesa, false);
6644
6645        sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6646
6647        sisfb_forcecrt1 = forcecrt1;
6648        if(forcecrt1 == 1)
6649                sisfb_crt1off = 0;
6650        else if(forcecrt1 == 0)
6651                sisfb_crt1off = 1;
6652
6653        if(noaccel == 1)
6654                sisfb_accel = 0;
6655        else if(noaccel == 0)
6656                sisfb_accel = 1;
6657
6658        if(noypan == 1)
6659                sisfb_ypan = 0;
6660        else if(noypan == 0)
6661                sisfb_ypan = 1;
6662
6663        if(nomax == 1)
6664                sisfb_max = 0;
6665        else if(nomax == 0)
6666                sisfb_max = 1;
6667
6668        if(mem)
6669                sisfb_parm_mem = mem;
6670
6671        if(userom != -1)
6672                sisfb_userom = userom;
6673
6674        if(useoem != -1)
6675                sisfb_useoem = useoem;
6676
6677        if(pdc != -1)
6678                sisfb_pdc  = (pdc  & 0x7f);
6679
6680        if(pdc1 != -1)
6681                sisfb_pdca = (pdc1 & 0x1f);
6682
6683        sisfb_nocrt2rate = nocrt2rate;
6684
6685        if(specialtiming)
6686                sisfb_search_specialtiming(specialtiming);
6687
6688        if((lvdshl >= 0) && (lvdshl <= 3))
6689                sisfb_lvdshl = lvdshl;
6690
6691        sisfb_tvxposoffset = tvxposoffset;
6692        sisfb_tvyposoffset = tvyposoffset;
6693
6694#if !defined(__i386__) && !defined(__x86_64__)
6695        sisfb_resetcard = (resetcard) ? 1 : 0;
6696        if(videoram)
6697                sisfb_videoram = videoram;
6698#endif
6699
6700        return sisfb_init();
6701}
6702
6703static void __exit sisfb_remove_module(void)
6704{
6705        pci_unregister_driver(&sisfb_driver);
6706        printk(KERN_DEBUG "sisfb: Module unloaded\n");
6707}
6708
6709module_init(sisfb_init_module);
6710module_exit(sisfb_remove_module);
6711
6712MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6713MODULE_LICENSE("GPL");
6714MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6715
6716module_param(mem, int, 0);
6717module_param(noaccel, int, 0);
6718module_param(noypan, int, 0);
6719module_param(nomax, int, 0);
6720module_param(userom, int, 0);
6721module_param(useoem, int, 0);
6722module_param(mode, charp, 0);
6723module_param(vesa, int, 0);
6724module_param(rate, int, 0);
6725module_param(forcecrt1, int, 0);
6726module_param(forcecrt2type, charp, 0);
6727module_param(scalelcd, int, 0);
6728module_param(pdc, int, 0);
6729module_param(pdc1, int, 0);
6730module_param(specialtiming, charp, 0);
6731module_param(lvdshl, int, 0);
6732module_param(tvstandard, charp, 0);
6733module_param(tvxposoffset, int, 0);
6734module_param(tvyposoffset, int, 0);
6735module_param(nocrt2rate, int, 0);
6736#if !defined(__i386__) && !defined(__x86_64__)
6737module_param(resetcard, int, 0);
6738module_param(videoram, int, 0);
6739#endif
6740
6741MODULE_PARM_DESC(mem,
6742        "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6743          "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6744          "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6745          "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6746          "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6747          "The value is to be specified without 'KB'.\n");
6748
6749MODULE_PARM_DESC(noaccel,
6750        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6751          "(default: 0)\n");
6752
6753MODULE_PARM_DESC(noypan,
6754        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6755          "will be performed by redrawing the screen. (default: 0)\n");
6756
6757MODULE_PARM_DESC(nomax,
6758        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6759          "memory for the virtual screen in order to optimize scrolling performance. If\n"
6760          "this is set to anything other than 0, sisfb will not do this and thereby \n"
6761          "enable the user to positively specify a virtual Y size of the screen using\n"
6762          "fbset. (default: 0)\n");
6763
6764MODULE_PARM_DESC(mode,
6765        "\nSelects the desired default display mode in the format XxYxDepth,\n"
6766         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6767         "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6768         "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6769
6770MODULE_PARM_DESC(vesa,
6771        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6772         "0x117 (default: 0x0103)\n");
6773
6774MODULE_PARM_DESC(rate,
6775        "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6776          "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6777          "will be ignored (default: 60)\n");
6778
6779MODULE_PARM_DESC(forcecrt1,
6780        "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6781          "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6782          "0=CRT1 OFF) (default: [autodetected])\n");
6783
6784MODULE_PARM_DESC(forcecrt2type,
6785        "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6786          "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6787          "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6788          "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6789          "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6790          "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6791          "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6792          "depends on the very hardware in use. (default: [autodetected])\n");
6793
6794MODULE_PARM_DESC(scalelcd,
6795        "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6796          "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6797          "show black bars around the image, TMDS panels will probably do the scaling\n"
6798          "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6799
6800MODULE_PARM_DESC(pdc,
6801        "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6802          "should detect this correctly in most cases; however, sometimes this is not\n"
6803          "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6804          "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6805          "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6806          "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6807
6808#ifdef CONFIG_FB_SIS_315
6809MODULE_PARM_DESC(pdc1,
6810        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6811          "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6812          "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6813          "implemented yet.\n");
6814#endif
6815
6816MODULE_PARM_DESC(specialtiming,
6817        "\nPlease refer to documentation for more information on this option.\n");
6818
6819MODULE_PARM_DESC(lvdshl,
6820        "\nPlease refer to documentation for more information on this option.\n");
6821
6822MODULE_PARM_DESC(tvstandard,
6823        "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6824          "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6825
6826MODULE_PARM_DESC(tvxposoffset,
6827        "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6828          "Default: 0\n");
6829
6830MODULE_PARM_DESC(tvyposoffset,
6831        "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6832          "Default: 0\n");
6833
6834MODULE_PARM_DESC(nocrt2rate,
6835        "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6836          "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6837
6838#if !defined(__i386__) && !defined(__x86_64__)
6839#ifdef CONFIG_FB_SIS_300
6840MODULE_PARM_DESC(resetcard,
6841        "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6842          "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6843          "currently). Default: 0\n");
6844
6845MODULE_PARM_DESC(videoram,
6846        "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6847          "some non-x86 architectures where the memory auto detection fails. Only\n"
6848          "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6849#endif
6850#endif
6851
6852#endif     /*  /MODULE  */
6853
6854/* _GPL only for new symbols. */
6855EXPORT_SYMBOL(sis_malloc);
6856EXPORT_SYMBOL(sis_free);
6857EXPORT_SYMBOL_GPL(sis_malloc_new);
6858EXPORT_SYMBOL_GPL(sis_free_new);
6859
6860
6861
6862