root/drivers/video/fbdev/sis/sis_main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sisfb_setdefaultparms
  2. sisfb_search_vesamode
  3. sisfb_search_mode
  4. sisfb_get_vga_mode_from_kernel
  5. sisfb_search_crt2type
  6. sisfb_search_tvstd
  7. sisfb_search_specialtiming
  8. sisfb_detect_custom_timing
  9. sisfb_interpret_edid
  10. sisfb_handle_ddc
  11. sisfb_verify_rate
  12. sisfb_validate_mode
  13. sisfb_search_refresh_rate
  14. sisfb_bridgeisslave
  15. sisfballowretracecrt1
  16. sisfbcheckvretracecrt1
  17. sisfbwaitretracecrt1
  18. sisfbcheckvretracecrt2
  19. sisfb_CheckVBRetrace
  20. sisfb_setupvbblankflags
  21. sisfb_myblank
  22. sisfb_read_nbridge_pci_dword
  23. sisfb_write_nbridge_pci_dword
  24. sisfb_read_lpc_pci_dword
  25. sisfb_write_nbridge_pci_byte
  26. sisfb_read_mio_pci_word
  27. sisfb_get_cmap_len
  28. sisfb_set_vparms
  29. sisfb_calc_maxyres
  30. sisfb_calc_pitch
  31. sisfb_set_pitch
  32. sisfb_bpp_to_var
  33. sisfb_set_mode
  34. sisfb_do_set_var
  35. sisfb_set_base_CRT1
  36. sisfb_set_base_CRT2
  37. sisfb_pan_var
  38. sisfb_open
  39. sisfb_release
  40. sisfb_setcolreg
  41. sisfb_set_par
  42. sisfb_check_var
  43. sisfb_pan_display
  44. sisfb_blank
  45. sisfb_ioctl
  46. sisfb_get_fix
  47. sisfb_get_northbridge
  48. sisfb_get_dram_size
  49. sisfb_detect_VB_connect
  50. sisfb_test_DDC1
  51. sisfb_sense_crt1
  52. SiS_SenseLCD
  53. SISDoSense
  54. SiS_Sense30x
  55. SiS_SenseCh
  56. sisfb_get_VB_type
  57. sisfb_engine_init
  58. sisfb_detect_lcd_type
  59. sisfb_save_pdc_emi
  60. sisfb_getheapstart
  61. sisfb_getheapsize
  62. sisfb_heap_init
  63. sisfb_poh_new_node
  64. sisfb_poh_allocate
  65. sisfb_delete_node
  66. sisfb_insert_node
  67. sisfb_poh_free
  68. sisfb_free_node
  69. sis_int_malloc
  70. sis_malloc
  71. sis_malloc_new
  72. sis_int_free
  73. sis_free
  74. sis_free_new
  75. sisfb_check_engine_and_sync
  76. sisfb_pre_setmode
  77. sisfb_fixup_SR11
  78. sisfb_set_TVxposoffset
  79. sisfb_set_TVyposoffset
  80. sisfb_post_setmode
  81. sisfb_reset_mode
  82. sisfb_handle_command
  83. sisfb_setup
  84. sisfb_check_rom
  85. sisfb_find_rom
  86. sisfb_post_map_vram
  87. sisfb_post_300_buswidth
  88. sisfb_post_300_rwtest
  89. sisfb_post_300_ramsize
  90. sisfb_post_sis300
  91. sisfb_post_sis315330
  92. sisfb_xgi_is21
  93. sisfb_post_xgi_delay
  94. sisfb_find_host_bridge
  95. sisfb_post_xgi_rwtest
  96. sisfb_post_xgi_ramsize
  97. sisfb_post_xgi_setclocks
  98. sisfb_post_xgi_ddr2_mrs_default
  99. sisfb_post_xgi_ddr2_mrs_xg21
  100. sisfb_post_xgi_ddr2
  101. sisfb_post_xgi_ramtype
  102. sisfb_post_xgi
  103. sisfb_probe
  104. sisfb_remove
  105. sisfb_init
  106. sisfb_init_module
  107. sisfb_remove_module

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

/* [<][>][^][v][top][bottom][index][help] */