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