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