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