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