Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sis_main.c
Go to the documentation of this file.
1 /*
2  * SiS 300/540/630[S]/730[S],
3  * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
4  * XGI V3XT/V5/V8, Z7
5  * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
6  *
7  * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the named License,
12  * or any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22  *
23  * Author: Thomas Winischhofer <[email protected]>
24  *
25  * Author of (practically wiped) code base:
26  * SiS (www.sis.com)
27  * Copyright (C) 1999 Silicon Integrated Systems, Inc.
28  *
29  * See http://www.winischhofer.net/ for more information and updates
30  *
31  * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32  * which is (c) 1998 Gerd Knorr <[email protected]>
33  *
34  */
35 
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
42 #include <linux/mm.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
45 #include <linux/fb.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
52 #include <linux/fs.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
55 #include <asm/io.h>
56 #ifdef CONFIG_MTRR
57 #include <asm/mtrr.h>
58 #endif
59 
60 #include "sis.h"
61 #include "sis_main.h"
62 
63 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65 #warning sisfb will not work!
66 #endif
67 
68 static void sisfb_handle_command(struct sis_video_info *ivideo,
69  struct sisfb_cmd *sisfb_command);
70 
71 /* ------------------ Internal helper routines ----------------- */
72 
73 static void __init
74 sisfb_setdefaultparms(void)
75 {
76  sisfb_off = 0;
77  sisfb_parm_mem = 0;
78  sisfb_accel = -1;
79  sisfb_ypan = -1;
80  sisfb_max = -1;
81  sisfb_userom = -1;
82  sisfb_useoem = -1;
83  sisfb_mode_idx = -1;
84  sisfb_parm_rate = -1;
85  sisfb_crt1off = 0;
86  sisfb_forcecrt1 = -1;
87  sisfb_crt2type = -1;
88  sisfb_crt2flags = 0;
89  sisfb_pdc = 0xff;
90  sisfb_pdca = 0xff;
91  sisfb_scalelcd = -1;
92  sisfb_specialtiming = CUT_NONE;
93  sisfb_lvdshl = -1;
94  sisfb_dstn = 0;
95  sisfb_fstn = 0;
96  sisfb_tvplug = -1;
97  sisfb_tvstd = -1;
98  sisfb_tvxposoffset = 0;
99  sisfb_tvyposoffset = 0;
100  sisfb_nocrt2rate = 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
102  sisfb_resetcard = 0;
103  sisfb_videoram = 0;
104 #endif
105 }
106 
107 /* ------------- Parameter parsing -------------- */
108 
109 static void __devinit
110 sisfb_search_vesamode(unsigned int vesamode, bool quiet)
111 {
112  int i = 0, j = 0;
113 
114  /* We don't know the hardware specs yet and there is no ivideo */
115 
116  if(vesamode == 0) {
117  if(!quiet)
118  printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
119 
121 
122  return;
123  }
124 
125  vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
126 
127  while(sisbios_mode[i++].mode_no[0] != 0) {
128  if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
129  (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
130  if(sisfb_fstn) {
131  if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
132  sisbios_mode[i-1].mode_no[1] == 0x56 ||
133  sisbios_mode[i-1].mode_no[1] == 0x53)
134  continue;
135  } else {
136  if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
137  sisbios_mode[i-1].mode_no[1] == 0x5b)
138  continue;
139  }
140  sisfb_mode_idx = i - 1;
141  j = 1;
142  break;
143  }
144  }
145  if((!j) && !quiet)
146  printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
147 }
148 
149 static void __devinit
150 sisfb_search_mode(char *name, bool quiet)
151 {
152  unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
153  int i = 0;
154  char strbuf[16], strbuf1[20];
155  char *nameptr = name;
156 
157  /* We don't know the hardware specs yet and there is no ivideo */
158 
159  if(name == NULL) {
160  if(!quiet)
161  printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
162 
164  return;
165  }
166 
167  if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
168  if(!quiet)
169  printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
170 
172  return;
173  }
174 
175  if(strlen(name) <= 19) {
176  strcpy(strbuf1, name);
177  for(i = 0; i < strlen(strbuf1); i++) {
178  if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
179  }
180 
181  /* This does some fuzzy mode naming detection */
182  if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
183  if((rate <= 32) || (depth > 32)) {
184  j = rate; rate = depth; depth = j;
185  }
186  sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
187  nameptr = strbuf;
189  } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
190  sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
191  nameptr = strbuf;
192  } else {
193  xres = 0;
194  if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
195  sprintf(strbuf, "%ux%ux8", xres, yres);
196  nameptr = strbuf;
197  } else {
198  sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
199  return;
200  }
201  }
202  }
203 
204  i = 0; j = 0;
205  while(sisbios_mode[i].mode_no[0] != 0) {
206  if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
207  if(sisfb_fstn) {
208  if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
209  sisbios_mode[i-1].mode_no[1] == 0x56 ||
210  sisbios_mode[i-1].mode_no[1] == 0x53)
211  continue;
212  } else {
213  if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
214  sisbios_mode[i-1].mode_no[1] == 0x5b)
215  continue;
216  }
217  sisfb_mode_idx = i - 1;
218  j = 1;
219  break;
220  }
221  }
222 
223  if((!j) && !quiet)
224  printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
225 }
226 
227 #ifndef MODULE
228 static void __devinit
229 sisfb_get_vga_mode_from_kernel(void)
230 {
231 #ifdef CONFIG_X86
232  char mymode[32];
233  int mydepth = screen_info.lfb_depth;
234 
236 
237  if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
238  (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
239  (mydepth >= 8) && (mydepth <= 32) ) {
240 
241  if(mydepth == 24) mydepth = 32;
242 
243  sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
245  mydepth);
246 
248  "sisfb: Using vga mode %s pre-set by kernel as default\n",
249  mymode);
250 
251  sisfb_search_mode(mymode, true);
252  }
253 #endif
254  return;
255 }
256 #endif
257 
258 static void __init
259 sisfb_search_crt2type(const char *name)
260 {
261  int i = 0;
262 
263  /* We don't know the hardware specs yet and there is no ivideo */
264 
265  if(name == NULL) return;
266 
267  while(sis_crt2type[i].type_no != -1) {
268  if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
269  sisfb_crt2type = sis_crt2type[i].type_no;
270  sisfb_tvplug = sis_crt2type[i].tvplug_no;
271  sisfb_crt2flags = sis_crt2type[i].flags;
272  break;
273  }
274  i++;
275  }
276 
277  sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
278  sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
279 
280  if(sisfb_crt2type < 0)
281  printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
282 }
283 
284 static void __init
285 sisfb_search_tvstd(const char *name)
286 {
287  int i = 0;
288 
289  /* We don't know the hardware specs yet and there is no ivideo */
290 
291  if(name == NULL)
292  return;
293 
294  while(sis_tvtype[i].type_no != -1) {
295  if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
296  sisfb_tvstd = sis_tvtype[i].type_no;
297  break;
298  }
299  i++;
300  }
301 }
302 
303 static void __init
304 sisfb_search_specialtiming(const char *name)
305 {
306  int i = 0;
307  bool found = false;
308 
309  /* We don't know the hardware specs yet and there is no ivideo */
310 
311  if(name == NULL)
312  return;
313 
314  if(!strnicmp(name, "none", 4)) {
315  sisfb_specialtiming = CUT_FORCENONE;
316  printk(KERN_DEBUG "sisfb: Special timing disabled\n");
317  } else {
318  while(mycustomttable[i].chipID != 0) {
319  if(!strnicmp(name,mycustomttable[i].optionName,
320  strlen(mycustomttable[i].optionName))) {
321  sisfb_specialtiming = mycustomttable[i].SpecialID;
322  found = true;
323  printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
324  mycustomttable[i].vendorName,
325  mycustomttable[i].cardName,
326  mycustomttable[i].optionName);
327  break;
328  }
329  i++;
330  }
331  if(!found) {
332  printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
333  printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
334  i = 0;
335  while(mycustomttable[i].chipID != 0) {
336  printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
337  mycustomttable[i].optionName,
338  mycustomttable[i].vendorName,
339  mycustomttable[i].cardName);
340  i++;
341  }
342  }
343  }
344 }
345 
346 /* ----------- Various detection routines ----------- */
347 
348 static void __devinit
349 sisfb_detect_custom_timing(struct sis_video_info *ivideo)
350 {
351  unsigned char *biosver = NULL;
352  unsigned char *biosdate = NULL;
353  bool footprint;
354  u32 chksum = 0;
355  int i, j;
356 
357  if(ivideo->SiS_Pr.UseROM) {
358  biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
359  biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
360  for(i = 0; i < 32768; i++)
361  chksum += ivideo->SiS_Pr.VirtualRomBase[i];
362  }
363 
364  i = 0;
365  do {
366  if( (mycustomttable[i].chipID == ivideo->chip) &&
367  ((!strlen(mycustomttable[i].biosversion)) ||
368  (ivideo->SiS_Pr.UseROM &&
369  (!strncmp(mycustomttable[i].biosversion, biosver,
370  strlen(mycustomttable[i].biosversion))))) &&
371  ((!strlen(mycustomttable[i].biosdate)) ||
372  (ivideo->SiS_Pr.UseROM &&
373  (!strncmp(mycustomttable[i].biosdate, biosdate,
374  strlen(mycustomttable[i].biosdate))))) &&
375  ((!mycustomttable[i].bioschksum) ||
376  (ivideo->SiS_Pr.UseROM &&
377  (mycustomttable[i].bioschksum == chksum))) &&
378  (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
379  (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
380  footprint = true;
381  for(j = 0; j < 5; j++) {
382  if(mycustomttable[i].biosFootprintAddr[j]) {
383  if(ivideo->SiS_Pr.UseROM) {
384  if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
385  mycustomttable[i].biosFootprintData[j]) {
386  footprint = false;
387  }
388  } else
389  footprint = false;
390  }
391  }
392  if(footprint) {
393  ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
394  printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
395  mycustomttable[i].vendorName,
396  mycustomttable[i].cardName);
397  printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
398  mycustomttable[i].optionName);
399  break;
400  }
401  }
402  i++;
403  } while(mycustomttable[i].chipID);
404 }
405 
406 static bool __devinit
407 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
408 {
409  int i, j, xres, yres, refresh, index;
410  u32 emodes;
411 
412  if(buffer[0] != 0x00 || buffer[1] != 0xff ||
413  buffer[2] != 0xff || buffer[3] != 0xff ||
414  buffer[4] != 0xff || buffer[5] != 0xff ||
415  buffer[6] != 0xff || buffer[7] != 0x00) {
416  printk(KERN_DEBUG "sisfb: Bad EDID header\n");
417  return false;
418  }
419 
420  if(buffer[0x12] != 0x01) {
421  printk(KERN_INFO "sisfb: EDID version %d not supported\n",
422  buffer[0x12]);
423  return false;
424  }
425 
426  monitor->feature = buffer[0x18];
427 
428  if(!(buffer[0x14] & 0x80)) {
429  if(!(buffer[0x14] & 0x08)) {
431  "sisfb: WARNING: Monitor does not support separate syncs\n");
432  }
433  }
434 
435  if(buffer[0x13] >= 0x01) {
436  /* EDID V1 rev 1 and 2: Search for monitor descriptor
437  * to extract ranges
438  */
439  j = 0x36;
440  for(i=0; i<4; i++) {
441  if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
442  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
443  buffer[j + 4] == 0x00) {
444  monitor->hmin = buffer[j + 7];
445  monitor->hmax = buffer[j + 8];
446  monitor->vmin = buffer[j + 5];
447  monitor->vmax = buffer[j + 6];
448  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
449  monitor->datavalid = true;
450  break;
451  }
452  j += 18;
453  }
454  }
455 
456  if(!monitor->datavalid) {
457  /* Otherwise: Get a range from the list of supported
458  * Estabished Timings. This is not entirely accurate,
459  * because fixed frequency monitors are not supported
460  * that way.
461  */
462  monitor->hmin = 65535; monitor->hmax = 0;
463  monitor->vmin = 65535; monitor->vmax = 0;
464  monitor->dclockmax = 0;
465  emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
466  for(i = 0; i < 13; i++) {
467  if(emodes & sisfb_ddcsmodes[i].mask) {
468  if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
469  if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
470  if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
471  if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
472  if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
473  }
474  }
475  index = 0x26;
476  for(i = 0; i < 8; i++) {
477  xres = (buffer[index] + 31) * 8;
478  switch(buffer[index + 1] & 0xc0) {
479  case 0xc0: yres = (xres * 9) / 16; break;
480  case 0x80: yres = (xres * 4) / 5; break;
481  case 0x40: yres = (xres * 3) / 4; break;
482  default: yres = xres; break;
483  }
484  refresh = (buffer[index + 1] & 0x3f) + 60;
485  if((xres >= 640) && (yres >= 480)) {
486  for(j = 0; j < 8; j++) {
487  if((xres == sisfb_ddcfmodes[j].x) &&
488  (yres == sisfb_ddcfmodes[j].y) &&
489  (refresh == sisfb_ddcfmodes[j].v)) {
490  if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
491  if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
492  if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
493  if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
494  if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
495  }
496  }
497  }
498  index += 2;
499  }
500  if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
501  monitor->datavalid = true;
502  }
503  }
504 
505  return monitor->datavalid;
506 }
507 
508 static void __devinit
509 sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
510 {
511  unsigned short temp, i, realcrtno = crtno;
512  unsigned char buffer[256];
513 
514  monitor->datavalid = false;
515 
516  if(crtno) {
517  if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
518  else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
519  else return;
520  }
521 
522  if((ivideo->sisfb_crt1off) && (!crtno))
523  return;
524 
525  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
526  realcrtno, 0, &buffer[0], ivideo->vbflags2);
527  if((!temp) || (temp == 0xffff)) {
528  printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
529  return;
530  } else {
531  printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
532  printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
533  crtno + 1,
534  (temp & 0x1a) ? "" : "[none of the supported]",
535  (temp & 0x02) ? "2 " : "",
536  (temp & 0x08) ? "D&P" : "",
537  (temp & 0x10) ? "FPDI-2" : "");
538  if(temp & 0x02) {
539  i = 3; /* Number of retrys */
540  do {
541  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
542  realcrtno, 1, &buffer[0], ivideo->vbflags2);
543  } while((temp) && i--);
544  if(!temp) {
545  if(sisfb_interpret_edid(monitor, &buffer[0])) {
546  printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
547  monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
548  monitor->dclockmax / 1000);
549  } else {
550  printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
551  }
552  } else {
553  printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
554  }
555  } else {
556  printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
557  }
558  }
559 }
560 
561 /* -------------- Mode validation --------------- */
562 
563 static bool
564 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
565  int mode_idx, int rate_idx, int rate)
566 {
567  int htotal, vtotal;
568  unsigned int dclock, hsync;
569 
570  if(!monitor->datavalid)
571  return true;
572 
573  if(mode_idx < 0)
574  return false;
575 
576  /* Skip for 320x200, 320x240, 640x400 */
577  switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
578  case 0x59:
579  case 0x41:
580  case 0x4f:
581  case 0x50:
582  case 0x56:
583  case 0x53:
584  case 0x2f:
585  case 0x5d:
586  case 0x5e:
587  return true;
588 #ifdef CONFIG_FB_SIS_315
589  case 0x5a:
590  case 0x5b:
591  if(ivideo->sisvga_engine == SIS_315_VGA) return true;
592 #endif
593  }
594 
595  if(rate < (monitor->vmin - 1))
596  return false;
597  if(rate > (monitor->vmax + 1))
598  return false;
599 
600  if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
601  sisbios_mode[mode_idx].mode_no[ivideo->mni],
602  &htotal, &vtotal, rate_idx)) {
603  dclock = (htotal * vtotal * rate) / 1000;
604  if(dclock > (monitor->dclockmax + 1000))
605  return false;
606  hsync = dclock / htotal;
607  if(hsync < (monitor->hmin - 1))
608  return false;
609  if(hsync > (monitor->hmax + 1))
610  return false;
611  } else {
612  return false;
613  }
614  return true;
615 }
616 
617 static int
618 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
619 {
620  u16 xres=0, yres, myres;
621 
622 #ifdef CONFIG_FB_SIS_300
623  if(ivideo->sisvga_engine == SIS_300_VGA) {
624  if(!(sisbios_mode[myindex].chipset & MD_SIS300))
625  return -1 ;
626  }
627 #endif
628 #ifdef CONFIG_FB_SIS_315
629  if(ivideo->sisvga_engine == SIS_315_VGA) {
630  if(!(sisbios_mode[myindex].chipset & MD_SIS315))
631  return -1;
632  }
633 #endif
634 
635  myres = sisbios_mode[myindex].yres;
636 
637  switch(vbflags & VB_DISPTYPE_DISP2) {
638 
639  case CRT2_LCD:
640  xres = ivideo->lcdxres; yres = ivideo->lcdyres;
641 
642  if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
643  (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
644  if(sisbios_mode[myindex].xres > xres)
645  return -1;
646  if(myres > yres)
647  return -1;
648  }
649 
650  if(ivideo->sisfb_fstn) {
651  if(sisbios_mode[myindex].xres == 320) {
652  if(myres == 240) {
653  switch(sisbios_mode[myindex].mode_no[1]) {
654  case 0x50: myindex = MODE_FSTN_8; break;
655  case 0x56: myindex = MODE_FSTN_16; break;
656  case 0x53: return -1;
657  }
658  }
659  }
660  }
661 
662  if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
663  sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
664  ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
665  return -1;
666  }
667  break;
668 
669  case CRT2_TV:
670  if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
671  sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
672  return -1;
673  }
674  break;
675 
676  case CRT2_VGA:
677  if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
678  sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
679  return -1;
680  }
681  break;
682  }
683 
684  return myindex;
685 }
686 
687 static u8
688 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
689 {
690  int i = 0;
691  u16 xres = sisbios_mode[mode_idx].xres;
692  u16 yres = sisbios_mode[mode_idx].yres;
693 
694  ivideo->rate_idx = 0;
695  while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
696  if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
697  if(sisfb_vrate[i].refresh == rate) {
698  ivideo->rate_idx = sisfb_vrate[i].idx;
699  break;
700  } else if(sisfb_vrate[i].refresh > rate) {
701  if((sisfb_vrate[i].refresh - rate) <= 3) {
702  DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
703  rate, sisfb_vrate[i].refresh);
704  ivideo->rate_idx = sisfb_vrate[i].idx;
705  ivideo->refresh_rate = sisfb_vrate[i].refresh;
706  } else if((sisfb_vrate[i].idx != 1) &&
707  ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
708  DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
709  rate, sisfb_vrate[i-1].refresh);
710  ivideo->rate_idx = sisfb_vrate[i-1].idx;
711  ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
712  }
713  break;
714  } else if((rate - sisfb_vrate[i].refresh) <= 2) {
715  DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
716  rate, sisfb_vrate[i].refresh);
717  ivideo->rate_idx = sisfb_vrate[i].idx;
718  break;
719  }
720  }
721  i++;
722  }
723  if(ivideo->rate_idx > 0) {
724  return ivideo->rate_idx;
725  } else {
726  printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
727  rate, xres, yres);
728  return 0;
729  }
730 }
731 
732 static bool
733 sisfb_bridgeisslave(struct sis_video_info *ivideo)
734 {
735  unsigned char P1_00;
736 
737  if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
738  return false;
739 
740  P1_00 = SiS_GetReg(SISPART1, 0x00);
741  if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
742  ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
743  return true;
744  } else {
745  return false;
746  }
747 }
748 
749 static bool
750 sisfballowretracecrt1(struct sis_video_info *ivideo)
751 {
752  u8 temp;
753 
754  temp = SiS_GetReg(SISCR, 0x17);
755  if(!(temp & 0x80))
756  return false;
757 
758  temp = SiS_GetReg(SISSR, 0x1f);
759  if(temp & 0xc0)
760  return false;
761 
762  return true;
763 }
764 
765 static bool
766 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
767 {
768  if(!sisfballowretracecrt1(ivideo))
769  return false;
770 
771  if (SiS_GetRegByte(SISINPSTAT) & 0x08)
772  return true;
773  else
774  return false;
775 }
776 
777 static void
778 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
779 {
780  int watchdog;
781 
782  if(!sisfballowretracecrt1(ivideo))
783  return;
784 
785  watchdog = 65536;
786  while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
787  watchdog = 65536;
788  while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
789 }
790 
791 static bool
792 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
793 {
794  unsigned char temp, reg;
795 
796  switch(ivideo->sisvga_engine) {
797  case SIS_300_VGA: reg = 0x25; break;
798  case SIS_315_VGA: reg = 0x30; break;
799  default: return false;
800  }
801 
802  temp = SiS_GetReg(SISPART1, reg);
803  if(temp & 0x02)
804  return true;
805  else
806  return false;
807 }
808 
809 static bool
810 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
811 {
812  if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
813  if(!sisfb_bridgeisslave(ivideo)) {
814  return sisfbcheckvretracecrt2(ivideo);
815  }
816  }
817  return sisfbcheckvretracecrt1(ivideo);
818 }
819 
820 static u32
821 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
822 {
823  u8 idx, reg1, reg2, reg3, reg4;
824  u32 ret = 0;
825 
826  (*vcount) = (*hcount) = 0;
827 
828  if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
829 
830  ret |= (FB_VBLANK_HAVE_VSYNC |
835  switch(ivideo->sisvga_engine) {
836  case SIS_300_VGA: idx = 0x25; break;
837  default:
838  case SIS_315_VGA: idx = 0x30; break;
839  }
840  reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
841  reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
842  reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
843  reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
844  if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
845  if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
846  if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
847  (*vcount) = reg3 | ((reg4 & 0x70) << 4);
848  (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
849 
850  } else if(sisfballowretracecrt1(ivideo)) {
851 
852  ret |= (FB_VBLANK_HAVE_VSYNC |
856  reg1 = SiS_GetRegByte(SISINPSTAT);
857  if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
858  if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
859  reg1 = SiS_GetReg(SISCR, 0x20);
860  reg1 = SiS_GetReg(SISCR, 0x1b);
861  reg2 = SiS_GetReg(SISCR, 0x1c);
862  reg3 = SiS_GetReg(SISCR, 0x1d);
863  (*vcount) = reg2 | ((reg3 & 0x07) << 8);
864  (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
865  }
866 
867  return ret;
868 }
869 
870 static int
871 sisfb_myblank(struct sis_video_info *ivideo, int blank)
872 {
873  u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
874  bool backlight = true;
875 
876  switch(blank) {
877  case FB_BLANK_UNBLANK: /* on */
878  sr01 = 0x00;
879  sr11 = 0x00;
880  sr1f = 0x00;
881  cr63 = 0x00;
882  p2_0 = 0x20;
883  p1_13 = 0x00;
884  backlight = true;
885  break;
886  case FB_BLANK_NORMAL: /* blank */
887  sr01 = 0x20;
888  sr11 = 0x00;
889  sr1f = 0x00;
890  cr63 = 0x00;
891  p2_0 = 0x20;
892  p1_13 = 0x00;
893  backlight = true;
894  break;
895  case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
896  sr01 = 0x20;
897  sr11 = 0x08;
898  sr1f = 0x80;
899  cr63 = 0x40;
900  p2_0 = 0x40;
901  p1_13 = 0x80;
902  backlight = false;
903  break;
904  case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
905  sr01 = 0x20;
906  sr11 = 0x08;
907  sr1f = 0x40;
908  cr63 = 0x40;
909  p2_0 = 0x80;
910  p1_13 = 0x40;
911  backlight = false;
912  break;
913  case FB_BLANK_POWERDOWN: /* off */
914  sr01 = 0x20;
915  sr11 = 0x08;
916  sr1f = 0xc0;
917  cr63 = 0x40;
918  p2_0 = 0xc0;
919  p1_13 = 0xc0;
920  backlight = false;
921  break;
922  default:
923  return 1;
924  }
925 
926  if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
927 
928  if( (!ivideo->sisfb_thismonitor.datavalid) ||
929  ((ivideo->sisfb_thismonitor.datavalid) &&
930  (ivideo->sisfb_thismonitor.feature & 0xe0))) {
931 
932  if(ivideo->sisvga_engine == SIS_315_VGA) {
933  SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
934  }
935 
936  if(!(sisfb_bridgeisslave(ivideo))) {
937  SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
938  SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
939  }
940  }
941 
942  }
943 
944  if(ivideo->currentvbflags & CRT2_LCD) {
945 
946  if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
947  if(backlight) {
948  SiS_SiS30xBLOn(&ivideo->SiS_Pr);
949  } else {
950  SiS_SiS30xBLOff(&ivideo->SiS_Pr);
951  }
952  } else if(ivideo->sisvga_engine == SIS_315_VGA) {
953 #ifdef CONFIG_FB_SIS_315
954  if(ivideo->vbflags2 & VB2_CHRONTEL) {
955  if(backlight) {
956  SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
957  } else {
958  SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
959  }
960  }
961 #endif
962  }
963 
964  if(((ivideo->sisvga_engine == SIS_300_VGA) &&
965  (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
966  ((ivideo->sisvga_engine == SIS_315_VGA) &&
967  ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
968  SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
969  }
970 
971  if(ivideo->sisvga_engine == SIS_300_VGA) {
972  if((ivideo->vbflags2 & VB2_30xB) &&
973  (!(ivideo->vbflags2 & VB2_30xBDH))) {
974  SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
975  }
976  } else if(ivideo->sisvga_engine == SIS_315_VGA) {
977  if((ivideo->vbflags2 & VB2_30xB) &&
978  (!(ivideo->vbflags2 & VB2_30xBDH))) {
979  SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
980  }
981  }
982 
983  } else if(ivideo->currentvbflags & CRT2_VGA) {
984 
985  if(ivideo->vbflags2 & VB2_30xB) {
986  SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
987  }
988 
989  }
990 
991  return 0;
992 }
993 
994 /* ------------- Callbacks from init.c/init301.c -------------- */
995 
996 #ifdef CONFIG_FB_SIS_300
997 unsigned int
998 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
999 {
1000  struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1001  u32 val = 0;
1002 
1003  pci_read_config_dword(ivideo->nbridge, reg, &val);
1004  return (unsigned int)val;
1005 }
1006 
1007 void
1008 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1009 {
1010  struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1011 
1012  pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1013 }
1014 
1015 unsigned int
1016 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1017 {
1018  struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1019  u32 val = 0;
1020 
1021  if(!ivideo->lpcdev) return 0;
1022 
1023  pci_read_config_dword(ivideo->lpcdev, reg, &val);
1024  return (unsigned int)val;
1025 }
1026 #endif
1027 
1028 #ifdef CONFIG_FB_SIS_315
1029 void
1030 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1031 {
1032  struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1033 
1034  pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1035 }
1036 
1037 unsigned int
1038 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1039 {
1040  struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1041  u16 val = 0;
1042 
1043  if(!ivideo->lpcdev) return 0;
1044 
1045  pci_read_config_word(ivideo->lpcdev, reg, &val);
1046  return (unsigned int)val;
1047 }
1048 #endif
1049 
1050 /* ----------- FBDev related routines for all series ----------- */
1051 
1052 static int
1053 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1054 {
1055  return (var->bits_per_pixel == 8) ? 256 : 16;
1056 }
1057 
1058 static void
1059 sisfb_set_vparms(struct sis_video_info *ivideo)
1060 {
1061  switch(ivideo->video_bpp) {
1062  case 8:
1063  ivideo->DstColor = 0x0000;
1064  ivideo->SiS310_AccelDepth = 0x00000000;
1065  ivideo->video_cmap_len = 256;
1066  break;
1067  case 16:
1068  ivideo->DstColor = 0x8000;
1069  ivideo->SiS310_AccelDepth = 0x00010000;
1070  ivideo->video_cmap_len = 16;
1071  break;
1072  case 32:
1073  ivideo->DstColor = 0xC000;
1074  ivideo->SiS310_AccelDepth = 0x00020000;
1075  ivideo->video_cmap_len = 16;
1076  break;
1077  default:
1078  ivideo->video_cmap_len = 16;
1079  printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1080  ivideo->accel = 0;
1081  }
1082 }
1083 
1084 static int
1085 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1086 {
1087  int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1088 
1089  if(maxyres > 32767) maxyres = 32767;
1090 
1091  return maxyres;
1092 }
1093 
1094 static void
1095 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1096 {
1097  ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1098  ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1099  if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1100  if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1101  ivideo->scrnpitchCRT1 <<= 1;
1102  }
1103  }
1104 }
1105 
1106 static void
1107 sisfb_set_pitch(struct sis_video_info *ivideo)
1108 {
1109  bool isslavemode = false;
1110  unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1111  unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1112 
1113  if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1114 
1115  /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1116  if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1117  SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1118  SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1119  }
1120 
1121  /* We must not set the pitch for CRT2 if bridge is in slave mode */
1122  if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1123  SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1124  SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1125  SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1126  }
1127 }
1128 
1129 static void
1130 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1131 {
1132  ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1133 
1134  switch(var->bits_per_pixel) {
1135  case 8:
1136  var->red.offset = var->green.offset = var->blue.offset = 0;
1137  var->red.length = var->green.length = var->blue.length = 8;
1138  break;
1139  case 16:
1140  var->red.offset = 11;
1141  var->red.length = 5;
1142  var->green.offset = 5;
1143  var->green.length = 6;
1144  var->blue.offset = 0;
1145  var->blue.length = 5;
1146  var->transp.offset = 0;
1147  var->transp.length = 0;
1148  break;
1149  case 32:
1150  var->red.offset = 16;
1151  var->red.length = 8;
1152  var->green.offset = 8;
1153  var->green.length = 8;
1154  var->blue.offset = 0;
1155  var->blue.length = 8;
1156  var->transp.offset = 24;
1157  var->transp.length = 8;
1158  break;
1159  }
1160 }
1161 
1162 static int
1163 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1164 {
1165  unsigned short modeno = ivideo->mode_no;
1166 
1167  /* >=2.6.12's fbcon clears the screen anyway */
1168  modeno |= 0x80;
1169 
1171 
1172  sisfb_pre_setmode(ivideo);
1173 
1174  if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1175  printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1176  return -EINVAL;
1177  }
1178 
1180 
1181  sisfb_post_setmode(ivideo);
1182 
1183  return 0;
1184 }
1185 
1186 
1187 static int
1188 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1189 {
1190  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1191  unsigned int htotal = 0, vtotal = 0;
1192  unsigned int drate = 0, hrate = 0;
1193  int found_mode = 0, ret;
1194  int old_mode;
1195  u32 pixclock;
1196 
1197  htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1198 
1199  vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1200 
1201  pixclock = var->pixclock;
1202 
1203  if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1204  vtotal += var->yres;
1205  vtotal <<= 1;
1206  } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1207  vtotal += var->yres;
1208  vtotal <<= 2;
1209  } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1210  vtotal += var->yres;
1211  vtotal <<= 1;
1212  } else vtotal += var->yres;
1213 
1214  if(!(htotal) || !(vtotal)) {
1215  DPRINTK("sisfb: Invalid 'var' information\n");
1216  return -EINVAL;
1217  }
1218 
1219  if(pixclock && htotal && vtotal) {
1220  drate = 1000000000 / pixclock;
1221  hrate = (drate * 1000) / htotal;
1222  ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1223  } else {
1224  ivideo->refresh_rate = 60;
1225  }
1226 
1227  old_mode = ivideo->sisfb_mode_idx;
1228  ivideo->sisfb_mode_idx = 0;
1229 
1230  while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1231  (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1232  if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1233  (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1234  (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1235  ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1236  found_mode = 1;
1237  break;
1238  }
1239  ivideo->sisfb_mode_idx++;
1240  }
1241 
1242  if(found_mode) {
1243  ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1244  ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1245  } else {
1246  ivideo->sisfb_mode_idx = -1;
1247  }
1248 
1249  if(ivideo->sisfb_mode_idx < 0) {
1250  printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1251  var->yres, var->bits_per_pixel);
1252  ivideo->sisfb_mode_idx = old_mode;
1253  return -EINVAL;
1254  }
1255 
1256  ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1257 
1258  if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1259  ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1260  ivideo->refresh_rate = 60;
1261  }
1262 
1263  if(isactive) {
1264  /* If acceleration to be used? Need to know
1265  * before pre/post_set_mode()
1266  */
1267  ivideo->accel = 0;
1268 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1269 #ifdef STUPID_ACCELF_TEXT_SHIT
1270  if(var->accel_flags & FB_ACCELF_TEXT) {
1271  info->flags &= ~FBINFO_HWACCEL_DISABLED;
1272  } else {
1273  info->flags |= FBINFO_HWACCEL_DISABLED;
1274  }
1275 #endif
1276  if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1277 #else
1278  if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1279 #endif
1280 
1281  if((ret = sisfb_set_mode(ivideo, 1))) {
1282  return ret;
1283  }
1284 
1285  ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1286  ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1287  ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1288 
1289  sisfb_calc_pitch(ivideo, var);
1290  sisfb_set_pitch(ivideo);
1291 
1292  sisfb_set_vparms(ivideo);
1293 
1294  ivideo->current_width = ivideo->video_width;
1295  ivideo->current_height = ivideo->video_height;
1296  ivideo->current_bpp = ivideo->video_bpp;
1297  ivideo->current_htotal = htotal;
1298  ivideo->current_vtotal = vtotal;
1299  ivideo->current_linelength = ivideo->video_linelength;
1300  ivideo->current_pixclock = var->pixclock;
1301  ivideo->current_refresh_rate = ivideo->refresh_rate;
1302  ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1303  }
1304 
1305  return 0;
1306 }
1307 
1308 static void
1309 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1310 {
1312 
1313  SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1314  SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1315  SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1316  if(ivideo->sisvga_engine == SIS_315_VGA) {
1317  SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1318  }
1319 }
1320 
1321 static void
1322 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1323 {
1324  if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1325  SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1326  SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1327  SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1328  SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1329  if(ivideo->sisvga_engine == SIS_315_VGA) {
1330  SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1331  }
1332  }
1333 }
1334 
1335 static int
1336 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1337  struct fb_var_screeninfo *var)
1338 {
1339  ivideo->current_base = var->yoffset * info->var.xres_virtual
1340  + var->xoffset;
1341 
1342  /* calculate base bpp dep. */
1343  switch (info->var.bits_per_pixel) {
1344  case 32:
1345  break;
1346  case 16:
1347  ivideo->current_base >>= 1;
1348  break;
1349  case 8:
1350  default:
1351  ivideo->current_base >>= 2;
1352  break;
1353  }
1354 
1355  ivideo->current_base += (ivideo->video_offset >> 2);
1356 
1357  sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1358  sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1359 
1360  return 0;
1361 }
1362 
1363 static int
1364 sisfb_open(struct fb_info *info, int user)
1365 {
1366  return 0;
1367 }
1368 
1369 static int
1370 sisfb_release(struct fb_info *info, int user)
1371 {
1372  return 0;
1373 }
1374 
1375 static int
1376 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1377  unsigned transp, struct fb_info *info)
1378 {
1379  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1380 
1381  if(regno >= sisfb_get_cmap_len(&info->var))
1382  return 1;
1383 
1384  switch(info->var.bits_per_pixel) {
1385  case 8:
1386  SiS_SetRegByte(SISDACA, regno);
1387  SiS_SetRegByte(SISDACD, (red >> 10));
1388  SiS_SetRegByte(SISDACD, (green >> 10));
1389  SiS_SetRegByte(SISDACD, (blue >> 10));
1390  if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1391  SiS_SetRegByte(SISDAC2A, regno);
1392  SiS_SetRegByte(SISDAC2D, (red >> 8));
1393  SiS_SetRegByte(SISDAC2D, (green >> 8));
1394  SiS_SetRegByte(SISDAC2D, (blue >> 8));
1395  }
1396  break;
1397  case 16:
1398  if (regno >= 16)
1399  break;
1400 
1401  ((u32 *)(info->pseudo_palette))[regno] =
1402  (red & 0xf800) |
1403  ((green & 0xfc00) >> 5) |
1404  ((blue & 0xf800) >> 11);
1405  break;
1406  case 32:
1407  if (regno >= 16)
1408  break;
1409 
1410  red >>= 8;
1411  green >>= 8;
1412  blue >>= 8;
1413  ((u32 *)(info->pseudo_palette))[regno] =
1414  (red << 16) | (green << 8) | (blue);
1415  break;
1416  }
1417  return 0;
1418 }
1419 
1420 static int
1421 sisfb_set_par(struct fb_info *info)
1422 {
1423  int err;
1424 
1425  if((err = sisfb_do_set_var(&info->var, 1, info)))
1426  return err;
1427 
1428  sisfb_get_fix(&info->fix, -1, info);
1429 
1430  return 0;
1431 }
1432 
1433 static int
1434 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1435 {
1436  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1437  unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1438  unsigned int drate = 0, hrate = 0, maxyres;
1439  int found_mode = 0;
1440  int refresh_rate, search_idx, tidx;
1441  bool recalc_clock = false;
1442  u32 pixclock;
1443 
1444  htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1445 
1446  vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1447 
1448  pixclock = var->pixclock;
1449 
1450  if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1451  vtotal += var->yres;
1452  vtotal <<= 1;
1453  } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1454  vtotal += var->yres;
1455  vtotal <<= 2;
1456  } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1457  vtotal += var->yres;
1458  vtotal <<= 1;
1459  } else
1460  vtotal += var->yres;
1461 
1462  if(!(htotal) || !(vtotal)) {
1463  SISFAIL("sisfb: no valid timing data");
1464  }
1465 
1466  search_idx = 0;
1467  while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1468  (sisbios_mode[search_idx].xres <= var->xres) ) {
1469  if( (sisbios_mode[search_idx].xres == var->xres) &&
1470  (sisbios_mode[search_idx].yres == var->yres) &&
1471  (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1472  if((tidx = sisfb_validate_mode(ivideo, search_idx,
1473  ivideo->currentvbflags)) > 0) {
1474  found_mode = 1;
1475  search_idx = tidx;
1476  break;
1477  }
1478  }
1479  search_idx++;
1480  }
1481 
1482  if(!found_mode) {
1483  search_idx = 0;
1484  while(sisbios_mode[search_idx].mode_no[0] != 0) {
1485  if( (var->xres <= sisbios_mode[search_idx].xres) &&
1486  (var->yres <= sisbios_mode[search_idx].yres) &&
1487  (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1488  if((tidx = sisfb_validate_mode(ivideo,search_idx,
1489  ivideo->currentvbflags)) > 0) {
1490  found_mode = 1;
1491  search_idx = tidx;
1492  break;
1493  }
1494  }
1495  search_idx++;
1496  }
1497  if(found_mode) {
1499  "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1500  var->xres, var->yres, var->bits_per_pixel,
1501  sisbios_mode[search_idx].xres,
1502  sisbios_mode[search_idx].yres,
1503  var->bits_per_pixel);
1504  var->xres = sisbios_mode[search_idx].xres;
1505  var->yres = sisbios_mode[search_idx].yres;
1506  } else {
1508  "sisfb: Failed to find supported mode near %dx%dx%d\n",
1509  var->xres, var->yres, var->bits_per_pixel);
1510  return -EINVAL;
1511  }
1512  }
1513 
1514  if( ((ivideo->vbflags2 & VB2_LVDS) ||
1515  ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1516  (var->bits_per_pixel == 8) ) {
1517  /* Slave modes on LVDS and 301B-DH */
1518  refresh_rate = 60;
1519  recalc_clock = true;
1520  } else if( (ivideo->current_htotal == htotal) &&
1521  (ivideo->current_vtotal == vtotal) &&
1522  (ivideo->current_pixclock == pixclock) ) {
1523  /* x=x & y=y & c=c -> assume depth change */
1524  drate = 1000000000 / pixclock;
1525  hrate = (drate * 1000) / htotal;
1526  refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1527  } else if( ( (ivideo->current_htotal != htotal) ||
1528  (ivideo->current_vtotal != vtotal) ) &&
1529  (ivideo->current_pixclock == var->pixclock) ) {
1530  /* x!=x | y!=y & c=c -> invalid pixclock */
1531  if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1532  refresh_rate =
1533  ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1534  } else if(ivideo->sisfb_parm_rate != -1) {
1535  /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1536  refresh_rate = ivideo->sisfb_parm_rate;
1537  } else {
1538  refresh_rate = 60;
1539  }
1540  recalc_clock = true;
1541  } else if((pixclock) && (htotal) && (vtotal)) {
1542  drate = 1000000000 / pixclock;
1543  hrate = (drate * 1000) / htotal;
1544  refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1545  } else if(ivideo->current_refresh_rate) {
1546  refresh_rate = ivideo->current_refresh_rate;
1547  recalc_clock = true;
1548  } else {
1549  refresh_rate = 60;
1550  recalc_clock = true;
1551  }
1552 
1553  myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1554 
1555  /* Eventually recalculate timing and clock */
1556  if(recalc_clock) {
1557  if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1558  var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1559  sisbios_mode[search_idx].mode_no[ivideo->mni],
1560  myrateindex));
1562  sisbios_mode[search_idx].mode_no[ivideo->mni],
1563  myrateindex, var);
1564  if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1565  var->pixclock <<= 1;
1566  }
1567  }
1568 
1569  if(ivideo->sisfb_thismonitor.datavalid) {
1570  if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1571  myrateindex, refresh_rate)) {
1573  "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1574  }
1575  }
1576 
1577  /* Adapt RGB settings */
1578  sisfb_bpp_to_var(ivideo, var);
1579 
1580  /* Sanity check for offsets */
1581  if(var->xoffset < 0) var->xoffset = 0;
1582  if(var->yoffset < 0) var->yoffset = 0;
1583 
1584  if(var->xres > var->xres_virtual)
1585  var->xres_virtual = var->xres;
1586 
1587  if(ivideo->sisfb_ypan) {
1588  maxyres = sisfb_calc_maxyres(ivideo, var);
1589  if(ivideo->sisfb_max) {
1590  var->yres_virtual = maxyres;
1591  } else {
1592  if(var->yres_virtual > maxyres) {
1593  var->yres_virtual = maxyres;
1594  }
1595  }
1596  if(var->yres_virtual <= var->yres) {
1597  var->yres_virtual = var->yres;
1598  }
1599  } else {
1600  if(var->yres != var->yres_virtual) {
1601  var->yres_virtual = var->yres;
1602  }
1603  var->xoffset = 0;
1604  var->yoffset = 0;
1605  }
1606 
1607  /* Truncate offsets to maximum if too high */
1608  if(var->xoffset > var->xres_virtual - var->xres) {
1609  var->xoffset = var->xres_virtual - var->xres - 1;
1610  }
1611 
1612  if(var->yoffset > var->yres_virtual - var->yres) {
1613  var->yoffset = var->yres_virtual - var->yres - 1;
1614  }
1615 
1616  /* Set everything else to 0 */
1617  var->red.msb_right =
1618  var->green.msb_right =
1619  var->blue.msb_right =
1620  var->transp.offset =
1621  var->transp.length =
1622  var->transp.msb_right = 0;
1623 
1624  return 0;
1625 }
1626 
1627 static int
1628 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1629 {
1630  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1631  int err;
1632 
1633  if (var->vmode & FB_VMODE_YWRAP)
1634  return -EINVAL;
1635 
1636  if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1637  var->yoffset + info->var.yres > info->var.yres_virtual)
1638  return -EINVAL;
1639 
1640  err = sisfb_pan_var(ivideo, info, var);
1641  if (err < 0)
1642  return err;
1643 
1644  info->var.xoffset = var->xoffset;
1645  info->var.yoffset = var->yoffset;
1646 
1647  return 0;
1648 }
1649 
1650 static int
1651 sisfb_blank(int blank, struct fb_info *info)
1652 {
1653  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1654 
1655  return sisfb_myblank(ivideo, blank);
1656 }
1657 
1658 /* ----------- FBDev related routines for all series ---------- */
1659 
1660 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1661  unsigned long arg)
1662 {
1663  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1664  struct sis_memreq sismemreq;
1665  struct fb_vblank sisvbblank;
1666  u32 gpu32 = 0;
1667 #ifndef __user
1668 #define __user
1669 #endif
1670  u32 __user *argp = (u32 __user *)arg;
1671 
1672  switch(cmd) {
1673  case FBIO_ALLOC:
1674  if(!capable(CAP_SYS_RAWIO))
1675  return -EPERM;
1676 
1677  if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1678  return -EFAULT;
1679 
1680  sis_malloc(&sismemreq);
1681 
1682  if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1683  sis_free((u32)sismemreq.offset);
1684  return -EFAULT;
1685  }
1686  break;
1687 
1688  case FBIO_FREE:
1689  if(!capable(CAP_SYS_RAWIO))
1690  return -EPERM;
1691 
1692  if(get_user(gpu32, argp))
1693  return -EFAULT;
1694 
1695  sis_free(gpu32);
1696  break;
1697 
1698  case FBIOGET_VBLANK:
1699 
1700  memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1701 
1702  sisvbblank.count = 0;
1703  sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1704 
1705  if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1706  return -EFAULT;
1707 
1708  break;
1709 
1710  case SISFB_GET_INFO_SIZE:
1711  return put_user(sizeof(struct sisfb_info), argp);
1712 
1713  case SISFB_GET_INFO_OLD:
1714  if(ivideo->warncount++ < 10)
1716  "sisfb: Deprecated ioctl call received - update your application!\n");
1717  case SISFB_GET_INFO: /* For communication with X driver */
1718  ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1719  ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1720  ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1721  ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1722  ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1723  ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1724  ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1725  ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1726  if(ivideo->modechanged) {
1727  ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1728  } else {
1729  ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1730  }
1731  ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1732  ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1733  ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1734  ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1735  ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1736  ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1737  ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1738  ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1739  ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1740  ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1741  ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1742  ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1743  ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1744  ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1745  ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1746  ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1747  ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1748  ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1749  ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1750  ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1751  ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1752  ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1753  ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1754  ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1755  ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1756  ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1757  ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1758  ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1759 
1760  if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1761  sizeof(ivideo->sisfb_infoblock)))
1762  return -EFAULT;
1763 
1764  break;
1765 
1767  if(ivideo->warncount++ < 10)
1769  "sisfb: Deprecated ioctl call received - update your application!\n");
1770  case SISFB_GET_VBRSTATUS:
1771  if(sisfb_CheckVBRetrace(ivideo))
1772  return put_user((u32)1, argp);
1773  else
1774  return put_user((u32)0, argp);
1775 
1777  if(ivideo->warncount++ < 10)
1779  "sisfb: Deprecated ioctl call received - update your application!\n");
1781  if(ivideo->sisfb_max)
1782  return put_user((u32)1, argp);
1783  else
1784  return put_user((u32)0, argp);
1785 
1787  if(ivideo->warncount++ < 10)
1789  "sisfb: Deprecated ioctl call received - update your application!\n");
1791  if(get_user(gpu32, argp))
1792  return -EFAULT;
1793 
1794  ivideo->sisfb_max = (gpu32) ? 1 : 0;
1795  break;
1796 
1797  case SISFB_SET_TVPOSOFFSET:
1798  if(get_user(gpu32, argp))
1799  return -EFAULT;
1800 
1801  sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1802  sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1803  break;
1804 
1805  case SISFB_GET_TVPOSOFFSET:
1806  return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1807  argp);
1808 
1809  case SISFB_COMMAND:
1810  if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1811  sizeof(struct sisfb_cmd)))
1812  return -EFAULT;
1813 
1814  sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1815 
1816  if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1817  sizeof(struct sisfb_cmd)))
1818  return -EFAULT;
1819 
1820  break;
1821 
1822  case SISFB_SET_LOCK:
1823  if(get_user(gpu32, argp))
1824  return -EFAULT;
1825 
1826  ivideo->sisfblocked = (gpu32) ? 1 : 0;
1827  break;
1828 
1829  default:
1830 #ifdef SIS_NEW_CONFIG_COMPAT
1831  return -ENOIOCTLCMD;
1832 #else
1833  return -EINVAL;
1834 #endif
1835  }
1836  return 0;
1837 }
1838 
1839 static int
1840 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1841 {
1842  struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1843 
1844  memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1845 
1846  strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1847 
1848  mutex_lock(&info->mm_lock);
1849  fix->smem_start = ivideo->video_base + ivideo->video_offset;
1850  fix->smem_len = ivideo->sisfb_mem;
1851  mutex_unlock(&info->mm_lock);
1852  fix->type = FB_TYPE_PACKED_PIXELS;
1853  fix->type_aux = 0;
1854  fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1855  fix->xpanstep = 1;
1856  fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1857  fix->ywrapstep = 0;
1858  fix->line_length = ivideo->video_linelength;
1859  fix->mmio_start = ivideo->mmio_base;
1860  fix->mmio_len = ivideo->mmio_size;
1861  if(ivideo->sisvga_engine == SIS_300_VGA) {
1862  fix->accel = FB_ACCEL_SIS_GLAMOUR;
1863  } else if((ivideo->chip == SIS_330) ||
1864  (ivideo->chip == SIS_760) ||
1865  (ivideo->chip == SIS_761)) {
1866  fix->accel = FB_ACCEL_SIS_XABRE;
1867  } else if(ivideo->chip == XGI_20) {
1869  } else if(ivideo->chip >= XGI_40) {
1871  } else {
1873  }
1874 
1875  return 0;
1876 }
1877 
1878 /* ---------------- fb_ops structures ----------------- */
1879 
1880 static struct fb_ops sisfb_ops = {
1881  .owner = THIS_MODULE,
1882  .fb_open = sisfb_open,
1883  .fb_release = sisfb_release,
1884  .fb_check_var = sisfb_check_var,
1885  .fb_set_par = sisfb_set_par,
1886  .fb_setcolreg = sisfb_setcolreg,
1887  .fb_pan_display = sisfb_pan_display,
1888  .fb_blank = sisfb_blank,
1889  .fb_fillrect = fbcon_sis_fillrect,
1890  .fb_copyarea = fbcon_sis_copyarea,
1891  .fb_imageblit = cfb_imageblit,
1892  .fb_sync = fbcon_sis_sync,
1893 #ifdef SIS_NEW_CONFIG_COMPAT
1894  .fb_compat_ioctl= sisfb_ioctl,
1895 #endif
1896  .fb_ioctl = sisfb_ioctl
1897 };
1898 
1899 /* ---------------- Chip generation dependent routines ---------------- */
1900 
1901 static struct pci_dev * __devinit
1902 sisfb_get_northbridge(int basechipid)
1903 {
1904  struct pci_dev *pdev = NULL;
1905  int nbridgenum, nbridgeidx, i;
1906  static const unsigned short nbridgeids[] = {
1907  PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1908  PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1910  PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1911  PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1914  PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1919  };
1920 
1921  switch(basechipid) {
1922 #ifdef CONFIG_FB_SIS_300
1923  case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1924  case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1925 #endif
1926 #ifdef CONFIG_FB_SIS_315
1927  case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1928  case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1929  case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1930 #endif
1931  default: return NULL;
1932  }
1933  for(i = 0; i < nbridgenum; i++) {
1934  if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1935  nbridgeids[nbridgeidx+i], NULL)))
1936  break;
1937  }
1938  return pdev;
1939 }
1940 
1941 static int __devinit
1942 sisfb_get_dram_size(struct sis_video_info *ivideo)
1943 {
1944 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1945  u8 reg;
1946 #endif
1947 
1948  ivideo->video_size = 0;
1949  ivideo->UMAsize = ivideo->LFBsize = 0;
1950 
1951  switch(ivideo->chip) {
1952 #ifdef CONFIG_FB_SIS_300
1953  case SIS_300:
1954  reg = SiS_GetReg(SISSR, 0x14);
1955  ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1956  break;
1957  case SIS_540:
1958  case SIS_630:
1959  case SIS_730:
1960  if(!ivideo->nbridge)
1961  return -1;
1962  pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
1963  ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1964  break;
1965 #endif
1966 #ifdef CONFIG_FB_SIS_315
1967  case SIS_315H:
1968  case SIS_315PRO:
1969  case SIS_315:
1970  reg = SiS_GetReg(SISSR, 0x14);
1971  ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1972  switch((reg >> 2) & 0x03) {
1973  case 0x01:
1974  case 0x03:
1975  ivideo->video_size <<= 1;
1976  break;
1977  case 0x02:
1978  ivideo->video_size += (ivideo->video_size/2);
1979  }
1980  break;
1981  case SIS_330:
1982  reg = SiS_GetReg(SISSR, 0x14);
1983  ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1984  if(reg & 0x0c) ivideo->video_size <<= 1;
1985  break;
1986  case SIS_550:
1987  case SIS_650:
1988  case SIS_740:
1989  reg = SiS_GetReg(SISSR, 0x14);
1990  ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1991  break;
1992  case SIS_661:
1993  case SIS_741:
1994  reg = SiS_GetReg(SISCR, 0x79);
1995  ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1996  break;
1997  case SIS_660:
1998  case SIS_760:
1999  case SIS_761:
2000  reg = SiS_GetReg(SISCR, 0x79);
2001  reg = (reg & 0xf0) >> 4;
2002  if(reg) {
2003  ivideo->video_size = (1 << reg) << 20;
2004  ivideo->UMAsize = ivideo->video_size;
2005  }
2006  reg = SiS_GetReg(SISCR, 0x78);
2007  reg &= 0x30;
2008  if(reg) {
2009  if(reg == 0x10) {
2010  ivideo->LFBsize = (32 << 20);
2011  } else {
2012  ivideo->LFBsize = (64 << 20);
2013  }
2014  ivideo->video_size += ivideo->LFBsize;
2015  }
2016  break;
2017  case SIS_340:
2018  case XGI_20:
2019  case XGI_40:
2020  reg = SiS_GetReg(SISSR, 0x14);
2021  ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2022  if(ivideo->chip != XGI_20) {
2023  reg = (reg & 0x0c) >> 2;
2024  if(ivideo->revision_id == 2) {
2025  if(reg & 0x01) reg = 0x02;
2026  else reg = 0x00;
2027  }
2028  if(reg == 0x02) ivideo->video_size <<= 1;
2029  else if(reg == 0x03) ivideo->video_size <<= 2;
2030  }
2031  break;
2032 #endif
2033  default:
2034  return -1;
2035  }
2036  return 0;
2037 }
2038 
2039 /* -------------- video bridge device detection --------------- */
2040 
2041 static void __devinit
2042 sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2043 {
2044  u8 cr32, temp;
2045 
2046  /* No CRT2 on XGI Z7 */
2047  if(ivideo->chip == XGI_20) {
2048  ivideo->sisfb_crt1off = 0;
2049  return;
2050  }
2051 
2052 #ifdef CONFIG_FB_SIS_300
2053  if(ivideo->sisvga_engine == SIS_300_VGA) {
2054  temp = SiS_GetReg(SISSR, 0x17);
2055  if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2056  /* PAL/NTSC is stored on SR16 on such machines */
2057  if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2058  temp = SiS_GetReg(SISSR, 0x16);
2059  if(temp & 0x20)
2060  ivideo->vbflags |= TV_PAL;
2061  else
2062  ivideo->vbflags |= TV_NTSC;
2063  }
2064  }
2065  }
2066 #endif
2067 
2068  cr32 = SiS_GetReg(SISCR, 0x32);
2069 
2070  if(cr32 & SIS_CRT1) {
2071  ivideo->sisfb_crt1off = 0;
2072  } else {
2073  ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2074  }
2075 
2076  ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2077 
2078  if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2079  if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2080  if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2081 
2082  /* Check given parms for hardware compatibility.
2083  * (Cannot do this in the search_xx routines since we don't
2084  * know what hardware we are running on then)
2085  */
2086 
2087  if(ivideo->chip != SIS_550) {
2088  ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2089  }
2090 
2091  if(ivideo->sisfb_tvplug != -1) {
2092  if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2093  (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2094  if(ivideo->sisfb_tvplug & TV_YPBPR) {
2095  ivideo->sisfb_tvplug = -1;
2096  printk(KERN_ERR "sisfb: YPbPr not supported\n");
2097  }
2098  }
2099  }
2100  if(ivideo->sisfb_tvplug != -1) {
2101  if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2102  (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2103  if(ivideo->sisfb_tvplug & TV_HIVISION) {
2104  ivideo->sisfb_tvplug = -1;
2105  printk(KERN_ERR "sisfb: HiVision not supported\n");
2106  }
2107  }
2108  }
2109  if(ivideo->sisfb_tvstd != -1) {
2110  if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2111  (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2112  (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2113  if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2114  ivideo->sisfb_tvstd = -1;
2115  printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2116  }
2117  }
2118  }
2119 
2120  /* Detect/set TV plug & type */
2121  if(ivideo->sisfb_tvplug != -1) {
2122  ivideo->vbflags |= ivideo->sisfb_tvplug;
2123  } else {
2124  if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2125  else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2126  else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2127  else {
2128  if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2129  if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2130  }
2131  }
2132 
2133  if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2134  if(ivideo->sisfb_tvstd != -1) {
2135  ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2136  ivideo->vbflags |= ivideo->sisfb_tvstd;
2137  }
2138  if(ivideo->vbflags & TV_SCART) {
2139  ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2140  ivideo->vbflags |= TV_PAL;
2141  }
2142  if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2143  if(ivideo->sisvga_engine == SIS_300_VGA) {
2144  temp = SiS_GetReg(SISSR, 0x38);
2145  if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2146  else ivideo->vbflags |= TV_NTSC;
2147  } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2148  temp = SiS_GetReg(SISSR, 0x38);
2149  if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2150  else ivideo->vbflags |= TV_NTSC;
2151  } else {
2152  temp = SiS_GetReg(SISCR, 0x79);
2153  if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2154  else ivideo->vbflags |= TV_NTSC;
2155  }
2156  }
2157  }
2158 
2159  /* Copy forceCRT1 option to CRT1off if option is given */
2160  if(ivideo->sisfb_forcecrt1 != -1) {
2161  ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2162  }
2163 }
2164 
2165 /* ------------------ Sensing routines ------------------ */
2166 
2167 static bool __devinit
2168 sisfb_test_DDC1(struct sis_video_info *ivideo)
2169 {
2170  unsigned short old;
2171  int count = 48;
2172 
2173  old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2174  do {
2175  if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2176  } while(count--);
2177  return (count != -1);
2178 }
2179 
2180 static void __devinit
2181 sisfb_sense_crt1(struct sis_video_info *ivideo)
2182 {
2183  bool mustwait = false;
2184  u8 sr1F, cr17;
2185 #ifdef CONFIG_FB_SIS_315
2186  u8 cr63=0;
2187 #endif
2188  u16 temp = 0xffff;
2189  int i;
2190 
2191  sr1F = SiS_GetReg(SISSR, 0x1F);
2192  SiS_SetRegOR(SISSR, 0x1F, 0x04);
2193  SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2194  if(sr1F & 0xc0) mustwait = true;
2195 
2196 #ifdef CONFIG_FB_SIS_315
2197  if(ivideo->sisvga_engine == SIS_315_VGA) {
2198  cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2199  cr63 &= 0x40;
2200  SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2201  }
2202 #endif
2203 
2204  cr17 = SiS_GetReg(SISCR, 0x17);
2205  cr17 &= 0x80;
2206  if(!cr17) {
2207  SiS_SetRegOR(SISCR, 0x17, 0x80);
2208  mustwait = true;
2209  SiS_SetReg(SISSR, 0x00, 0x01);
2210  SiS_SetReg(SISSR, 0x00, 0x03);
2211  }
2212 
2213  if(mustwait) {
2214  for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2215  }
2216 
2217 #ifdef CONFIG_FB_SIS_315
2218  if(ivideo->chip >= SIS_330) {
2219  SiS_SetRegAND(SISCR, 0x32, ~0x20);
2220  if(ivideo->chip >= SIS_340) {
2221  SiS_SetReg(SISCR, 0x57, 0x4a);
2222  } else {
2223  SiS_SetReg(SISCR, 0x57, 0x5f);
2224  }
2225  SiS_SetRegOR(SISCR, 0x53, 0x02);
2226  while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2227  while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2228  if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2229  SiS_SetRegAND(SISCR, 0x53, 0xfd);
2230  SiS_SetRegAND(SISCR, 0x57, 0x00);
2231  }
2232 #endif
2233 
2234  if(temp == 0xffff) {
2235  i = 3;
2236  do {
2237  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2238  ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2239  } while(((temp == 0) || (temp == 0xffff)) && i--);
2240 
2241  if((temp == 0) || (temp == 0xffff)) {
2242  if(sisfb_test_DDC1(ivideo)) temp = 1;
2243  }
2244  }
2245 
2246  if((temp) && (temp != 0xffff)) {
2247  SiS_SetRegOR(SISCR, 0x32, 0x20);
2248  }
2249 
2250 #ifdef CONFIG_FB_SIS_315
2251  if(ivideo->sisvga_engine == SIS_315_VGA) {
2252  SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2253  }
2254 #endif
2255 
2256  SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2257 
2258  SiS_SetReg(SISSR, 0x1F, sr1F);
2259 }
2260 
2261 /* Determine and detect attached devices on SiS30x */
2262 static void __devinit
2263 SiS_SenseLCD(struct sis_video_info *ivideo)
2264 {
2265  unsigned char buffer[256];
2266  unsigned short temp, realcrtno, i;
2267  u8 reg, cr37 = 0, paneltype = 0;
2268  u16 xres, yres;
2269 
2270  ivideo->SiS_Pr.PanelSelfDetected = false;
2271 
2272  /* LCD detection only for TMDS bridges */
2273  if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2274  return;
2275  if(ivideo->vbflags2 & VB2_30xBDH)
2276  return;
2277 
2278  /* If LCD already set up by BIOS, skip it */
2279  reg = SiS_GetReg(SISCR, 0x32);
2280  if(reg & 0x08)
2281  return;
2282 
2283  realcrtno = 1;
2284  if(ivideo->SiS_Pr.DDCPortMixup)
2285  realcrtno = 0;
2286 
2287  /* Check DDC capabilities */
2288  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2289  realcrtno, 0, &buffer[0], ivideo->vbflags2);
2290 
2291  if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2292  return;
2293 
2294  /* Read DDC data */
2295  i = 3; /* Number of retrys */
2296  do {
2297  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2298  ivideo->sisvga_engine, realcrtno, 1,
2299  &buffer[0], ivideo->vbflags2);
2300  } while((temp) && i--);
2301 
2302  if(temp)
2303  return;
2304 
2305  /* No digital device */
2306  if(!(buffer[0x14] & 0x80))
2307  return;
2308 
2309  /* First detailed timing preferred timing? */
2310  if(!(buffer[0x18] & 0x02))
2311  return;
2312 
2313  xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2314  yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2315 
2316  switch(xres) {
2317  case 1024:
2318  if(yres == 768)
2319  paneltype = 0x02;
2320  break;
2321  case 1280:
2322  if(yres == 1024)
2323  paneltype = 0x03;
2324  break;
2325  case 1600:
2326  if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2327  paneltype = 0x0b;
2328  break;
2329  }
2330 
2331  if(!paneltype)
2332  return;
2333 
2334  if(buffer[0x23])
2335  cr37 |= 0x10;
2336 
2337  if((buffer[0x47] & 0x18) == 0x18)
2338  cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2339  else
2340  cr37 |= 0xc0;
2341 
2342  SiS_SetReg(SISCR, 0x36, paneltype);
2343  cr37 &= 0xf1;
2344  SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2345  SiS_SetRegOR(SISCR, 0x32, 0x08);
2346 
2347  ivideo->SiS_Pr.PanelSelfDetected = true;
2348 }
2349 
2350 static int __devinit
2351 SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2352 {
2353  int temp, mytest, result, i, j;
2354 
2355  for(j = 0; j < 10; j++) {
2356  result = 0;
2357  for(i = 0; i < 3; i++) {
2358  mytest = test;
2359  SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2360  temp = (type >> 8) | (mytest & 0x00ff);
2361  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2362  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2363  mytest >>= 8;
2364  mytest &= 0x7f;
2365  temp = SiS_GetReg(SISPART4, 0x03);
2366  temp ^= 0x0e;
2367  temp &= mytest;
2368  if(temp == mytest) result++;
2369 #if 1
2370  SiS_SetReg(SISPART4, 0x11, 0x00);
2371  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2372  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2373 #endif
2374  }
2375  if((result == 0) || (result >= 2)) break;
2376  }
2377  return result;
2378 }
2379 
2380 static void __devinit
2381 SiS_Sense30x(struct sis_video_info *ivideo)
2382 {
2383  u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2384  u16 svhs=0, svhs_c=0;
2385  u16 cvbs=0, cvbs_c=0;
2386  u16 vga2=0, vga2_c=0;
2387  int myflag, result;
2388  char stdstr[] = "sisfb: Detected";
2389  char tvstr[] = "TV connected to";
2390 
2391  if(ivideo->vbflags2 & VB2_301) {
2392  svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2393  myflag = SiS_GetReg(SISPART4, 0x01);
2394  if(myflag & 0x04) {
2395  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2396  }
2397  } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2398  svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2399  } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2400  svhs = 0x0200; cvbs = 0x0100;
2401  } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2402  svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2403  } else
2404  return;
2405 
2406  vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2407  if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2408  svhs_c = 0x0408; cvbs_c = 0x0808;
2409  }
2410 
2411  biosflag = 2;
2412  if(ivideo->haveXGIROM) {
2413  biosflag = ivideo->bios_abase[0x58] & 0x03;
2414  } else if(ivideo->newrom) {
2415  if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2416  } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2417  if(ivideo->bios_abase) {
2418  biosflag = ivideo->bios_abase[0xfe] & 0x03;
2419  }
2420  }
2421 
2422  if(ivideo->chip == SIS_300) {
2423  myflag = SiS_GetReg(SISSR, 0x3b);
2424  if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2425  }
2426 
2427  if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2428  vga2 = vga2_c = 0;
2429  }
2430 
2431  backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2432  SiS_SetRegOR(SISSR, 0x1e, 0x20);
2433 
2434  backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2435  if(ivideo->vbflags2 & VB2_30xC) {
2436  SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2437  } else {
2438  SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2439  }
2440  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2441 
2442  backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2443  SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2444 
2445  backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2446  if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2447  SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2448  }
2449 
2450  if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2451  SISDoSense(ivideo, 0, 0);
2452  }
2453 
2454  SiS_SetRegAND(SISCR, 0x32, ~0x14);
2455 
2456  if(vga2_c || vga2) {
2457  if(SISDoSense(ivideo, vga2, vga2_c)) {
2458  if(biosflag & 0x01) {
2459  printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2460  SiS_SetRegOR(SISCR, 0x32, 0x04);
2461  } else {
2462  printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2463  SiS_SetRegOR(SISCR, 0x32, 0x10);
2464  }
2465  }
2466  }
2467 
2468  SiS_SetRegAND(SISCR, 0x32, 0x3f);
2469 
2470  if(ivideo->vbflags2 & VB2_30xCLV) {
2471  SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2472  }
2473 
2474  if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2475  SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2476  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2477  if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2478  if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2479  printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2480  SiS_SetRegOR(SISCR, 0x32, 0x80);
2481  }
2482  }
2483  SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2484  }
2485 
2486  SiS_SetRegAND(SISCR, 0x32, ~0x03);
2487 
2488  if(!(ivideo->vbflags & TV_YPBPR)) {
2489  if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2490  printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2491  SiS_SetRegOR(SISCR, 0x32, 0x02);
2492  }
2493  if((biosflag & 0x02) || (!result)) {
2494  if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2495  printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2496  SiS_SetRegOR(SISCR, 0x32, 0x01);
2497  }
2498  }
2499  }
2500 
2501  SISDoSense(ivideo, 0, 0);
2502 
2503  SiS_SetReg(SISPART2, 0x00, backupP2_00);
2504  SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2505  SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2506 
2507  if(ivideo->vbflags2 & VB2_30xCLV) {
2508  biosflag = SiS_GetReg(SISPART2, 0x00);
2509  if(biosflag & 0x20) {
2510  for(myflag = 2; myflag > 0; myflag--) {
2511  biosflag ^= 0x20;
2512  SiS_SetReg(SISPART2, 0x00, biosflag);
2513  }
2514  }
2515  }
2516 
2517  SiS_SetReg(SISPART2, 0x00, backupP2_00);
2518 }
2519 
2520 /* Determine and detect attached TV's on Chrontel */
2521 static void __devinit
2522 SiS_SenseCh(struct sis_video_info *ivideo)
2523 {
2524 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2525  u8 temp1, temp2;
2526  char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2527 #endif
2528 #ifdef CONFIG_FB_SIS_300
2529  unsigned char test[3];
2530  int i;
2531 #endif
2532 
2533  if(ivideo->chip < SIS_315H) {
2534 
2535 #ifdef CONFIG_FB_SIS_300
2536  ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2537  SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2538  SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2539  temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2540  /* See Chrontel TB31 for explanation */
2541  temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2542  if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2543  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2544  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2545  }
2546  temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2547  if(temp2 != temp1) temp1 = temp2;
2548 
2549  if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2550  /* Read power status */
2551  temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2552  if((temp1 & 0x03) != 0x03) {
2553  /* Power all outputs */
2554  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2555  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2556  }
2557  /* Sense connected TV devices */
2558  for(i = 0; i < 3; i++) {
2559  SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2560  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2561  SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2562  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2563  temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2564  if(!(temp1 & 0x08)) test[i] = 0x02;
2565  else if(!(temp1 & 0x02)) test[i] = 0x01;
2566  else test[i] = 0;
2567  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2568  }
2569 
2570  if(test[0] == test[1]) temp1 = test[0];
2571  else if(test[0] == test[2]) temp1 = test[0];
2572  else if(test[1] == test[2]) temp1 = test[1];
2573  else {
2575  "sisfb: TV detection unreliable - test results varied\n");
2576  temp1 = test[2];
2577  }
2578  if(temp1 == 0x02) {
2579  printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2580  ivideo->vbflags |= TV_SVIDEO;
2581  SiS_SetRegOR(SISCR, 0x32, 0x02);
2582  SiS_SetRegAND(SISCR, 0x32, ~0x05);
2583  } else if (temp1 == 0x01) {
2584  printk(KERN_INFO "%s CVBS output\n", stdstr);
2585  ivideo->vbflags |= TV_AVIDEO;
2586  SiS_SetRegOR(SISCR, 0x32, 0x01);
2587  SiS_SetRegAND(SISCR, 0x32, ~0x06);
2588  } else {
2589  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2590  SiS_SetRegAND(SISCR, 0x32, ~0x07);
2591  }
2592  } else if(temp1 == 0) {
2593  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2594  SiS_SetRegAND(SISCR, 0x32, ~0x07);
2595  }
2596  /* Set general purpose IO for Chrontel communication */
2597  SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2598 #endif
2599 
2600  } else {
2601 
2602 #ifdef CONFIG_FB_SIS_315
2603  ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2604  temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2605  SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2606  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2607  temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2608  temp2 |= 0x01;
2609  SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2610  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2611  temp2 ^= 0x01;
2612  SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2613  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2614  temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2615  SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2616  temp1 = 0;
2617  if(temp2 & 0x02) temp1 |= 0x01;
2618  if(temp2 & 0x10) temp1 |= 0x01;
2619  if(temp2 & 0x04) temp1 |= 0x02;
2620  if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2621  switch(temp1) {
2622  case 0x01:
2623  printk(KERN_INFO "%s CVBS output\n", stdstr);
2624  ivideo->vbflags |= TV_AVIDEO;
2625  SiS_SetRegOR(SISCR, 0x32, 0x01);
2626  SiS_SetRegAND(SISCR, 0x32, ~0x06);
2627  break;
2628  case 0x02:
2629  printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2630  ivideo->vbflags |= TV_SVIDEO;
2631  SiS_SetRegOR(SISCR, 0x32, 0x02);
2632  SiS_SetRegAND(SISCR, 0x32, ~0x05);
2633  break;
2634  case 0x04:
2635  printk(KERN_INFO "%s SCART output\n", stdstr);
2636  SiS_SetRegOR(SISCR, 0x32, 0x04);
2637  SiS_SetRegAND(SISCR, 0x32, ~0x03);
2638  break;
2639  default:
2640  SiS_SetRegAND(SISCR, 0x32, ~0x07);
2641  }
2642 #endif
2643  }
2644 }
2645 
2646 static void __devinit
2647 sisfb_get_VB_type(struct sis_video_info *ivideo)
2648 {
2649  char stdstr[] = "sisfb: Detected";
2650  char bridgestr[] = "video bridge";
2651  u8 vb_chipid;
2652  u8 reg;
2653 
2654  /* No CRT2 on XGI Z7 */
2655  if(ivideo->chip == XGI_20)
2656  return;
2657 
2658  vb_chipid = SiS_GetReg(SISPART4, 0x00);
2659  switch(vb_chipid) {
2660  case 0x01:
2661  reg = SiS_GetReg(SISPART4, 0x01);
2662  if(reg < 0xb0) {
2663  ivideo->vbflags |= VB_301; /* Deprecated */
2664  ivideo->vbflags2 |= VB2_301;
2665  printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2666  } else if(reg < 0xc0) {
2667  ivideo->vbflags |= VB_301B; /* Deprecated */
2668  ivideo->vbflags2 |= VB2_301B;
2669  reg = SiS_GetReg(SISPART4, 0x23);
2670  if(!(reg & 0x02)) {
2671  ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2672  ivideo->vbflags2 |= VB2_30xBDH;
2673  printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2674  } else {
2675  printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2676  }
2677  } else if(reg < 0xd0) {
2678  ivideo->vbflags |= VB_301C; /* Deprecated */
2679  ivideo->vbflags2 |= VB2_301C;
2680  printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2681  } else if(reg < 0xe0) {
2682  ivideo->vbflags |= VB_301LV; /* Deprecated */
2683  ivideo->vbflags2 |= VB2_301LV;
2684  printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2685  } else if(reg <= 0xe1) {
2686  reg = SiS_GetReg(SISPART4, 0x39);
2687  if(reg == 0xff) {
2688  ivideo->vbflags |= VB_302LV; /* Deprecated */
2689  ivideo->vbflags2 |= VB2_302LV;
2690  printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2691  } else {
2692  ivideo->vbflags |= VB_301C; /* Deprecated */
2693  ivideo->vbflags2 |= VB2_301C;
2694  printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2695 #if 0
2696  ivideo->vbflags |= VB_302ELV; /* Deprecated */
2697  ivideo->vbflags2 |= VB2_302ELV;
2698  printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2699 #endif
2700  }
2701  }
2702  break;
2703  case 0x02:
2704  ivideo->vbflags |= VB_302B; /* Deprecated */
2705  ivideo->vbflags2 |= VB2_302B;
2706  printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2707  break;
2708  }
2709 
2710  if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2711  reg = SiS_GetReg(SISCR, 0x37);
2712  reg &= SIS_EXTERNAL_CHIP_MASK;
2713  reg >>= 1;
2714  if(ivideo->sisvga_engine == SIS_300_VGA) {
2715 #ifdef CONFIG_FB_SIS_300
2716  switch(reg) {
2718  ivideo->vbflags |= VB_LVDS; /* Deprecated */
2719  ivideo->vbflags2 |= VB2_LVDS;
2720  break;
2722  ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2723  ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2724  break;
2726  ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2727  ivideo->vbflags2 |= VB2_CHRONTEL;
2728  break;
2730  ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2731  ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2732  break;
2733  }
2734  if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2735 #endif
2736  } else if(ivideo->chip < SIS_661) {
2737 #ifdef CONFIG_FB_SIS_315
2738  switch (reg) {
2740  ivideo->vbflags |= VB_LVDS; /* Deprecated */
2741  ivideo->vbflags2 |= VB2_LVDS;
2742  break;
2744  ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2745  ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2746  break;
2747  }
2748  if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2749 #endif
2750  } else if(ivideo->chip >= SIS_661) {
2751 #ifdef CONFIG_FB_SIS_315
2752  reg = SiS_GetReg(SISCR, 0x38);
2753  reg >>= 5;
2754  switch(reg) {
2755  case 0x02:
2756  ivideo->vbflags |= VB_LVDS; /* Deprecated */
2757  ivideo->vbflags2 |= VB2_LVDS;
2758  break;
2759  case 0x03:
2760  ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2761  ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2762  break;
2763  case 0x04:
2764  ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2765  ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2766  break;
2767  }
2768  if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2769 #endif
2770  }
2771  if(ivideo->vbflags2 & VB2_LVDS) {
2772  printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2773  }
2774  if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2775  printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2776  }
2777  if(ivideo->vbflags2 & VB2_CHRONTEL) {
2778  printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2779  }
2780  if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2781  printk(KERN_INFO "%s Conexant external device\n", stdstr);
2782  }
2783  }
2784 
2785  if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2786  SiS_SenseLCD(ivideo);
2787  SiS_Sense30x(ivideo);
2788  } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2789  SiS_SenseCh(ivideo);
2790  }
2791 }
2792 
2793 /* ---------- Engine initialization routines ------------ */
2794 
2795 static void
2796 sisfb_engine_init(struct sis_video_info *ivideo)
2797 {
2798 
2799  /* Initialize command queue (we use MMIO only) */
2800 
2801  /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2802 
2803  ivideo->caps &= ~(TURBO_QUEUE_CAP |
2807 
2808 #ifdef CONFIG_FB_SIS_300
2809  if(ivideo->sisvga_engine == SIS_300_VGA) {
2810  u32 tqueue_pos;
2811  u8 tq_state;
2812 
2813  tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2814 
2816  tq_state |= 0xf0;
2817  tq_state &= 0xfc;
2818  tq_state |= (u8)(tqueue_pos >> 8);
2820 
2821  SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2822 
2823  ivideo->caps |= TURBO_QUEUE_CAP;
2824  }
2825 #endif
2826 
2827 #ifdef CONFIG_FB_SIS_315
2828  if(ivideo->sisvga_engine == SIS_315_VGA) {
2829  u32 tempq = 0, templ;
2830  u8 temp;
2831 
2832  if(ivideo->chip == XGI_20) {
2833  switch(ivideo->cmdQueueSize) {
2834  case (64 * 1024):
2836  break;
2837  case (128 * 1024):
2838  default:
2840  }
2841  } else {
2842  switch(ivideo->cmdQueueSize) {
2843  case (4 * 1024 * 1024):
2844  temp = SIS_CMD_QUEUE_SIZE_4M;
2845  break;
2846  case (2 * 1024 * 1024):
2847  temp = SIS_CMD_QUEUE_SIZE_2M;
2848  break;
2849  case (1 * 1024 * 1024):
2850  temp = SIS_CMD_QUEUE_SIZE_1M;
2851  break;
2852  default:
2853  case (512 * 1024):
2854  temp = SIS_CMD_QUEUE_SIZE_512k;
2855  }
2856  }
2857 
2860 
2861  if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2862  /* Must disable dual pipe on XGI_40. Can't do
2863  * this in MMIO mode, because it requires
2864  * setting/clearing a bit in the MMIO fire trigger
2865  * register.
2866  */
2867  if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2868 
2869  MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2870 
2872 
2873  tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2874  MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2875 
2876  tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2877  MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2878 
2879  writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2880  writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2881  writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2882  writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2883 
2884  MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2885 
2886  sisfb_syncaccel(ivideo);
2887 
2889 
2890  }
2891  }
2892 
2893  tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2894  MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2895 
2898 
2899  tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2900  MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2901 
2902  ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2903  }
2904 #endif
2905 
2906  ivideo->engineok = 1;
2907 }
2908 
2909 static void __devinit
2910 sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2911 {
2912  u8 reg;
2913  int i;
2914 
2915  reg = SiS_GetReg(SISCR, 0x36);
2916  reg &= 0x0f;
2917  if(ivideo->sisvga_engine == SIS_300_VGA) {
2918  ivideo->CRT2LCDType = sis300paneltype[reg];
2919  } else if(ivideo->chip >= SIS_661) {
2920  ivideo->CRT2LCDType = sis661paneltype[reg];
2921  } else {
2922  ivideo->CRT2LCDType = sis310paneltype[reg];
2923  if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2924  if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2925  (ivideo->CRT2LCDType != LCD_320x240_3)) {
2926  ivideo->CRT2LCDType = LCD_320x240;
2927  }
2928  }
2929  }
2930 
2931  if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2932  /* For broken BIOSes: Assume 1024x768, RGB18 */
2933  ivideo->CRT2LCDType = LCD_1024x768;
2934  SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2935  SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2936  printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2937  }
2938 
2939  for(i = 0; i < SIS_LCD_NUMBER; i++) {
2940  if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2941  ivideo->lcdxres = sis_lcd_data[i].xres;
2942  ivideo->lcdyres = sis_lcd_data[i].yres;
2943  ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2944  break;
2945  }
2946  }
2947 
2948 #ifdef CONFIG_FB_SIS_300
2949  if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2950  ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2951  ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2952  } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2953  ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2954  ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2955  } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2956  ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2957  ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2958  }
2959 #endif
2960 
2961  printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2962  ivideo->lcdxres, ivideo->lcdyres);
2963 }
2964 
2965 static void __devinit
2966 sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2967 {
2968 #ifdef CONFIG_FB_SIS_300
2969  /* Save the current PanelDelayCompensation if the LCD is currently used */
2970  if(ivideo->sisvga_engine == SIS_300_VGA) {
2971  if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2972  int tmp;
2973  tmp = SiS_GetReg(SISCR, 0x30);
2974  if(tmp & 0x20) {
2975  /* Currently on LCD? If yes, read current pdc */
2976  ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2977  ivideo->detectedpdc &= 0x3c;
2978  if(ivideo->SiS_Pr.PDC == -1) {
2979  /* Let option override detection */
2980  ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2981  }
2982  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2983  ivideo->detectedpdc);
2984  }
2985  if((ivideo->SiS_Pr.PDC != -1) &&
2986  (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
2987  printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
2988  ivideo->SiS_Pr.PDC);
2989  }
2990  }
2991  }
2992 #endif
2993 
2994 #ifdef CONFIG_FB_SIS_315
2995  if(ivideo->sisvga_engine == SIS_315_VGA) {
2996 
2997  /* Try to find about LCDA */
2998  if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
2999  int tmp;
3000  tmp = SiS_GetReg(SISPART1, 0x13);
3001  if(tmp & 0x04) {
3002  ivideo->SiS_Pr.SiS_UseLCDA = true;
3003  ivideo->detectedlcda = 0x03;
3004  }
3005  }
3006 
3007  /* Save PDC */
3008  if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3009  int tmp;
3010  tmp = SiS_GetReg(SISCR, 0x30);
3011  if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3012  /* Currently on LCD? If yes, read current pdc */
3013  u8 pdc;
3014  pdc = SiS_GetReg(SISPART1, 0x2D);
3015  ivideo->detectedpdc = (pdc & 0x0f) << 1;
3016  ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3017  pdc = SiS_GetReg(SISPART1, 0x35);
3018  ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3019  pdc = SiS_GetReg(SISPART1, 0x20);
3020  ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3021  if(ivideo->newrom) {
3022  /* New ROM invalidates other PDC resp. */
3023  if(ivideo->detectedlcda != 0xff) {
3024  ivideo->detectedpdc = 0xff;
3025  } else {
3026  ivideo->detectedpdca = 0xff;
3027  }
3028  }
3029  if(ivideo->SiS_Pr.PDC == -1) {
3030  if(ivideo->detectedpdc != 0xff) {
3031  ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3032  }
3033  }
3034  if(ivideo->SiS_Pr.PDCA == -1) {
3035  if(ivideo->detectedpdca != 0xff) {
3036  ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3037  }
3038  }
3039  if(ivideo->detectedpdc != 0xff) {
3041  "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3042  ivideo->detectedpdc);
3043  }
3044  if(ivideo->detectedpdca != 0xff) {
3046  "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3047  ivideo->detectedpdca);
3048  }
3049  }
3050 
3051  /* Save EMI */
3052  if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3053  ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3054  ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3055  ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3056  ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3057  ivideo->SiS_Pr.HaveEMI = true;
3058  if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3059  ivideo->SiS_Pr.HaveEMILCD = true;
3060  }
3061  }
3062  }
3063 
3064  /* Let user override detected PDCs (all bridges) */
3065  if(ivideo->vbflags2 & VB2_30xBLV) {
3066  if((ivideo->SiS_Pr.PDC != -1) &&
3067  (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3068  printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3069  ivideo->SiS_Pr.PDC);
3070  }
3071  if((ivideo->SiS_Pr.PDCA != -1) &&
3072  (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3073  printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3074  ivideo->SiS_Pr.PDCA);
3075  }
3076  }
3077 
3078  }
3079 #endif
3080 }
3081 
3082 /* -------------------- Memory manager routines ---------------------- */
3083 
3084 static u32 __devinit
3085 sisfb_getheapstart(struct sis_video_info *ivideo)
3086 {
3087  u32 ret = ivideo->sisfb_parm_mem * 1024;
3088  u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3089  u32 def;
3090 
3091  /* Calculate heap start = end of memory for console
3092  *
3093  * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3094  * C = console, D = heap, H = HWCursor, Q = cmd-queue
3095  *
3096  * On 76x in UMA+LFB mode, the layout is as follows:
3097  * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3098  * where the heap is the entire UMA area, eventually
3099  * into the LFB area if the given mem parameter is
3100  * higher than the size of the UMA memory.
3101  *
3102  * Basically given by "mem" parameter
3103  *
3104  * maximum = videosize - cmd_queue - hwcursor
3105  * (results in a heap of size 0)
3106  * default = SiS 300: depends on videosize
3107  * SiS 315/330/340/XGI: 32k below max
3108  */
3109 
3110  if(ivideo->sisvga_engine == SIS_300_VGA) {
3111  if(ivideo->video_size > 0x1000000) {
3112  def = 0xc00000;
3113  } else if(ivideo->video_size > 0x800000) {
3114  def = 0x800000;
3115  } else {
3116  def = 0x400000;
3117  }
3118  } else if(ivideo->UMAsize && ivideo->LFBsize) {
3119  ret = def = 0;
3120  } else {
3121  def = maxoffs - 0x8000;
3122  }
3123 
3124  /* Use default for secondary card for now (FIXME) */
3125  if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3126  ret = def;
3127 
3128  return ret;
3129 }
3130 
3131 static u32 __devinit
3132 sisfb_getheapsize(struct sis_video_info *ivideo)
3133 {
3134  u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3135  u32 ret = 0;
3136 
3137  if(ivideo->UMAsize && ivideo->LFBsize) {
3138  if( (!ivideo->sisfb_parm_mem) ||
3139  ((ivideo->sisfb_parm_mem * 1024) > max) ||
3140  ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3141  ret = ivideo->UMAsize;
3142  max -= ivideo->UMAsize;
3143  } else {
3144  ret = max - (ivideo->sisfb_parm_mem * 1024);
3145  max = ivideo->sisfb_parm_mem * 1024;
3146  }
3147  ivideo->video_offset = ret;
3148  ivideo->sisfb_mem = max;
3149  } else {
3150  ret = max - ivideo->heapstart;
3151  ivideo->sisfb_mem = ivideo->heapstart;
3152  }
3153 
3154  return ret;
3155 }
3156 
3157 static int __devinit
3158 sisfb_heap_init(struct sis_video_info *ivideo)
3159 {
3160  struct SIS_OH *poh;
3161 
3162  ivideo->video_offset = 0;
3163  if(ivideo->sisfb_parm_mem) {
3164  if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3165  (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3166  ivideo->sisfb_parm_mem = 0;
3167  }
3168  }
3169 
3170  ivideo->heapstart = sisfb_getheapstart(ivideo);
3171  ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3172 
3173  ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3174  ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3175 
3176  printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3177  (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3178 
3179  ivideo->sisfb_heap.vinfo = ivideo;
3180 
3181  ivideo->sisfb_heap.poha_chain = NULL;
3182  ivideo->sisfb_heap.poh_freelist = NULL;
3183 
3184  poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3185  if(poh == NULL)
3186  return 1;
3187 
3188  poh->poh_next = &ivideo->sisfb_heap.oh_free;
3189  poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3190  poh->size = ivideo->sisfb_heap_size;
3191  poh->offset = ivideo->heapstart;
3192 
3193  ivideo->sisfb_heap.oh_free.poh_next = poh;
3194  ivideo->sisfb_heap.oh_free.poh_prev = poh;
3195  ivideo->sisfb_heap.oh_free.size = 0;
3196  ivideo->sisfb_heap.max_freesize = poh->size;
3197 
3198  ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3199  ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3200  ivideo->sisfb_heap.oh_used.size = SENTINEL;
3201 
3202  if(ivideo->cardnumber == 0) {
3203  /* For the first card, make this heap the "global" one
3204  * for old DRM (which could handle only one card)
3205  */
3206  sisfb_heap = &ivideo->sisfb_heap;
3207  }
3208 
3209  return 0;
3210 }
3211 
3212 static struct SIS_OH *
3213 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3214 {
3215  struct SIS_OHALLOC *poha;
3216  struct SIS_OH *poh;
3217  unsigned long cOhs;
3218  int i;
3219 
3220  if(memheap->poh_freelist == NULL) {
3222  if(!poha)
3223  return NULL;
3224 
3225  poha->poha_next = memheap->poha_chain;
3226  memheap->poha_chain = poha;
3227 
3228  cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3229 
3230  poh = &poha->aoh[0];
3231  for(i = cOhs - 1; i != 0; i--) {
3232  poh->poh_next = poh + 1;
3233  poh = poh + 1;
3234  }
3235 
3236  poh->poh_next = NULL;
3237  memheap->poh_freelist = &poha->aoh[0];
3238  }
3239 
3240  poh = memheap->poh_freelist;
3241  memheap->poh_freelist = poh->poh_next;
3242 
3243  return poh;
3244 }
3245 
3246 static struct SIS_OH *
3247 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3248 {
3249  struct SIS_OH *pohThis;
3250  struct SIS_OH *pohRoot;
3251  int bAllocated = 0;
3252 
3253  if(size > memheap->max_freesize) {
3254  DPRINTK("sisfb: Can't allocate %dk video memory\n",
3255  (unsigned int) size / 1024);
3256  return NULL;
3257  }
3258 
3259  pohThis = memheap->oh_free.poh_next;
3260 
3261  while(pohThis != &memheap->oh_free) {
3262  if(size <= pohThis->size) {
3263  bAllocated = 1;
3264  break;
3265  }
3266  pohThis = pohThis->poh_next;
3267  }
3268 
3269  if(!bAllocated) {
3270  DPRINTK("sisfb: Can't allocate %dk video memory\n",
3271  (unsigned int) size / 1024);
3272  return NULL;
3273  }
3274 
3275  if(size == pohThis->size) {
3276  pohRoot = pohThis;
3277  sisfb_delete_node(pohThis);
3278  } else {
3279  pohRoot = sisfb_poh_new_node(memheap);
3280  if(pohRoot == NULL)
3281  return NULL;
3282 
3283  pohRoot->offset = pohThis->offset;
3284  pohRoot->size = size;
3285 
3286  pohThis->offset += size;
3287  pohThis->size -= size;
3288  }
3289 
3290  memheap->max_freesize -= size;
3291 
3292  pohThis = &memheap->oh_used;
3293  sisfb_insert_node(pohThis, pohRoot);
3294 
3295  return pohRoot;
3296 }
3297 
3298 static void
3299 sisfb_delete_node(struct SIS_OH *poh)
3300 {
3301  poh->poh_prev->poh_next = poh->poh_next;
3302  poh->poh_next->poh_prev = poh->poh_prev;
3303 }
3304 
3305 static void
3306 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3307 {
3308  struct SIS_OH *pohTemp = pohList->poh_next;
3309 
3310  pohList->poh_next = poh;
3311  pohTemp->poh_prev = poh;
3312 
3313  poh->poh_prev = pohList;
3314  poh->poh_next = pohTemp;
3315 }
3316 
3317 static struct SIS_OH *
3318 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3319 {
3320  struct SIS_OH *pohThis;
3321  struct SIS_OH *poh_freed;
3322  struct SIS_OH *poh_prev;
3323  struct SIS_OH *poh_next;
3324  u32 ulUpper;
3325  u32 ulLower;
3326  int foundNode = 0;
3327 
3328  poh_freed = memheap->oh_used.poh_next;
3329 
3330  while(poh_freed != &memheap->oh_used) {
3331  if(poh_freed->offset == base) {
3332  foundNode = 1;
3333  break;
3334  }
3335 
3336  poh_freed = poh_freed->poh_next;
3337  }
3338 
3339  if(!foundNode)
3340  return NULL;
3341 
3342  memheap->max_freesize += poh_freed->size;
3343 
3344  poh_prev = poh_next = NULL;
3345  ulUpper = poh_freed->offset + poh_freed->size;
3346  ulLower = poh_freed->offset;
3347 
3348  pohThis = memheap->oh_free.poh_next;
3349 
3350  while(pohThis != &memheap->oh_free) {
3351  if(pohThis->offset == ulUpper) {
3352  poh_next = pohThis;
3353  } else if((pohThis->offset + pohThis->size) == ulLower) {
3354  poh_prev = pohThis;
3355  }
3356  pohThis = pohThis->poh_next;
3357  }
3358 
3359  sisfb_delete_node(poh_freed);
3360 
3361  if(poh_prev && poh_next) {
3362  poh_prev->size += (poh_freed->size + poh_next->size);
3363  sisfb_delete_node(poh_next);
3364  sisfb_free_node(memheap, poh_freed);
3365  sisfb_free_node(memheap, poh_next);
3366  return poh_prev;
3367  }
3368 
3369  if(poh_prev) {
3370  poh_prev->size += poh_freed->size;
3371  sisfb_free_node(memheap, poh_freed);
3372  return poh_prev;
3373  }
3374 
3375  if(poh_next) {
3376  poh_next->size += poh_freed->size;
3377  poh_next->offset = poh_freed->offset;
3378  sisfb_free_node(memheap, poh_freed);
3379  return poh_next;
3380  }
3381 
3382  sisfb_insert_node(&memheap->oh_free, poh_freed);
3383 
3384  return poh_freed;
3385 }
3386 
3387 static void
3388 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3389 {
3390  if(poh == NULL)
3391  return;
3392 
3393  poh->poh_next = memheap->poh_freelist;
3394  memheap->poh_freelist = poh;
3395 }
3396 
3397 static void
3398 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3399 {
3400  struct SIS_OH *poh = NULL;
3401 
3402  if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3403  poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3404 
3405  if(poh == NULL) {
3406  req->offset = req->size = 0;
3407  DPRINTK("sisfb: Video RAM allocation failed\n");
3408  } else {
3409  req->offset = poh->offset;
3410  req->size = poh->size;
3411  DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3412  (poh->offset + ivideo->video_vbase));
3413  }
3414 }
3415 
3416 void
3418 {
3419  struct sis_video_info *ivideo = sisfb_heap->vinfo;
3420 
3421  if(&ivideo->sisfb_heap == sisfb_heap)
3422  sis_int_malloc(ivideo, req);
3423  else
3424  req->offset = req->size = 0;
3425 }
3426 
3427 void
3428 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3429 {
3430  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3431 
3432  sis_int_malloc(ivideo, req);
3433 }
3434 
3435 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3436 
3437 static void
3438 sis_int_free(struct sis_video_info *ivideo, u32 base)
3439 {
3440  struct SIS_OH *poh;
3441 
3442  if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3443  return;
3444 
3445  poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3446 
3447  if(poh == NULL) {
3448  DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3449  (unsigned int) base);
3450  }
3451 }
3452 
3453 void
3455 {
3456  struct sis_video_info *ivideo = sisfb_heap->vinfo;
3457 
3458  sis_int_free(ivideo, base);
3459 }
3460 
3461 void
3462 sis_free_new(struct pci_dev *pdev, u32 base)
3463 {
3464  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3465 
3466  sis_int_free(ivideo, base);
3467 }
3468 
3469 /* --------------------- SetMode routines ------------------------- */
3470 
3471 static void
3472 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3473 {
3474  u8 cr30, cr31;
3475 
3476  /* Check if MMIO and engines are enabled,
3477  * and sync in case they are. Can't use
3478  * ivideo->accel here, as this might have
3479  * been changed before this is called.
3480  */
3483  /* MMIO and 2D/3D engine enabled? */
3484  if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3485 #ifdef CONFIG_FB_SIS_300
3486  if(ivideo->sisvga_engine == SIS_300_VGA) {
3487  /* Don't care about TurboQueue. It's
3488  * enough to know that the engines
3489  * are enabled
3490  */
3491  sisfb_syncaccel(ivideo);
3492  }
3493 #endif
3494 #ifdef CONFIG_FB_SIS_315
3495  if(ivideo->sisvga_engine == SIS_315_VGA) {
3496  /* Check that any queue mode is
3497  * enabled, and that the queue
3498  * is not in the state of "reset"
3499  */
3500  cr30 = SiS_GetReg(SISSR, 0x26);
3501  if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3502  sisfb_syncaccel(ivideo);
3503  }
3504  }
3505 #endif
3506  }
3507 }
3508 
3509 static void
3510 sisfb_pre_setmode(struct sis_video_info *ivideo)
3511 {
3512  u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3513  int tvregnum = 0;
3514 
3516 
3517  SiS_SetReg(SISSR, 0x05, 0x86);
3518 
3519  cr31 = SiS_GetReg(SISCR, 0x31);
3520  cr31 &= ~0x60;
3521  cr31 |= 0x04;
3522 
3523  cr33 = ivideo->rate_idx & 0x0F;
3524 
3525 #ifdef CONFIG_FB_SIS_315
3526  if(ivideo->sisvga_engine == SIS_315_VGA) {
3527  if(ivideo->chip >= SIS_661) {
3528  cr38 = SiS_GetReg(SISCR, 0x38);
3529  cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3530  } else {
3531  tvregnum = 0x38;
3532  cr38 = SiS_GetReg(SISCR, tvregnum);
3533  cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3534  }
3535  }
3536 #endif
3537 #ifdef CONFIG_FB_SIS_300
3538  if(ivideo->sisvga_engine == SIS_300_VGA) {
3539  tvregnum = 0x35;
3540  cr38 = SiS_GetReg(SISCR, tvregnum);
3541  }
3542 #endif
3543 
3544  SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3545  SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3546  ivideo->curFSTN = ivideo->curDSTN = 0;
3547 
3548  switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3549 
3550  case CRT2_TV:
3551  cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3552  if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3553 #ifdef CONFIG_FB_SIS_315
3554  if(ivideo->chip >= SIS_661) {
3555  cr38 |= 0x04;
3556  if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3557  else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3558  else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3560  cr35 &= ~0x01;
3561  ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3562  } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3563  cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3564  cr38 |= 0x08;
3565  if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3566  else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3567  else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3568  cr31 &= ~0x01;
3569  ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3570  }
3571 #endif
3572  } else if((ivideo->vbflags & TV_HIVISION) &&
3573  (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3574  if(ivideo->chip >= SIS_661) {
3575  cr38 |= 0x04;
3576  cr35 |= 0x60;
3577  } else {
3578  cr30 |= 0x80;
3579  }
3581  cr31 |= 0x01;
3582  cr35 |= 0x01;
3583  ivideo->currentvbflags |= TV_HIVISION;
3584  } else if(ivideo->vbflags & TV_SCART) {
3586  cr31 |= 0x01;
3587  cr35 |= 0x01;
3588  ivideo->currentvbflags |= TV_SCART;
3589  } else {
3590  if(ivideo->vbflags & TV_SVIDEO) {
3592  ivideo->currentvbflags |= TV_SVIDEO;
3593  }
3594  if(ivideo->vbflags & TV_AVIDEO) {
3596  ivideo->currentvbflags |= TV_AVIDEO;
3597  }
3598  }
3599  cr31 |= SIS_DRIVER_MODE;
3600 
3601  if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3602  if(ivideo->vbflags & TV_PAL) {
3603  cr31 |= 0x01; cr35 |= 0x01;
3604  ivideo->currentvbflags |= TV_PAL;
3605  if(ivideo->vbflags & TV_PALM) {
3606  cr38 |= 0x40; cr35 |= 0x04;
3607  ivideo->currentvbflags |= TV_PALM;
3608  } else if(ivideo->vbflags & TV_PALN) {
3609  cr38 |= 0x80; cr35 |= 0x08;
3610  ivideo->currentvbflags |= TV_PALN;
3611  }
3612  } else {
3613  cr31 &= ~0x01; cr35 &= ~0x01;
3614  ivideo->currentvbflags |= TV_NTSC;
3615  if(ivideo->vbflags & TV_NTSCJ) {
3616  cr38 |= 0x40; cr35 |= 0x02;
3617  ivideo->currentvbflags |= TV_NTSCJ;
3618  }
3619  }
3620  }
3621  break;
3622 
3623  case CRT2_LCD:
3625  cr31 |= SIS_DRIVER_MODE;
3626  SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3627  SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3628  ivideo->curFSTN = ivideo->sisfb_fstn;
3629  ivideo->curDSTN = ivideo->sisfb_dstn;
3630  break;
3631 
3632  case CRT2_VGA:
3634  cr31 |= SIS_DRIVER_MODE;
3635  if(ivideo->sisfb_nocrt2rate) {
3636  cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3637  } else {
3638  cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3639  }
3640  break;
3641 
3642  default: /* disable CRT2 */
3643  cr30 = 0x00;
3645  }
3646 
3647  SiS_SetReg(SISCR, 0x30, cr30);
3648  SiS_SetReg(SISCR, 0x33, cr33);
3649 
3650  if(ivideo->chip >= SIS_661) {
3651 #ifdef CONFIG_FB_SIS_315
3652  cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3653  SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3654  cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3655  SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3656 #endif
3657  } else if(ivideo->chip != SIS_300) {
3658  SiS_SetReg(SISCR, tvregnum, cr38);
3659  }
3660  SiS_SetReg(SISCR, 0x31, cr31);
3661 
3662  ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3663 
3664  sisfb_check_engine_and_sync(ivideo);
3665 }
3666 
3667 /* Fix SR11 for 661 and later */
3668 #ifdef CONFIG_FB_SIS_315
3669 static void
3670 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3671 {
3672  u8 tmpreg;
3673 
3674  if(ivideo->chip >= SIS_661) {
3675  tmpreg = SiS_GetReg(SISSR, 0x11);
3676  if(tmpreg & 0x20) {
3677  tmpreg = SiS_GetReg(SISSR, 0x3e);
3678  tmpreg = (tmpreg + 1) & 0xff;
3679  SiS_SetReg(SISSR, 0x3e, tmpreg);
3680  tmpreg = SiS_GetReg(SISSR, 0x11);
3681  }
3682  if(tmpreg & 0xf0) {
3683  SiS_SetRegAND(SISSR, 0x11, 0x0f);
3684  }
3685  }
3686 }
3687 #endif
3688 
3689 static void
3690 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3691 {
3692  if(val > 32) val = 32;
3693  if(val < -32) val = -32;
3694  ivideo->tvxpos = val;
3695 
3696  if(ivideo->sisfblocked) return;
3697  if(!ivideo->modechanged) return;
3698 
3699  if(ivideo->currentvbflags & CRT2_TV) {
3700 
3701  if(ivideo->vbflags2 & VB2_CHRONTEL) {
3702 
3703  int x = ivideo->tvx;
3704 
3705  switch(ivideo->chronteltype) {
3706  case 1:
3707  x += val;
3708  if(x < 0) x = 0;
3709  SiS_SetReg(SISSR, 0x05, 0x86);
3710  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3711  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3712  break;
3713  case 2:
3714  /* Not supported by hardware */
3715  break;
3716  }
3717 
3718  } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3719 
3721  unsigned short temp;
3722 
3723  p2_1f = ivideo->p2_1f;
3724  p2_20 = ivideo->p2_20;
3725  p2_2b = ivideo->p2_2b;
3726  p2_42 = ivideo->p2_42;
3727  p2_43 = ivideo->p2_43;
3728 
3729  temp = p2_1f | ((p2_20 & 0xf0) << 4);
3730  temp += (val * 2);
3731  p2_1f = temp & 0xff;
3732  p2_20 = (temp & 0xf00) >> 4;
3733  p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3734  temp = p2_43 | ((p2_42 & 0xf0) << 4);
3735  temp += (val * 2);
3736  p2_43 = temp & 0xff;
3737  p2_42 = (temp & 0xf00) >> 4;
3738  SiS_SetReg(SISPART2, 0x1f, p2_1f);
3739  SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3740  SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3741  SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3742  SiS_SetReg(SISPART2, 0x43, p2_43);
3743  }
3744  }
3745 }
3746 
3747 static void
3748 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3749 {
3750  if(val > 32) val = 32;
3751  if(val < -32) val = -32;
3752  ivideo->tvypos = val;
3753 
3754  if(ivideo->sisfblocked) return;
3755  if(!ivideo->modechanged) return;
3756 
3757  if(ivideo->currentvbflags & CRT2_TV) {
3758 
3759  if(ivideo->vbflags2 & VB2_CHRONTEL) {
3760 
3761  int y = ivideo->tvy;
3762 
3763  switch(ivideo->chronteltype) {
3764  case 1:
3765  y -= val;
3766  if(y < 0) y = 0;
3767  SiS_SetReg(SISSR, 0x05, 0x86);
3768  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3769  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3770  break;
3771  case 2:
3772  /* Not supported by hardware */
3773  break;
3774  }
3775 
3776  } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3777 
3778  char p2_01, p2_02;
3779  val /= 2;
3780  p2_01 = ivideo->p2_01;
3781  p2_02 = ivideo->p2_02;
3782 
3783  p2_01 += val;
3784  p2_02 += val;
3785  if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3786  while((p2_01 <= 0) || (p2_02 <= 0)) {
3787  p2_01 += 2;
3788  p2_02 += 2;
3789  }
3790  }
3791  SiS_SetReg(SISPART2, 0x01, p2_01);
3792  SiS_SetReg(SISPART2, 0x02, p2_02);
3793  }
3794  }
3795 }
3796 
3797 static void
3798 sisfb_post_setmode(struct sis_video_info *ivideo)
3799 {
3800  bool crt1isoff = false;
3801  bool doit = true;
3802 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3803  u8 reg;
3804 #endif
3805 #ifdef CONFIG_FB_SIS_315
3806  u8 reg1;
3807 #endif
3808 
3809  SiS_SetReg(SISSR, 0x05, 0x86);
3810 
3811 #ifdef CONFIG_FB_SIS_315
3812  sisfb_fixup_SR11(ivideo);
3813 #endif
3814 
3815  /* Now we actually HAVE changed the display mode */
3816  ivideo->modechanged = 1;
3817 
3818  /* We can't switch off CRT1 if bridge is in slave mode */
3819  if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3820  if(sisfb_bridgeisslave(ivideo)) doit = false;
3821  } else
3822  ivideo->sisfb_crt1off = 0;
3823 
3824 #ifdef CONFIG_FB_SIS_300
3825  if(ivideo->sisvga_engine == SIS_300_VGA) {
3826  if((ivideo->sisfb_crt1off) && (doit)) {
3827  crt1isoff = true;
3828  reg = 0x00;
3829  } else {
3830  crt1isoff = false;
3831  reg = 0x80;
3832  }
3833  SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3834  }
3835 #endif
3836 #ifdef CONFIG_FB_SIS_315
3837  if(ivideo->sisvga_engine == SIS_315_VGA) {
3838  if((ivideo->sisfb_crt1off) && (doit)) {
3839  crt1isoff = true;
3840  reg = 0x40;
3841  reg1 = 0xc0;
3842  } else {
3843  crt1isoff = false;
3844  reg = 0x00;
3845  reg1 = 0x00;
3846  }
3847  SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3848  SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3849  }
3850 #endif
3851 
3852  if(crt1isoff) {
3853  ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3854  ivideo->currentvbflags |= VB_SINGLE_MODE;
3855  } else {
3856  ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3857  if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3858  ivideo->currentvbflags |= VB_MIRROR_MODE;
3859  } else {
3860  ivideo->currentvbflags |= VB_SINGLE_MODE;
3861  }
3862  }
3863 
3865 
3866  if(ivideo->currentvbflags & CRT2_TV) {
3867  if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3868  ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3869  ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3870  ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3871  ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3872  ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3873  ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3874  ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3875  } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3876  if(ivideo->chronteltype == 1) {
3877  ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3878  ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3879  ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3880  ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3881  }
3882  }
3883  }
3884 
3885  if(ivideo->tvxpos) {
3886  sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3887  }
3888  if(ivideo->tvypos) {
3889  sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3890  }
3891 
3892  /* Eventually sync engines */
3893  sisfb_check_engine_and_sync(ivideo);
3894 
3895  /* (Re-)Initialize chip engines */
3896  if(ivideo->accel) {
3897  sisfb_engine_init(ivideo);
3898  } else {
3899  ivideo->engineok = 0;
3900  }
3901 }
3902 
3903 static int
3904 sisfb_reset_mode(struct sis_video_info *ivideo)
3905 {
3906  if(sisfb_set_mode(ivideo, 0))
3907  return 1;
3908 
3909  sisfb_set_pitch(ivideo);
3910  sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3911  sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3912 
3913  return 0;
3914 }
3915 
3916 static void
3917 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3918 {
3919  int mycrt1off;
3920 
3921  switch(sisfb_command->sisfb_cmd) {
3922  case SISFB_CMD_GETVBFLAGS:
3923  if(!ivideo->modechanged) {
3924  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3925  } else {
3926  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3927  sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3928  sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3929  }
3930  break;
3931  case SISFB_CMD_SWITCHCRT1:
3932  /* arg[0]: 0 = off, 1 = on, 99 = query */
3933  if(!ivideo->modechanged) {
3934  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3935  } else if(sisfb_command->sisfb_arg[0] == 99) {
3936  /* Query */
3937  sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3938  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3939  } else if(ivideo->sisfblocked) {
3940  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3941  } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3942  (sisfb_command->sisfb_arg[0] == 0)) {
3943  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3944  } else {
3945  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3946  mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3947  if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3948  ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3949  ivideo->sisfb_crt1off = mycrt1off;
3950  if(sisfb_reset_mode(ivideo)) {
3951  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3952  }
3953  }
3954  sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3955  }
3956  break;
3957  /* more to come */
3958  default:
3959  sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3960  printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3961  sisfb_command->sisfb_cmd);
3962  }
3963 }
3964 
3965 #ifndef MODULE
3966 static int __init sisfb_setup(char *options)
3967 {
3968  char *this_opt;
3969 
3970  sisfb_setdefaultparms();
3971 
3972  if(!options || !(*options))
3973  return 0;
3974 
3975  while((this_opt = strsep(&options, ",")) != NULL) {
3976 
3977  if(!(*this_opt)) continue;
3978 
3979  if(!strnicmp(this_opt, "off", 3)) {
3980  sisfb_off = 1;
3981  } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
3982  /* Need to check crt2 type first for fstn/dstn */
3983  sisfb_search_crt2type(this_opt + 14);
3984  } else if(!strnicmp(this_opt, "tvmode:",7)) {
3985  sisfb_search_tvstd(this_opt + 7);
3986  } else if(!strnicmp(this_opt, "tvstandard:",11)) {
3987  sisfb_search_tvstd(this_opt + 11);
3988  } else if(!strnicmp(this_opt, "mode:", 5)) {
3989  sisfb_search_mode(this_opt + 5, false);
3990  } else if(!strnicmp(this_opt, "vesa:", 5)) {
3991  sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
3992  } else if(!strnicmp(this_opt, "rate:", 5)) {
3993  sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3994  } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
3995  sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3996  } else if(!strnicmp(this_opt, "mem:",4)) {
3997  sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
3998  } else if(!strnicmp(this_opt, "pdc:", 4)) {
3999  sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4000  } else if(!strnicmp(this_opt, "pdc1:", 5)) {
4001  sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4002  } else if(!strnicmp(this_opt, "noaccel", 7)) {
4003  sisfb_accel = 0;
4004  } else if(!strnicmp(this_opt, "accel", 5)) {
4005  sisfb_accel = -1;
4006  } else if(!strnicmp(this_opt, "noypan", 6)) {
4007  sisfb_ypan = 0;
4008  } else if(!strnicmp(this_opt, "ypan", 4)) {
4009  sisfb_ypan = -1;
4010  } else if(!strnicmp(this_opt, "nomax", 5)) {
4011  sisfb_max = 0;
4012  } else if(!strnicmp(this_opt, "max", 3)) {
4013  sisfb_max = -1;
4014  } else if(!strnicmp(this_opt, "userom:", 7)) {
4015  sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4016  } else if(!strnicmp(this_opt, "useoem:", 7)) {
4017  sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4018  } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
4019  sisfb_nocrt2rate = 1;
4020  } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
4021  unsigned long temp = 2;
4022  temp = simple_strtoul(this_opt + 9, NULL, 0);
4023  if((temp == 0) || (temp == 1)) {
4024  sisfb_scalelcd = temp ^ 1;
4025  }
4026  } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
4027  int temp = 0;
4028  temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4029  if((temp >= -32) && (temp <= 32)) {
4030  sisfb_tvxposoffset = temp;
4031  }
4032  } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
4033  int temp = 0;
4034  temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4035  if((temp >= -32) && (temp <= 32)) {
4036  sisfb_tvyposoffset = temp;
4037  }
4038  } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
4039  sisfb_search_specialtiming(this_opt + 14);
4040  } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
4041  int temp = 4;
4042  temp = simple_strtoul(this_opt + 7, NULL, 0);
4043  if((temp >= 0) && (temp <= 3)) {
4044  sisfb_lvdshl = temp;
4045  }
4046  } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4047  sisfb_search_mode(this_opt, true);
4048 #if !defined(__i386__) && !defined(__x86_64__)
4049  } else if(!strnicmp(this_opt, "resetcard", 9)) {
4050  sisfb_resetcard = 1;
4051  } else if(!strnicmp(this_opt, "videoram:", 9)) {
4052  sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4053 #endif
4054  } else {
4055  printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4056  }
4057 
4058  }
4059 
4060  return 0;
4061 }
4062 #endif
4063 
4064 static int __devinit
4065 sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
4066 {
4067  void __iomem *rom;
4068  int romptr;
4069 
4070  if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4071  return 0;
4072 
4073  romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4074  if(romptr > (0x10000 - 8))
4075  return 0;
4076 
4077  rom = rom_base + romptr;
4078 
4079  if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4080  (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4081  return 0;
4082 
4083  if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4084  return 0;
4085 
4086  if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4087  return 0;
4088 
4089  return 1;
4090 }
4091 
4092 static unsigned char * __devinit
4093 sisfb_find_rom(struct pci_dev *pdev)
4094 {
4095  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4096  void __iomem *rom_base;
4097  unsigned char *myrombase = NULL;
4098  size_t romsize;
4099 
4100  /* First, try the official pci ROM functions (except
4101  * on integrated chipsets which have no ROM).
4102  */
4103 
4104  if(!ivideo->nbridge) {
4105 
4106  if((rom_base = pci_map_rom(pdev, &romsize))) {
4107 
4108  if(sisfb_check_rom(rom_base, ivideo)) {
4109 
4110  if((myrombase = vmalloc(65536))) {
4111  memcpy_fromio(myrombase, rom_base,
4112  (romsize > 65536) ? 65536 : romsize);
4113  }
4114  }
4115  pci_unmap_rom(pdev, rom_base);
4116  }
4117  }
4118 
4119  if(myrombase) return myrombase;
4120 
4121  /* Otherwise do it the conventional way. */
4122 
4123 #if defined(__i386__) || defined(__x86_64__)
4124  {
4125  u32 temp;
4126 
4127  for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4128 
4129  rom_base = ioremap(temp, 65536);
4130  if (!rom_base)
4131  continue;
4132 
4133  if (!sisfb_check_rom(rom_base, ivideo)) {
4134  iounmap(rom_base);
4135  continue;
4136  }
4137 
4138  if ((myrombase = vmalloc(65536)))
4139  memcpy_fromio(myrombase, rom_base, 65536);
4140 
4141  iounmap(rom_base);
4142  break;
4143 
4144  }
4145 
4146  }
4147 #endif
4148 
4149  return myrombase;
4150 }
4151 
4152 static void __devinit
4153 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4154  unsigned int min)
4155 {
4156  if (*mapsize < (min << 20))
4157  return;
4158 
4159  ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4160 
4161  if(!ivideo->video_vbase) {
4163  "sisfb: Unable to map maximum video RAM for size detection\n");
4164  (*mapsize) >>= 1;
4165  while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4166  (*mapsize) >>= 1;
4167  if((*mapsize) < (min << 20))
4168  break;
4169  }
4170  if(ivideo->video_vbase) {
4172  "sisfb: Video RAM size detection limited to %dMB\n",
4173  (int)((*mapsize) >> 20));
4174  }
4175  }
4176 }
4177 
4178 #ifdef CONFIG_FB_SIS_300
4179 static int __devinit
4180 sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4181 {
4182  void __iomem *FBAddress = ivideo->video_vbase;
4183  unsigned short temp;
4184  unsigned char reg;
4185  int i, j;
4186 
4187  SiS_SetRegAND(SISSR, 0x15, 0xFB);
4188  SiS_SetRegOR(SISSR, 0x15, 0x04);
4189  SiS_SetReg(SISSR, 0x13, 0x00);
4190  SiS_SetReg(SISSR, 0x14, 0xBF);
4191 
4192  for(i = 0; i < 2; i++) {
4193  temp = 0x1234;
4194  for(j = 0; j < 4; j++) {
4195  writew(temp, FBAddress);
4196  if(readw(FBAddress) == temp)
4197  break;
4198  SiS_SetRegOR(SISSR, 0x3c, 0x01);
4199  reg = SiS_GetReg(SISSR, 0x05);
4200  reg = SiS_GetReg(SISSR, 0x05);
4201  SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4202  reg = SiS_GetReg(SISSR, 0x05);
4203  reg = SiS_GetReg(SISSR, 0x05);
4204  temp++;
4205  }
4206  }
4207 
4208  writel(0x01234567L, FBAddress);
4209  writel(0x456789ABL, (FBAddress + 4));
4210  writel(0x89ABCDEFL, (FBAddress + 8));
4211  writel(0xCDEF0123L, (FBAddress + 12));
4212 
4213  reg = SiS_GetReg(SISSR, 0x3b);
4214  if(reg & 0x01) {
4215  if(readl((FBAddress + 12)) == 0xCDEF0123L)
4216  return 4; /* Channel A 128bit */
4217  }
4218 
4219  if(readl((FBAddress + 4)) == 0x456789ABL)
4220  return 2; /* Channel B 64bit */
4221 
4222  return 1; /* 32bit */
4223 }
4224 
4225 static const unsigned short __devinitconst SiS_DRAMType[17][5] = {
4226  {0x0C,0x0A,0x02,0x40,0x39},
4227  {0x0D,0x0A,0x01,0x40,0x48},
4228  {0x0C,0x09,0x02,0x20,0x35},
4229  {0x0D,0x09,0x01,0x20,0x44},
4230  {0x0C,0x08,0x02,0x10,0x31},
4231  {0x0D,0x08,0x01,0x10,0x40},
4232  {0x0C,0x0A,0x01,0x20,0x34},
4233  {0x0C,0x09,0x01,0x08,0x32},
4234  {0x0B,0x08,0x02,0x08,0x21},
4235  {0x0C,0x08,0x01,0x08,0x30},
4236  {0x0A,0x08,0x02,0x04,0x11},
4237  {0x0B,0x0A,0x01,0x10,0x28},
4238  {0x09,0x08,0x02,0x02,0x01},
4239  {0x0B,0x09,0x01,0x08,0x24},
4240  {0x0B,0x08,0x01,0x04,0x20},
4241  {0x0A,0x08,0x01,0x02,0x10},
4242  {0x09,0x08,0x01,0x01,0x00}
4243 };
4244 
4245 static int __devinit
4246 sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
4247  int PseudoRankCapacity, int PseudoAdrPinCount,
4248  unsigned int mapsize)
4249 {
4250  void __iomem *FBAddr = ivideo->video_vbase;
4251  unsigned short sr14;
4252  unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4253  unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4254 
4255  for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4256 
4257  RankCapacity = buswidth * SiS_DRAMType[k][3];
4258 
4259  if(RankCapacity != PseudoRankCapacity)
4260  continue;
4261 
4262  if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4263  continue;
4264 
4265  BankNumHigh = RankCapacity * 16 * iteration - 1;
4266  if(iteration == 3) { /* Rank No */
4267  BankNumMid = RankCapacity * 16 - 1;
4268  } else {
4269  BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4270  }
4271 
4272  PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4273  PhysicalAdrHigh = BankNumHigh;
4274  PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4275  PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4276 
4277  SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4278  SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4279  sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4280  if(buswidth == 4) sr14 |= 0x80;
4281  else if(buswidth == 2) sr14 |= 0x40;
4282  SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4283  SiS_SetReg(SISSR, 0x14, sr14);
4284 
4285  BankNumHigh <<= 16;
4286  BankNumMid <<= 16;
4287 
4288  if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4289  (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4290  (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4291  (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4292  continue;
4293 
4294  /* Write data */
4295  writew(((unsigned short)PhysicalAdrHigh),
4296  (FBAddr + BankNumHigh + PhysicalAdrHigh));
4297  writew(((unsigned short)BankNumMid),
4298  (FBAddr + BankNumMid + PhysicalAdrHigh));
4299  writew(((unsigned short)PhysicalAdrHalfPage),
4300  (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4301  writew(((unsigned short)PhysicalAdrOtherPage),
4302  (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4303 
4304  /* Read data */
4305  if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4306  return 1;
4307  }
4308 
4309  return 0;
4310 }
4311 
4312 static void __devinit
4313 sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4314 {
4315  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4316  int i, j, buswidth;
4317  int PseudoRankCapacity, PseudoAdrPinCount;
4318 
4319  buswidth = sisfb_post_300_buswidth(ivideo);
4320 
4321  for(i = 6; i >= 0; i--) {
4322  PseudoRankCapacity = 1 << i;
4323  for(j = 4; j >= 1; j--) {
4324  PseudoAdrPinCount = 15 - j;
4325  if((PseudoRankCapacity * j) <= 64) {
4326  if(sisfb_post_300_rwtest(ivideo,
4327  j,
4328  buswidth,
4329  PseudoRankCapacity,
4330  PseudoAdrPinCount,
4331  mapsize))
4332  return;
4333  }
4334  }
4335  }
4336 }
4337 
4338 static void __devinit
4339 sisfb_post_sis300(struct pci_dev *pdev)
4340 {
4341  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4342  unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4343  u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4344  u16 index, rindex, memtype = 0;
4345  unsigned int mapsize;
4346 
4347  if(!ivideo->SiS_Pr.UseROM)
4348  bios = NULL;
4349 
4350  SiS_SetReg(SISSR, 0x05, 0x86);
4351 
4352  if(bios) {
4353  if(bios[0x52] & 0x80) {
4354  memtype = bios[0x52];
4355  } else {
4356  memtype = SiS_GetReg(SISSR, 0x3a);
4357  }
4358  memtype &= 0x07;
4359  }
4360 
4361  v3 = 0x80; v6 = 0x80;
4362  if(ivideo->revision_id <= 0x13) {
4363  v1 = 0x44; v2 = 0x42;
4364  v4 = 0x44; v5 = 0x42;
4365  } else {
4366  v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4367  v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4368  if(bios) {
4369  index = memtype * 5;
4370  rindex = index + 0x54;
4371  v1 = bios[rindex++];
4372  v2 = bios[rindex++];
4373  v3 = bios[rindex++];
4374  rindex = index + 0x7c;
4375  v4 = bios[rindex++];
4376  v5 = bios[rindex++];
4377  v6 = bios[rindex++];
4378  }
4379  }
4380  SiS_SetReg(SISSR, 0x28, v1);
4381  SiS_SetReg(SISSR, 0x29, v2);
4382  SiS_SetReg(SISSR, 0x2a, v3);
4383  SiS_SetReg(SISSR, 0x2e, v4);
4384  SiS_SetReg(SISSR, 0x2f, v5);
4385  SiS_SetReg(SISSR, 0x30, v6);
4386 
4387  v1 = 0x10;
4388  if(bios)
4389  v1 = bios[0xa4];
4390  SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4391 
4392  SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4393 
4394  v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4395  v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4396  if(bios) {
4397  memtype += 0xa5;
4398  v1 = bios[memtype];
4399  v2 = bios[memtype + 8];
4400  v3 = bios[memtype + 16];
4401  v4 = bios[memtype + 24];
4402  v5 = bios[memtype + 32];
4403  v6 = bios[memtype + 40];
4404  v7 = bios[memtype + 48];
4405  v8 = bios[memtype + 56];
4406  }
4407  if(ivideo->revision_id >= 0x80)
4408  v3 &= 0xfd;
4409  SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4410  SiS_SetReg(SISSR, 0x16, v2);
4411  SiS_SetReg(SISSR, 0x17, v3);
4412  SiS_SetReg(SISSR, 0x18, v4);
4413  SiS_SetReg(SISSR, 0x19, v5);
4414  SiS_SetReg(SISSR, 0x1a, v6);
4415  SiS_SetReg(SISSR, 0x1b, v7);
4416  SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4417  SiS_SetRegAND(SISSR, 0x15, 0xfb);
4418  SiS_SetRegOR(SISSR, 0x15, 0x04);
4419  if(bios) {
4420  if(bios[0x53] & 0x02) {
4421  SiS_SetRegOR(SISSR, 0x19, 0x20);
4422  }
4423  }
4424  v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4425  if(ivideo->revision_id >= 0x80)
4426  v1 |= 0x01;
4427  SiS_SetReg(SISSR, 0x1f, v1);
4428  SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4429  v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4430  if(bios) {
4431  v1 = bios[0xe8];
4432  v2 = bios[0xe9];
4433  v3 = bios[0xea];
4434  }
4435  SiS_SetReg(SISSR, 0x23, v1);
4436  SiS_SetReg(SISSR, 0x24, v2);
4437  SiS_SetReg(SISSR, 0x25, v3);
4438  SiS_SetReg(SISSR, 0x21, 0x84);
4439  SiS_SetReg(SISSR, 0x22, 0x00);
4440  SiS_SetReg(SISCR, 0x37, 0x00);
4441  SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4442  SiS_SetReg(SISPART1, 0x00, 0x00);
4443  v1 = 0x40; v2 = 0x11;
4444  if(bios) {
4445  v1 = bios[0xec];
4446  v2 = bios[0xeb];
4447  }
4448  SiS_SetReg(SISPART1, 0x02, v1);
4449 
4450  if(ivideo->revision_id >= 0x80)
4451  v2 &= ~0x01;
4452 
4453  reg = SiS_GetReg(SISPART4, 0x00);
4454  if((reg == 1) || (reg == 2)) {
4455  SiS_SetReg(SISCR, 0x37, 0x02);
4456  SiS_SetReg(SISPART2, 0x00, 0x1c);
4457  v4 = 0x00; v5 = 0x00; v6 = 0x10;
4458  if(ivideo->SiS_Pr.UseROM) {
4459  v4 = bios[0xf5];
4460  v5 = bios[0xf6];
4461  v6 = bios[0xf7];
4462  }
4463  SiS_SetReg(SISPART4, 0x0d, v4);
4464  SiS_SetReg(SISPART4, 0x0e, v5);
4465  SiS_SetReg(SISPART4, 0x10, v6);
4466  SiS_SetReg(SISPART4, 0x0f, 0x3f);
4467  reg = SiS_GetReg(SISPART4, 0x01);
4468  if(reg >= 0xb0) {
4469  reg = SiS_GetReg(SISPART4, 0x23);
4470  reg &= 0x20;
4471  reg <<= 1;
4472  SiS_SetReg(SISPART4, 0x23, reg);
4473  }
4474  } else {
4475  v2 &= ~0x10;
4476  }
4477  SiS_SetReg(SISSR, 0x32, v2);
4478 
4479  SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4480 
4481  reg = SiS_GetReg(SISSR, 0x16);
4482  reg &= 0xc3;
4483  SiS_SetReg(SISCR, 0x35, reg);
4484  SiS_SetReg(SISCR, 0x83, 0x00);
4485 #if !defined(__i386__) && !defined(__x86_64__)
4486  if(sisfb_videoram) {
4487  SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4488  reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4489  SiS_SetReg(SISSR, 0x14, reg);
4490  } else {
4491 #endif
4492  /* Need to map max FB size for finding out about RAM size */
4493  mapsize = ivideo->video_size;
4494  sisfb_post_map_vram(ivideo, &mapsize, 4);
4495 
4496  if(ivideo->video_vbase) {
4497  sisfb_post_300_ramsize(pdev, mapsize);
4498  iounmap(ivideo->video_vbase);
4499  } else {
4501  "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4502  SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4503  SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4504  }
4505 #if !defined(__i386__) && !defined(__x86_64__)
4506  }
4507 #endif
4508  if(bios) {
4509  v1 = bios[0xe6];
4510  v2 = bios[0xe7];
4511  } else {
4512  reg = SiS_GetReg(SISSR, 0x3a);
4513  if((reg & 0x30) == 0x30) {
4514  v1 = 0x04; /* PCI */
4515  v2 = 0x92;
4516  } else {
4517  v1 = 0x14; /* AGP */
4518  v2 = 0xb2;
4519  }
4520  }
4521  SiS_SetReg(SISSR, 0x21, v1);
4522  SiS_SetReg(SISSR, 0x22, v2);
4523 
4524  /* Sense CRT1 */
4525  sisfb_sense_crt1(ivideo);
4526 
4527  /* Set default mode, don't clear screen */
4528  ivideo->SiS_Pr.SiS_UseOEM = false;
4529  SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4530  SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4531  ivideo->curFSTN = ivideo->curDSTN = 0;
4532  ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4533  SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4534 
4535  SiS_SetReg(SISSR, 0x05, 0x86);
4536 
4537  /* Display off */
4538  SiS_SetRegOR(SISSR, 0x01, 0x20);
4539 
4540  /* Save mode number in CR34 */
4541  SiS_SetReg(SISCR, 0x34, 0x2e);
4542 
4543  /* Let everyone know what the current mode is */
4544  ivideo->modeprechange = 0x2e;
4545 }
4546 #endif
4547 
4548 #ifdef CONFIG_FB_SIS_315
4549 #if 0
4550 static void __devinit
4551 sisfb_post_sis315330(struct pci_dev *pdev)
4552 {
4553  /* TODO */
4554 }
4555 #endif
4556 
4557 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4558 {
4559  return ivideo->chip_real_id == XGI_21;
4560 }
4561 
4562 static void __devinit
4563 sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4564 {
4565  unsigned int i;
4566  u8 reg;
4567 
4568  for(i = 0; i <= (delay * 10 * 36); i++) {
4569  reg = SiS_GetReg(SISSR, 0x05);
4570  reg++;
4571  }
4572 }
4573 
4574 static int __devinit
4575 sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
4576  unsigned short pcivendor)
4577 {
4578  struct pci_dev *pdev = NULL;
4579  unsigned short temp;
4580  int ret = 0;
4581 
4582  while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4583  temp = pdev->vendor;
4584  if(temp == pcivendor) {
4585  ret = 1;
4586  pci_dev_put(pdev);
4587  break;
4588  }
4589  }
4590 
4591  return ret;
4592 }
4593 
4594 static int __devinit
4595 sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4596  unsigned int enda, unsigned int mapsize)
4597 {
4598  unsigned int pos;
4599  int i;
4600 
4601  writel(0, ivideo->video_vbase);
4602 
4603  for(i = starta; i <= enda; i++) {
4604  pos = 1 << i;
4605  if(pos < mapsize)
4606  writel(pos, ivideo->video_vbase + pos);
4607  }
4608 
4609  sisfb_post_xgi_delay(ivideo, 150);
4610 
4611  if(readl(ivideo->video_vbase) != 0)
4612  return 0;
4613 
4614  for(i = starta; i <= enda; i++) {
4615  pos = 1 << i;
4616  if(pos < mapsize) {
4617  if(readl(ivideo->video_vbase + pos) != pos)
4618  return 0;
4619  } else
4620  return 0;
4621  }
4622 
4623  return 1;
4624 }
4625 
4626 static int __devinit
4627 sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4628 {
4629  unsigned int buswidth, ranksize, channelab, mapsize;
4630  int i, j, k, l, status;
4631  u8 reg, sr14;
4632  static const u8 dramsr13[12 * 5] = {
4633  0x02, 0x0e, 0x0b, 0x80, 0x5d,
4634  0x02, 0x0e, 0x0a, 0x40, 0x59,
4635  0x02, 0x0d, 0x0b, 0x40, 0x4d,
4636  0x02, 0x0e, 0x09, 0x20, 0x55,
4637  0x02, 0x0d, 0x0a, 0x20, 0x49,
4638  0x02, 0x0c, 0x0b, 0x20, 0x3d,
4639  0x02, 0x0e, 0x08, 0x10, 0x51,
4640  0x02, 0x0d, 0x09, 0x10, 0x45,
4641  0x02, 0x0c, 0x0a, 0x10, 0x39,
4642  0x02, 0x0d, 0x08, 0x08, 0x41,
4643  0x02, 0x0c, 0x09, 0x08, 0x35,
4644  0x02, 0x0c, 0x08, 0x04, 0x31
4645  };
4646  static const u8 dramsr13_4[4 * 5] = {
4647  0x02, 0x0d, 0x09, 0x40, 0x45,
4648  0x02, 0x0c, 0x09, 0x20, 0x35,
4649  0x02, 0x0c, 0x08, 0x10, 0x31,
4650  0x02, 0x0b, 0x08, 0x08, 0x21
4651  };
4652 
4653  /* Enable linear mode, disable 0xa0000 address decoding */
4654  /* We disable a0000 address decoding, because
4655  * - if running on x86, if the card is disabled, it means
4656  * that another card is in the system. We don't want
4657  * to interphere with that primary card's textmode.
4658  * - if running on non-x86, there usually is no VGA window
4659  * at a0000.
4660  */
4661  SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4662 
4663  /* Need to map max FB size for finding out about RAM size */
4664  mapsize = ivideo->video_size;
4665  sisfb_post_map_vram(ivideo, &mapsize, 32);
4666 
4667  if(!ivideo->video_vbase) {
4668  printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4669  SiS_SetReg(SISSR, 0x13, 0x35);
4670  SiS_SetReg(SISSR, 0x14, 0x41);
4671  /* TODO */
4672  return -ENOMEM;
4673  }
4674 
4675  /* Non-interleaving */
4676  SiS_SetReg(SISSR, 0x15, 0x00);
4677  /* No tiling */
4678  SiS_SetReg(SISSR, 0x1c, 0x00);
4679 
4680  if(ivideo->chip == XGI_20) {
4681 
4682  channelab = 1;
4683  reg = SiS_GetReg(SISCR, 0x97);
4684  if(!(reg & 0x01)) { /* Single 32/16 */
4685  buswidth = 32;
4686  SiS_SetReg(SISSR, 0x13, 0xb1);
4687  SiS_SetReg(SISSR, 0x14, 0x52);
4688  sisfb_post_xgi_delay(ivideo, 1);
4689  sr14 = 0x02;
4690  if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4691  goto bail_out;
4692 
4693  SiS_SetReg(SISSR, 0x13, 0x31);
4694  SiS_SetReg(SISSR, 0x14, 0x42);
4695  sisfb_post_xgi_delay(ivideo, 1);
4696  if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4697  goto bail_out;
4698 
4699  buswidth = 16;
4700  SiS_SetReg(SISSR, 0x13, 0xb1);
4701  SiS_SetReg(SISSR, 0x14, 0x41);
4702  sisfb_post_xgi_delay(ivideo, 1);
4703  sr14 = 0x01;
4704  if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4705  goto bail_out;
4706  else
4707  SiS_SetReg(SISSR, 0x13, 0x31);
4708  } else { /* Dual 16/8 */
4709  buswidth = 16;
4710  SiS_SetReg(SISSR, 0x13, 0xb1);
4711  SiS_SetReg(SISSR, 0x14, 0x41);
4712  sisfb_post_xgi_delay(ivideo, 1);
4713  sr14 = 0x01;
4714  if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4715  goto bail_out;
4716 
4717  SiS_SetReg(SISSR, 0x13, 0x31);
4718  SiS_SetReg(SISSR, 0x14, 0x31);
4719  sisfb_post_xgi_delay(ivideo, 1);
4720  if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4721  goto bail_out;
4722 
4723  buswidth = 8;
4724  SiS_SetReg(SISSR, 0x13, 0xb1);
4725  SiS_SetReg(SISSR, 0x14, 0x30);
4726  sisfb_post_xgi_delay(ivideo, 1);
4727  sr14 = 0x00;
4728  if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4729  goto bail_out;
4730  else
4731  SiS_SetReg(SISSR, 0x13, 0x31);
4732  }
4733 
4734  } else { /* XGI_40 */
4735 
4736  reg = SiS_GetReg(SISCR, 0x97);
4737  if(!(reg & 0x10)) {
4738  reg = SiS_GetReg(SISSR, 0x39);
4739  reg >>= 1;
4740  }
4741 
4742  if(reg & 0x01) { /* DDRII */
4743  buswidth = 32;
4744  if(ivideo->revision_id == 2) {
4745  channelab = 2;
4746  SiS_SetReg(SISSR, 0x13, 0xa1);
4747  SiS_SetReg(SISSR, 0x14, 0x44);
4748  sr14 = 0x04;
4749  sisfb_post_xgi_delay(ivideo, 1);
4750  if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4751  goto bail_out;
4752 
4753  SiS_SetReg(SISSR, 0x13, 0x21);
4754  SiS_SetReg(SISSR, 0x14, 0x34);
4755  if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4756  goto bail_out;
4757 
4758  channelab = 1;
4759  SiS_SetReg(SISSR, 0x13, 0xa1);
4760  SiS_SetReg(SISSR, 0x14, 0x40);
4761  sr14 = 0x00;
4762  if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4763  goto bail_out;
4764 
4765  SiS_SetReg(SISSR, 0x13, 0x21);
4766  SiS_SetReg(SISSR, 0x14, 0x30);
4767  } else {
4768  channelab = 3;
4769  SiS_SetReg(SISSR, 0x13, 0xa1);
4770  SiS_SetReg(SISSR, 0x14, 0x4c);
4771  sr14 = 0x0c;
4772  sisfb_post_xgi_delay(ivideo, 1);
4773  if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4774  goto bail_out;
4775 
4776  channelab = 2;
4777  SiS_SetReg(SISSR, 0x14, 0x48);
4778  sisfb_post_xgi_delay(ivideo, 1);
4779  sr14 = 0x08;
4780  if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4781  goto bail_out;
4782 
4783  SiS_SetReg(SISSR, 0x13, 0x21);
4784  SiS_SetReg(SISSR, 0x14, 0x3c);
4785  sr14 = 0x0c;
4786 
4787  if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4788  channelab = 3;
4789  } else {
4790  channelab = 2;
4791  SiS_SetReg(SISSR, 0x14, 0x38);
4792  sr14 = 0x08;
4793  }
4794  }
4795  sisfb_post_xgi_delay(ivideo, 1);
4796 
4797  } else { /* DDR */
4798 
4799  buswidth = 64;
4800  if(ivideo->revision_id == 2) {
4801  channelab = 1;
4802  SiS_SetReg(SISSR, 0x13, 0xa1);
4803  SiS_SetReg(SISSR, 0x14, 0x52);
4804  sisfb_post_xgi_delay(ivideo, 1);
4805  sr14 = 0x02;
4806  if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4807  goto bail_out;
4808 
4809  SiS_SetReg(SISSR, 0x13, 0x21);
4810  SiS_SetReg(SISSR, 0x14, 0x42);
4811  } else {
4812  channelab = 2;
4813  SiS_SetReg(SISSR, 0x13, 0xa1);
4814  SiS_SetReg(SISSR, 0x14, 0x5a);
4815  sisfb_post_xgi_delay(ivideo, 1);
4816  sr14 = 0x0a;
4817  if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4818  goto bail_out;
4819 
4820  SiS_SetReg(SISSR, 0x13, 0x21);
4821  SiS_SetReg(SISSR, 0x14, 0x4a);
4822  }
4823  sisfb_post_xgi_delay(ivideo, 1);
4824 
4825  }
4826  }
4827 
4828 bail_out:
4829  SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4830  sisfb_post_xgi_delay(ivideo, 1);
4831 
4832  j = (ivideo->chip == XGI_20) ? 5 : 9;
4833  k = (ivideo->chip == XGI_20) ? 12 : 4;
4834  status = -EIO;
4835 
4836  for(i = 0; i < k; i++) {
4837 
4838  reg = (ivideo->chip == XGI_20) ?
4839  dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4840  SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4841  sisfb_post_xgi_delay(ivideo, 50);
4842 
4843  ranksize = (ivideo->chip == XGI_20) ?
4844  dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4845 
4846  reg = SiS_GetReg(SISSR, 0x13);
4847  if(reg & 0x80) ranksize <<= 1;
4848 
4849  if(ivideo->chip == XGI_20) {
4850  if(buswidth == 16) ranksize <<= 1;
4851  else if(buswidth == 32) ranksize <<= 2;
4852  } else {
4853  if(buswidth == 64) ranksize <<= 1;
4854  }
4855 
4856  reg = 0;
4857  l = channelab;
4858  if(l == 3) l = 4;
4859  if((ranksize * l) <= 256) {
4860  while((ranksize >>= 1)) reg += 0x10;
4861  }
4862 
4863  if(!reg) continue;
4864 
4865  SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4866  sisfb_post_xgi_delay(ivideo, 1);
4867 
4868  if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4869  status = 0;
4870  break;
4871  }
4872  }
4873 
4874  iounmap(ivideo->video_vbase);
4875 
4876  return status;
4877 }
4878 
4879 static void __devinit
4880 sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4881 {
4882  u8 v1, v2, v3;
4883  int index;
4884  static const u8 cs90[8 * 3] = {
4885  0x16, 0x01, 0x01,
4886  0x3e, 0x03, 0x01,
4887  0x7c, 0x08, 0x01,
4888  0x79, 0x06, 0x01,
4889  0x29, 0x01, 0x81,
4890  0x5c, 0x23, 0x01,
4891  0x5c, 0x23, 0x01,
4892  0x5c, 0x23, 0x01
4893  };
4894  static const u8 csb8[8 * 3] = {
4895  0x5c, 0x23, 0x01,
4896  0x29, 0x01, 0x01,
4897  0x7c, 0x08, 0x01,
4898  0x79, 0x06, 0x01,
4899  0x29, 0x01, 0x81,
4900  0x5c, 0x23, 0x01,
4901  0x5c, 0x23, 0x01,
4902  0x5c, 0x23, 0x01
4903  };
4904 
4905  regb = 0; /* ! */
4906 
4907  index = regb * 3;
4908  v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4909  if(ivideo->haveXGIROM) {
4910  v1 = ivideo->bios_abase[0x90 + index];
4911  v2 = ivideo->bios_abase[0x90 + index + 1];
4912  v3 = ivideo->bios_abase[0x90 + index + 2];
4913  }
4914  SiS_SetReg(SISSR, 0x28, v1);
4915  SiS_SetReg(SISSR, 0x29, v2);
4916  SiS_SetReg(SISSR, 0x2a, v3);
4917  sisfb_post_xgi_delay(ivideo, 0x43);
4918  sisfb_post_xgi_delay(ivideo, 0x43);
4919  sisfb_post_xgi_delay(ivideo, 0x43);
4920  index = regb * 3;
4921  v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4922  if(ivideo->haveXGIROM) {
4923  v1 = ivideo->bios_abase[0xb8 + index];
4924  v2 = ivideo->bios_abase[0xb8 + index + 1];
4925  v3 = ivideo->bios_abase[0xb8 + index + 2];
4926  }
4927  SiS_SetReg(SISSR, 0x2e, v1);
4928  SiS_SetReg(SISSR, 0x2f, v2);
4929  SiS_SetReg(SISSR, 0x30, v3);
4930  sisfb_post_xgi_delay(ivideo, 0x43);
4931  sisfb_post_xgi_delay(ivideo, 0x43);
4932  sisfb_post_xgi_delay(ivideo, 0x43);
4933 }
4934 
4935 static void __devinit
4936 sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
4937 {
4938  unsigned char *bios = ivideo->bios_abase;
4939  u8 v1;
4940 
4941  SiS_SetReg(SISSR, 0x28, 0x64);
4942  SiS_SetReg(SISSR, 0x29, 0x63);
4943  sisfb_post_xgi_delay(ivideo, 15);
4944  SiS_SetReg(SISSR, 0x18, 0x00);
4945  SiS_SetReg(SISSR, 0x19, 0x20);
4946  SiS_SetReg(SISSR, 0x16, 0x00);
4947  SiS_SetReg(SISSR, 0x16, 0x80);
4948  SiS_SetReg(SISSR, 0x18, 0xc5);
4949  SiS_SetReg(SISSR, 0x19, 0x23);
4950  SiS_SetReg(SISSR, 0x16, 0x00);
4951  SiS_SetReg(SISSR, 0x16, 0x80);
4952  sisfb_post_xgi_delay(ivideo, 1);
4953  SiS_SetReg(SISCR, 0x97, 0x11);
4954  sisfb_post_xgi_setclocks(ivideo, regb);
4955  sisfb_post_xgi_delay(ivideo, 0x46);
4956  SiS_SetReg(SISSR, 0x18, 0xc5);
4957  SiS_SetReg(SISSR, 0x19, 0x23);
4958  SiS_SetReg(SISSR, 0x16, 0x00);
4959  SiS_SetReg(SISSR, 0x16, 0x80);
4960  sisfb_post_xgi_delay(ivideo, 1);
4961  SiS_SetReg(SISSR, 0x1b, 0x04);
4962  sisfb_post_xgi_delay(ivideo, 1);
4963  SiS_SetReg(SISSR, 0x1b, 0x00);
4964  sisfb_post_xgi_delay(ivideo, 1);
4965  v1 = 0x31;
4966  if (ivideo->haveXGIROM) {
4967  v1 = bios[0xf0];
4968  }
4969  SiS_SetReg(SISSR, 0x18, v1);
4970  SiS_SetReg(SISSR, 0x19, 0x06);
4971  SiS_SetReg(SISSR, 0x16, 0x04);
4972  SiS_SetReg(SISSR, 0x16, 0x84);
4973  sisfb_post_xgi_delay(ivideo, 1);
4974 }
4975 
4976 static void __devinit
4977 sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4978 {
4979  sisfb_post_xgi_setclocks(ivideo, 1);
4980 
4981  SiS_SetReg(SISCR, 0x97, 0x11);
4982  sisfb_post_xgi_delay(ivideo, 0x46);
4983 
4984  SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
4985  SiS_SetReg(SISSR, 0x19, 0x80);
4986  SiS_SetReg(SISSR, 0x16, 0x05);
4987  SiS_SetReg(SISSR, 0x16, 0x85);
4988 
4989  SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
4990  SiS_SetReg(SISSR, 0x19, 0xc0);
4991  SiS_SetReg(SISSR, 0x16, 0x05);
4992  SiS_SetReg(SISSR, 0x16, 0x85);
4993 
4994  SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
4995  SiS_SetReg(SISSR, 0x19, 0x40);
4996  SiS_SetReg(SISSR, 0x16, 0x05);
4997  SiS_SetReg(SISSR, 0x16, 0x85);
4998 
4999  SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5000  SiS_SetReg(SISSR, 0x19, 0x02);
5001  SiS_SetReg(SISSR, 0x16, 0x05);
5002  SiS_SetReg(SISSR, 0x16, 0x85);
5003  sisfb_post_xgi_delay(ivideo, 1);
5004 
5005  SiS_SetReg(SISSR, 0x1b, 0x04);
5006  sisfb_post_xgi_delay(ivideo, 1);
5007 
5008  SiS_SetReg(SISSR, 0x1b, 0x00);
5009  sisfb_post_xgi_delay(ivideo, 1);
5010 
5011  SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5012  SiS_SetReg(SISSR, 0x19, 0x00);
5013  SiS_SetReg(SISSR, 0x16, 0x05);
5014  SiS_SetReg(SISSR, 0x16, 0x85);
5015  sisfb_post_xgi_delay(ivideo, 1);
5016 }
5017 
5018 static void __devinit
5019 sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5020 {
5021  unsigned char *bios = ivideo->bios_abase;
5022  static const u8 cs158[8] = {
5023  0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5024  };
5025  static const u8 cs160[8] = {
5026  0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5027  };
5028  static const u8 cs168[8] = {
5029  0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5030  };
5031  u8 reg;
5032  u8 v1;
5033  u8 v2;
5034  u8 v3;
5035 
5036  SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5037  SiS_SetReg(SISCR, 0x82, 0x77);
5038  SiS_SetReg(SISCR, 0x86, 0x00);
5039  reg = SiS_GetReg(SISCR, 0x86);
5040  SiS_SetReg(SISCR, 0x86, 0x88);
5041  reg = SiS_GetReg(SISCR, 0x86);
5042  v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5043  if (ivideo->haveXGIROM) {
5044  v1 = bios[regb + 0x168];
5045  v2 = bios[regb + 0x160];
5046  v3 = bios[regb + 0x158];
5047  }
5048  SiS_SetReg(SISCR, 0x86, v1);
5049  SiS_SetReg(SISCR, 0x82, 0x77);
5050  SiS_SetReg(SISCR, 0x85, 0x00);
5051  reg = SiS_GetReg(SISCR, 0x85);
5052  SiS_SetReg(SISCR, 0x85, 0x88);
5053  reg = SiS_GetReg(SISCR, 0x85);
5054  SiS_SetReg(SISCR, 0x85, v2);
5055  SiS_SetReg(SISCR, 0x82, v3);
5056  SiS_SetReg(SISCR, 0x98, 0x01);
5057  SiS_SetReg(SISCR, 0x9a, 0x02);
5058  if (sisfb_xgi_is21(ivideo))
5059  sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5060  else
5061  sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5062 }
5063 
5064 static u8 __devinit
5065 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5066 {
5067  unsigned char *bios = ivideo->bios_abase;
5068  u8 ramtype;
5069  u8 reg;
5070  u8 v1;
5071 
5072  ramtype = 0x00; v1 = 0x10;
5073  if (ivideo->haveXGIROM) {
5074  ramtype = bios[0x62];
5075  v1 = bios[0x1d2];
5076  }
5077  if (!(ramtype & 0x80)) {
5078  if (sisfb_xgi_is21(ivideo)) {
5079  SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5080  SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5081  reg = SiS_GetReg(SISCR, 0x48);
5082  SiS_SetRegOR(SISCR, 0xb4, 0x02);
5083  ramtype = reg & 0x01; /* GPIOH */
5084  } else if (ivideo->chip == XGI_20) {
5085  SiS_SetReg(SISCR, 0x97, v1);
5086  reg = SiS_GetReg(SISCR, 0x97);
5087  if (reg & 0x10) {
5088  ramtype = (reg & 0x01) << 1;
5089  }
5090  } else {
5091  reg = SiS_GetReg(SISSR, 0x39);
5092  ramtype = reg & 0x02;
5093  if (!(ramtype)) {
5094  reg = SiS_GetReg(SISSR, 0x3a);
5095  ramtype = (reg >> 1) & 0x01;
5096  }
5097  }
5098  }
5099  ramtype &= 0x07;
5100 
5101  return ramtype;
5102 }
5103 
5104 static int __devinit
5105 sisfb_post_xgi(struct pci_dev *pdev)
5106 {
5107  struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5108  unsigned char *bios = ivideo->bios_abase;
5109  struct pci_dev *mypdev = NULL;
5110  const u8 *ptr, *ptr2;
5111  u8 v1, v2, v3, v4, v5, reg, ramtype;
5112  u32 rega, regb, regd;
5113  int i, j, k, index;
5114  static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5115  static const u8 cs76[2] = { 0xa3, 0xfb };
5116  static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5117  static const u8 cs158[8] = {
5118  0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5119  };
5120  static const u8 cs160[8] = {
5121  0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5122  };
5123  static const u8 cs168[8] = {
5124  0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5125  };
5126  static const u8 cs128[3 * 8] = {
5127  0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5128  0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5129  0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5130  };
5131  static const u8 cs148[2 * 8] = {
5132  0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5133  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5134  };
5135  static const u8 cs31a[8 * 4] = {
5136  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5137  0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5138  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5139  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5140  };
5141  static const u8 cs33a[8 * 4] = {
5142  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5143  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5144  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5145  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5146  };
5147  static const u8 cs45a[8 * 2] = {
5148  0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5149  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5150  };
5151  static const u8 cs170[7 * 8] = {
5152  0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5153  0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5154  0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5155  0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5156  0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5157  0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5158  0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5159  };
5160  static const u8 cs1a8[3 * 8] = {
5161  0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5162  0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5163  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5164  };
5165  static const u8 cs100[2 * 8] = {
5166  0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5167  0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5168  };
5169 
5170  /* VGA enable */
5171  reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5173 
5174  /* Misc */
5175  reg = SiS_GetRegByte(SISMISCR) | 0x01;
5176  SiS_SetRegByte(SISMISCW, reg);
5177 
5178  /* Unlock SR */
5179  SiS_SetReg(SISSR, 0x05, 0x86);
5180  reg = SiS_GetReg(SISSR, 0x05);
5181  if(reg != 0xa1)
5182  return 0;
5183 
5184  /* Clear some regs */
5185  for(i = 0; i < 0x22; i++) {
5186  if(0x06 + i == 0x20) continue;
5187  SiS_SetReg(SISSR, 0x06 + i, 0x00);
5188  }
5189  for(i = 0; i < 0x0b; i++) {
5190  SiS_SetReg(SISSR, 0x31 + i, 0x00);
5191  }
5192  for(i = 0; i < 0x10; i++) {
5193  SiS_SetReg(SISCR, 0x30 + i, 0x00);
5194  }
5195 
5196  ptr = cs78;
5197  if(ivideo->haveXGIROM) {
5198  ptr = (const u8 *)&bios[0x78];
5199  }
5200  for(i = 0; i < 3; i++) {
5201  SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5202  }
5203 
5204  ptr = cs76;
5205  if(ivideo->haveXGIROM) {
5206  ptr = (const u8 *)&bios[0x76];
5207  }
5208  for(i = 0; i < 2; i++) {
5209  SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5210  }
5211 
5212  v1 = 0x18; v2 = 0x00;
5213  if(ivideo->haveXGIROM) {
5214  v1 = bios[0x74];
5215  v2 = bios[0x75];
5216  }
5217  SiS_SetReg(SISSR, 0x07, v1);
5218  SiS_SetReg(SISSR, 0x11, 0x0f);
5219  SiS_SetReg(SISSR, 0x1f, v2);
5220  /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5221  SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5222  SiS_SetReg(SISSR, 0x27, 0x74);
5223 
5224  ptr = cs7b;
5225  if(ivideo->haveXGIROM) {
5226  ptr = (const u8 *)&bios[0x7b];
5227  }
5228  for(i = 0; i < 3; i++) {
5229  SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5230  }
5231 
5232  if(ivideo->chip == XGI_40) {
5233  if(ivideo->revision_id == 2) {
5234  SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5235  }
5236  SiS_SetReg(SISCR, 0x7d, 0xfe);
5237  SiS_SetReg(SISCR, 0x7e, 0x0f);
5238  }
5239  if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5240  SiS_SetRegAND(SISCR, 0x58, 0xd7);
5241  reg = SiS_GetReg(SISCR, 0xcb);
5242  if(reg & 0x20) {
5243  SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5244  }
5245  }
5246 
5247  reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5248  SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5249 
5250  if(ivideo->chip == XGI_20) {
5251  SiS_SetReg(SISSR, 0x36, 0x70);
5252  } else {
5253  SiS_SetReg(SISVID, 0x00, 0x86);
5254  SiS_SetReg(SISVID, 0x32, 0x00);
5255  SiS_SetReg(SISVID, 0x30, 0x00);
5256  SiS_SetReg(SISVID, 0x32, 0x01);
5257  SiS_SetReg(SISVID, 0x30, 0x00);
5258  SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5259  SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5260 
5261  SiS_SetReg(SISPART1, 0x2f, 0x01);
5262  SiS_SetReg(SISPART1, 0x00, 0x00);
5263  SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5264  SiS_SetReg(SISPART1, 0x2e, 0x08);
5265  SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5266  SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5267 
5268  reg = SiS_GetReg(SISPART4, 0x00);
5269  if(reg == 1 || reg == 2) {
5270  SiS_SetReg(SISPART2, 0x00, 0x1c);
5271  SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5272  SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5273  SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5274  SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5275 
5276  reg = SiS_GetReg(SISPART4, 0x01);
5277  if((reg & 0xf0) >= 0xb0) {
5278  reg = SiS_GetReg(SISPART4, 0x23);
5279  if(reg & 0x20) reg |= 0x40;
5280  SiS_SetReg(SISPART4, 0x23, reg);
5281  reg = (reg & 0x20) ? 0x02 : 0x00;
5282  SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5283  }
5284  }
5285 
5286  v1 = bios[0x77];
5287 
5288  reg = SiS_GetReg(SISSR, 0x3b);
5289  if(reg & 0x02) {
5290  reg = SiS_GetReg(SISSR, 0x3a);
5291  v2 = (reg & 0x30) >> 3;
5292  if(!(v2 & 0x04)) v2 ^= 0x02;
5293  reg = SiS_GetReg(SISSR, 0x39);
5294  if(reg & 0x80) v2 |= 0x80;
5295  v2 |= 0x01;
5296 
5297  if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5298  pci_dev_put(mypdev);
5299  if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5300  v2 &= 0xf9;
5301  v2 |= 0x08;
5302  v1 &= 0xfe;
5303  } else {
5304  mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5305  if(!mypdev)
5306  mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5307  if(!mypdev)
5308  mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5309  if(mypdev) {
5310  pci_read_config_dword(mypdev, 0x94, &regd);
5311  regd &= 0xfffffeff;
5312  pci_write_config_dword(mypdev, 0x94, regd);
5313  v1 &= 0xfe;
5314  pci_dev_put(mypdev);
5315  } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5316  v1 &= 0xfe;
5317  } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5318  sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5319  sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5320  sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5321  if((v2 & 0x06) == 4)
5322  v2 ^= 0x06;
5323  v2 |= 0x08;
5324  }
5325  }
5326