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