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