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