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