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