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