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