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