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