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