1 /*
2 SIS chipset driver
3
4 Matan Ziv-Av <matan@svgalib.org>
5
6 Fixes for 530 and for vesafb by Marcelo de Paula Bezerra
7 <mosca@internetaddress.com>.
8
9
10 This driver is based on the XFree86 sis driver, written by
11
12 Alan Hourihane
13
14 and modified by
15 Xavier Ducoin,
16 Mike Chapman,
17 Juanjo Santamarta,
18 Mitani Hiroshi,
19 David Thomas.
20
21 And on the documentation availbale from sis's web pages (not many
22 chipset companies still do this).
23
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include "vga.h"
31 #include "libvga.h"
32 #include "driver.h"
33 #include "timing.h"
34 #include "vgaregs.h"
35 #include "interface.h"
36 #include "accel.h"
37 #include "vgapci.h"
38
39 #define SISREG_SAVE(i) (VGA_TOTAL_REGS+i)
40 #define SIS_TOTAL_REGS (VGA_TOTAL_REGS + 0x48 - 5)
41
42 #define XR(i) (VGA_TOTAL_REGS+i-5)
43
44 #define PCI_CHIP_SG86C201 0x0001
45 #define PCI_CHIP_SG86C202 0x0002
46 #define PCI_CHIP_SG86C205 0x0205
47 #define PCI_CHIP_SG86C215 0x0215
48 #define PCI_CHIP_SG86C225 0x0225
49 #define PCI_CHIP_SIS5598 0x0200
50 #define PCI_CHIP_SIS5597 0x0200
51 #define PCI_CHIP_SIS6326 0x6326
52 #define PCI_CHIP_SIS530 0x6306
53 #define PCI_CHIP_SIS300 0x0300
54 #define PCI_CHIP_SIS540 0x5300
55 #define PCI_CHIP_SIS630 0x6300
56
57 #define ClockReg XR(0x07)
58 #define DualBanks XR(0x0B)
59 #define BankReg XR(0x06)
60 #define CRTCOff XR(0x0A)
61 #define DispCRT XR(0x27)
62 #define Unknown XR(0x08)
63 #define LinearAddr0 XR(0x20)
64 #define LinearAddr1 XR(0x21)
65
66 enum { SIS_86C201=0, SIS_86C202, SIS_86C205, SIS_86C215, SIS_86C225,
67 SIS_5597, SIS_5598, SIS_6326, SIS_530 };
68
69 #define write_xr(num,val) {outb(SEQ_I, num);outb(SEQ_D, val);}
70 #define read_xr(num,var) {outb(SEQ_I, num);var=inb(SEQ_D);}
71
72 static int sis_init(int, int, int);
73 static void sis_unlock(void);
74 static void sis_lock(void);
75 static void sisClockLoad(int, unsigned char *);
76 static void sis_CPUthreshold(int,int,int *,int *);
77
78 void __svgalib_sisaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);
79
80 static int sis_memory;
81 static int sis_is_linear, sis_linear_base;
82 static int sis_chiptype;
83
84 static int sis_edo_vram = 0, sis_host_bus = 0, sis_fast_vram = 0,
85 sis_pci_burst_on = 0, sis_pci_burst_off = 0;
86
87 static CardSpecs *cardspecs;
88
sis_setpage(int page)89 static void sis_setpage(int page)
90 {
91 char tmp;
92
93 read_xr(0x0b,tmp);
94 if (tmp&8) {
95 outb(0x3cb,page);
96 outb(0x3cd,page);
97 } else
98 outb(0x3cd,page|(page<<4));
99 }
100
__svgalib_sis_inlinearmode(void)101 static int __svgalib_sis_inlinearmode(void)
102 {
103 return sis_is_linear;
104 }
105
106 /* Fill in chipset specific mode information */
107
sis_getmodeinfo(int mode,vga_modeinfo * modeinfo)108 static void sis_getmodeinfo(int mode, vga_modeinfo *modeinfo)
109 {
110
111 if(modeinfo->colors==16)return;
112
113 modeinfo->maxpixels = sis_memory*1024/modeinfo->bytesperpixel;
114 modeinfo->maxlogicalwidth = 4088;
115 modeinfo->startaddressrange = sis_memory * 1024 - 1;
116 modeinfo->haveblit = 0;
117 modeinfo->flags &= ~HAVE_RWPAGE;
118
119 if (modeinfo->bytesperpixel >= 1) {
120 if(sis_linear_base)modeinfo->flags |= CAPABLE_LINEAR;
121 if (__svgalib_sis_inlinearmode())
122 modeinfo->flags |= IS_LINEAR;
123 }
124 }
125
126 /* Read and save chipset-specific registers */
127
sis_saveregs(unsigned char regs[])128 static int sis_saveregs(unsigned char regs[])
129 {
130 int i;
131
132 sis_unlock();
133
134 regs[XR(0x40)] = inb(0x3cb);
135 regs[XR(0x41)] = inb(0x3cd);
136
137 if(sis_chiptype==SIS_5597)
138 for(i=0x38; i<0x3a;i++)read_xr(i,regs[XR(i)]);
139
140 if(sis_chiptype==SIS_6326)
141 for(i=0x38; i<0x3d;i++)read_xr(i,regs[XR(i)]);
142
143 if(sis_chiptype==SIS_530)
144 for(i=0x38; i<0x40 ; i++)read_xr(i,regs[XR(i)]);
145
146 /* get all the clocks */
147 if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
148 i = regs[XR(0x38)] & 0xfc;
149 write_xr(0x38,i|1);
150 read_xr(0x13,regs[XR(0x42)]);
151 read_xr(0x2a,regs[XR(0x43)]);
152 read_xr(0x2b,regs[XR(0x44)]);
153 write_xr(0x38,i|2);
154 read_xr(0x13,regs[XR(0x45)]);
155 read_xr(0x2a,regs[XR(0x46)]);
156 read_xr(0x2b,regs[XR(0x47)]);
157 write_xr(0x38,i); /* Make sure that the loop gets the internal VCLK registers */
158 }
159
160 for(i=5; i<0x38;i++)read_xr(i,regs[XR(i)]);
161
162 if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530)
163 write_xr(0x38,regs[XR(0x38)]);
164
165 return SIS_TOTAL_REGS - VGA_TOTAL_REGS;
166 }
167
168 /* Set chipset-specific registers */
169
sis_setregs(const unsigned char regs[],int mode)170 static void sis_setregs(const unsigned char regs[], int mode)
171 {
172 int i;
173
174 sis_unlock();
175
176 outb(0x3cb,regs[XR(0x40)]);
177 outb(0x3cd,regs[XR(0x41)]);
178
179 /* set all the clocks */
180 if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
181 i = regs[XR(0x38)] & 0xfc;
182 write_xr(0x38,i|1);
183 write_xr(0x13,regs[XR(0x42)]);
184 write_xr(0x2a,regs[XR(0x43)]);
185 write_xr(0x2b,regs[XR(0x44)]);
186 write_xr(0x38,i|2);
187 write_xr(0x13,regs[XR(0x45)]);
188 write_xr(0x2a,regs[XR(0x46)]);
189 write_xr(0x2b,regs[XR(0x47)]);
190 write_xr(0x38,i); /* Make sure that the loop puts the internal VCLK registers */
191 }
192
193 for(i=6; i<0x38;i++)write_xr(i,regs[XR(i)]);
194
195 if(sis_chiptype==SIS_5597)
196 for(i=0x38; i<0x3a;i++)write_xr(i,regs[XR(i)]);
197
198 if(sis_chiptype==SIS_6326)
199 for(i=0x38; i<0x3d;i++)write_xr(i,regs[XR(i)]);
200
201 if(sis_chiptype==SIS_530)
202 for(i=0x38; i<0x40;i++)write_xr(i,regs[XR(i)]);
203 }
204
205
206 /* Return nonzero if mode is available */
207
sis_modeavailable(int mode)208 static int sis_modeavailable(int mode)
209 {
210 struct info *info;
211 ModeTiming *modetiming;
212 ModeInfo *modeinfo;
213
214 if ((mode < G640x480x256 )
215 || mode == G720x348x2)
216 return __svgalib_vga_driverspecs.modeavailable(mode);
217
218 info = &__svgalib_infotable[mode];
219 if (sis_memory * 1024 < info->ydim * info->xbytes)
220 return 0;
221
222 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
223
224 if(modeinfo->bytesPerPixel==4){
225 free(modeinfo);
226 return 0;
227 };
228
229 modetiming = malloc(sizeof(ModeTiming));
230 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
231 free(modetiming);
232 free(modeinfo);
233 return 0;
234 }
235 free(modetiming);
236 free(modeinfo);
237
238 return SVGADRV;
239 }
240
241 /* Local, called by sis_setmode(). */
242
sis_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo,int mode)243 static void sis_initializemode(unsigned char *moderegs,
244 ModeTiming * modetiming, ModeInfo * modeinfo, int mode)
245 { /* long k; */
246 int offset;
247
248 __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
249
250 sis_saveregs(moderegs);
251
252 sisClockLoad(modetiming->pixelClock,moderegs);
253 offset = modetiming->CrtcHDisplay >>
254 ((modetiming->flags & INTERLACED) ? 2 : 3);
255
256 moderegs[ATT+16] = 0x01;
257 moderegs[20] = 0x40;
258 moderegs[23] = 0xA3;
259
260 moderegs[ATT+0x10] = 0x01; /* mode */
261 moderegs[ATT+0x11] = 0x00; /* overscan (border) color */
262 moderegs[ATT+0x12] = 0x0F; /* enable all color planes */
263 moderegs[ATT+0x13] = 0x00; /* horiz pixel panning 0 */
264
265 if ( (modeinfo->bitsPerPixel == 16) || (modeinfo->bitsPerPixel == 24) )
266 moderegs[GRA+0x05] = 0x00; /* normal read/write mode */
267
268 if (modeinfo->bitsPerPixel == 16) {
269 offset <<= 1; /* double the width of the buffer */
270 } else if (modeinfo->bitsPerPixel == 24) {
271 offset += offset << 1;
272 }
273
274 moderegs[BankReg] = 0x02;
275 moderegs[DualBanks] = 0x00;
276
277 if ( sis_is_linear ) {
278 moderegs[BankReg] |= 0x80; /* enable linear mode addressing */
279 moderegs[LinearAddr0] = (sis_linear_base & 0x07f80000) >> 19 ;
280 moderegs[LinearAddr1] = ((sis_linear_base & 0xf8000000) >> 27) |
281 (0x60) ; /* Enable Linear with max 4 mb*/
282 } else moderegs[DualBanks] |= 0x08;
283
284 if (modeinfo->bitsPerPixel == 16) {
285 if (modeinfo->greenWeight == 5)
286 moderegs[BankReg] |= 0x04; /* 16bpp = 5-5-5 */
287 else
288 moderegs[BankReg] |= 0x08; /* 16bpp = 5-6-5 */
289 }
290
291 if (modeinfo->bitsPerPixel == 24) {
292 moderegs[BankReg] |= 0x10;
293 moderegs[DualBanks] |= 0x80;
294 }
295
296 moderegs[0x13] = offset & 0xFF;
297 moderegs[CRTCOff] = ((offset & 0xF00) >> 4) |
298 (((modetiming->CrtcVTotal-2) & 0x400) >> 10 ) |
299 (((modetiming->CrtcVDisplay-1) & 0x400) >> 9 ) |
300 (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) |
301 (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ) ;
302
303 if (modetiming->flags & INTERLACED)
304 moderegs[BankReg] |= 0x20;
305
306 if ((sis_chiptype == SIS_5597) ||
307 (sis_chiptype == SIS_6326) ||
308 (sis_chiptype == SIS_530)) {
309 moderegs[XR(0x0C)] |= 0x20; /* readahead cache */
310 moderegs[XR(0x07)] |= 0x80; /* combine FIFOs */
311 }
312
313 if((sis_chiptype == SIS_530) || (sis_chiptype==SIS_5597)) {
314 moderegs[XR(0x0c)] |= 0x80; /* 32 bit memory access */
315 moderegs[XR(0x26)]&=0xfe; /* zero bit 20 of start address */
316 };
317
318 /* makes SR27 d[3:1]=0; If yes, I believe this is the offset for the
319 scroll, or somthing like that... */
320 moderegs[XR(0x27)]&=0xf0;
321
322 {
323 int CRT_ENGthreshold,CRT_CPUthresholdLow, CRT_CPUthresholdHigh;
324
325 CRT_ENGthreshold = 0x1F;
326 sis_CPUthreshold(modetiming->pixelClock, modeinfo->bitsPerPixel,
327 &CRT_CPUthresholdLow, &CRT_CPUthresholdHigh);
328 moderegs[XR(0x08)] = (CRT_ENGthreshold & 0x0F) |
329 (CRT_CPUthresholdLow & 0x0F)<<4 ;
330 moderegs[XR(0x09)] &= 0xF0; /* Yeou */
331 moderegs[XR(0x09)] |= (CRT_CPUthresholdHigh & 0x0F); /* Yeou */
332
333 if (sis_chiptype == SIS_530) {
334 /* CRT/CPU/Engine Threshold Bit[4] */
335 moderegs[XR(0x3F)] &= 0xE3;
336 moderegs[XR(0x3F)] |= ((CRT_CPUthresholdHigh & 0x10) |
337 ((CRT_ENGthreshold & 0x10) >> 1) |
338 ((CRT_CPUthresholdLow & 0x10) >> 2));
339 }
340 }
341
342 moderegs[59]=0x6f;
343
344 return ;
345 }
346
347
sis_setmode(int mode,int prv_mode)348 static int sis_setmode(int mode, int prv_mode)
349 {
350 unsigned char *moderegs;
351 ModeTiming *modetiming;
352 ModeInfo *modeinfo;
353 int tmp, var;
354
355 if ((mode < G640x480x256)||(mode==G720x348x2)) {
356 if(sis_chiptype >= SIS_5597) {
357 /* Work Around for vesafb case */
358 read_xr(0x06,tmp);
359 tmp&=~(0x1E); /* Depth registers */
360 write_xr(0x06,tmp);
361 /* program the 25 and 28 Mhz clocks */
362 if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
363 read_xr(0x38,tmp);
364 tmp &= 0xfc;
365 write_xr(0x38,tmp|1);
366 read_xr(0x13,var);
367 write_xr(0x13,var|0x40);
368 write_xr(0x2a,0x1b);
369 write_xr(0x2b,0xe1);
370 write_xr(0x38,tmp|2);
371 read_xr(0x13,var);
372 write_xr(0x13,var|0x40);
373 write_xr(0x2a,0x4e);
374 write_xr(0x2b,0xe4);
375 write_xr(0x38,tmp);
376 }
377 }
378
379 return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
380 }
381 if (!sis_modeavailable(mode))
382 return 1;
383
384 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
385
386 modetiming = malloc(sizeof(ModeTiming));
387 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
388 free(modetiming);
389 free(modeinfo);
390 return 1;
391 }
392
393 moderegs = malloc(SIS_TOTAL_REGS);
394
395 sis_initializemode(moderegs, modetiming, modeinfo, mode);
396
397
398 free(modetiming);
399
400 __svgalib_setregs(moderegs); /* Set standard regs. */
401 sis_setregs(moderegs, mode); /* Set extended regs. */
402 free(moderegs);
403
404 __svgalib_InitializeAcceleratorInterface(modeinfo);
405
406 free(modeinfo);
407 return 0;
408 }
409
410
411 /* Unlock chipset-specific registers */
412
sis_unlock(void)413 static void sis_unlock(void)
414 {
415 int vgaIOBase, temp;
416
417 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
418 outb(vgaIOBase + 4, 0x11);
419 temp = inb(vgaIOBase + 5);
420 outb(vgaIOBase + 5, temp & 0x7F);
421
422 outw(SEQ_I,0x8605);
423
424 }
425
sis_lock(void)426 static void sis_lock(void)
427 {
428 int vgaIOBase, temp;
429
430 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
431 outb(vgaIOBase + 4, 0x11);
432 temp = inb(vgaIOBase + 5);
433 outb(vgaIOBase + 5, temp & 0x7F);
434
435 outw(SEQ_I,0x0005);
436
437 }
438
439 #define VENDOR_ID 0x1039
440
441 /* Indentify chipset, initialize and return non-zero if detected */
442
sis_test(void)443 static int sis_test(void)
444 {
445 int _ioperm=0, found;
446 long buf[64];
447
448 if (getenv("IOPERM") == NULL) {
449 _ioperm=1;
450 if (iopl(3) < 0) {
451 printf("svgalib: cannot get I/O permissions\n");
452 exit(1);
453 }
454 }
455
456 found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
457
458 if (_ioperm) iopl(0);
459
460 if(!found&&(
461 (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C201)||
462 (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C202)||
463 (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C205)||
464 (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C215)||
465 (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C225)||
466 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5597)||
467 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5598)||
468 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS530)||
469 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS540)||
470 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS630)||
471 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS300)||
472 (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS6326)
473 )){
474 sis_init(0,0,0);
475 return 1;
476 };
477 return 0;
478 }
479
480
481 /* Set display start address (not for 16 color modes) */
482 /* Cirrus supports any address in video memory (up to 2Mb) */
483
sis_setdisplaystart(int address)484 static void sis_setdisplaystart(int address)
485 {
486 int temp;
487 address=address >> 2;
488 outw(CRT_IC, (address & 0x00FF00) | 0x0C);
489 outw(CRT_IC, ((address & 0x00FF) << 8) | 0x0D);
490
491 read_xr(0x27,temp);
492 temp &= 0xf0;
493 temp |= (address&0xf0000)>>16;
494 write_xr(0x27,temp);
495 }
496
497
498 /* Set logical scanline length (usually multiple of 8) */
499 /* Cirrus supports multiples of 8, up to 4088 */
500
sis_setlogicalwidth(int width)501 static void sis_setlogicalwidth(int width)
502 {
503 int offset = width >> 3;
504 int temp;
505
506 __svgalib_outCR(0x13,offset&0xff);
507 read_xr(0x0a,temp);
508 temp &= 0xf;
509 temp |= (offset&0xf00)>>4;
510 write_xr(0x0a,temp);
511 }
512
sis_linear(int op,int param)513 static int sis_linear(int op, int param)
514 {
515 if (op==LINEAR_ENABLE){
516 int temp;
517
518 sis_is_linear=1;
519 read_xr(6,temp);
520 temp |=0x80;
521 write_xr(0x20,(sis_linear_base & 0x07f80000) >> 19) ;
522 write_xr(0x21,((sis_linear_base & 0xf8000000) >> 27) |
523 (0x60)) ; /* Enable Linear with max 4 mb*/
524 write_xr(6,temp);
525 return 0;
526 };
527 if (op==LINEAR_DISABLE){
528 int temp;
529
530 sis_is_linear=0;
531 read_xr(6,temp);
532 temp &=0x7f;
533 write_xr(0x20,0) ;
534 write_xr(0x21,0) ;
535 write_xr(6,temp);
536 return 0;
537 };
538 if (op==LINEAR_QUERY_BASE) return sis_linear_base;
539 if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */
540 else return -1; /* Unknown function. */
541 }
542
sis_match_programmable_clock(int clock)543 static int sis_match_programmable_clock(int clock)
544 {
545 return clock ;
546 }
547
sis_map_clock(int bpp,int clock)548 static int sis_map_clock(int bpp, int clock)
549 {
550 return clock ;
551 }
552
sis_map_horizontal_crtc(int bpp,int pixelclock,int htiming)553 static int sis_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
554 {
555 return htiming;
556 }
557
558 /* Function table (exported) */
559
560 DriverSpecs __svgalib_sis_driverspecs =
561 {
562 sis_saveregs,
563 sis_setregs,
564 sis_unlock,
565 sis_lock,
566 sis_test,
567 sis_init,
568 sis_setpage,
569 NULL,
570 NULL,
571 sis_setmode,
572 sis_modeavailable,
573 sis_setdisplaystart,
574 sis_setlogicalwidth,
575 sis_getmodeinfo,
576 0, /* old blit funcs */
577 0,
578 0,
579 0,
580 0,
581 0, /* ext_set */
582 0, /* accel */
583 sis_linear,
584 0, /* accelspecs, filled in during init. */
585 NULL, /* Emulation */
586 };
587
588 /* Initialize chipset (called after detection) */
589
sis_init(int force,int par1,int par2)590 static int sis_init(int force, int par1, int par2)
591 {
592 unsigned long buf[64];
593 int found=0;
594 int _ioperm=0;
595
596 sis_unlock();
597 if (force) {
598 sis_memory = par1;
599 sis_chiptype = par2;
600 } else {
601
602 };
603
604 if (getenv("IOPERM") == NULL) {
605 _ioperm=1;
606 if (iopl(3) < 0) {
607 printf("svgalib: cannot get I/O permissions\n");
608 exit(1);
609 }
610 }
611 found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
612 if (_ioperm) iopl(0);
613 sis_linear_base=0;
614 sis_chiptype=0;
615 if (!found){
616 sis_linear_base=buf[4]&0xffffff00;
617 switch((buf[0]>>16)&0xffff) {
618 case PCI_CHIP_SG86C201: sis_chiptype=SIS_86C201; break;
619 case PCI_CHIP_SG86C202: sis_chiptype=SIS_86C202; break;
620 case PCI_CHIP_SG86C205: sis_chiptype=SIS_86C205; break;
621 case PCI_CHIP_SG86C215: sis_chiptype=SIS_86C215; break;
622 case PCI_CHIP_SG86C225: sis_chiptype=SIS_86C225; break;
623 case PCI_CHIP_SIS5597: sis_chiptype=SIS_5597; break;
624 case PCI_CHIP_SIS300:
625 case PCI_CHIP_SIS540:
626 case PCI_CHIP_SIS630:
627 case PCI_CHIP_SIS530: sis_chiptype=SIS_530; break;
628 /* case PCI_CHIP_SIS5598: sis_chiptype=SIS_5598; break;*/
629 case PCI_CHIP_SIS6326: sis_chiptype=SIS_6326; break;
630 };
631 };
632
633 if(sis_memory==0){
634 if ((sis_chiptype == SIS_6326)||(sis_chiptype==SIS_530)){
635 int temp;
636 read_xr(0x0C,temp);
637 temp >>= 1;
638 sis_memory=1024<<(temp&0x03);
639 };
640 if ( sis_chiptype == SIS_5597) {
641 int temp,bsiz;
642 /* Because 5597 shares main memory,
643 I test for BIOS CONFIGURED memory.*/
644
645 read_xr(0x0C,temp);
646 bsiz = (temp >> 1) & 3;
647
648 read_xr(0x2F,temp);
649 temp &= 7;
650 temp++;
651 if (bsiz > 0) temp = temp << 1;
652 sis_memory = 256 * temp;
653
654 };
655 if(sis_chiptype<SIS_5597) {
656 int temp;
657 read_xr(0x0F,temp);
658
659 sis_memory=1024<<(temp&0x03);
660 };
661 };
662 if (__svgalib_driver_report) {
663 printf("Using SIS driver, %iKB. Chiptype=%i\n",sis_memory,sis_chiptype);
664 };
665
666 cardspecs = malloc(sizeof(CardSpecs));
667 cardspecs->videoMemory = sis_memory;
668 cardspecs->maxPixelClock4bpp = 75000;
669 cardspecs->maxPixelClock8bpp = 135000;
670 cardspecs->maxPixelClock16bpp = 135000;
671 cardspecs->maxPixelClock24bpp = 135000;
672 cardspecs->maxPixelClock32bpp = 0;
673 cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE;
674 cardspecs->maxHorizontalCrtc = 2040;
675 cardspecs->maxPixelClock4bpp = 0;
676 cardspecs->nClocks =0;
677 cardspecs->mapClock = sis_map_clock;
678 cardspecs->mapHorizontalCrtc = sis_map_horizontal_crtc;
679 cardspecs->matchProgrammableClock=sis_match_programmable_clock;
680 __svgalib_driverspecs = &__svgalib_sis_driverspecs;
681 __svgalib_banked_mem_base=0xa0000;
682 __svgalib_banked_mem_size=0x10000;
683 __svgalib_linear_mem_base=sis_linear_base;
684 __svgalib_linear_mem_size=sis_memory*0x400;
685 return 0;
686 }
687
688 static void
sisCalcClock(int Clock,int max_VLD,unsigned int * vclk)689 sisCalcClock(int Clock, int max_VLD, unsigned int *vclk)
690 {
691 int M, N, P, PSN, VLD, PSNx;
692
693 int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0;
694 double bestError, abest = 42.0, bestFout;
695 double target;
696
697 double Fvco, Fout;
698 double error, aerror;
699
700 /*
701 * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler)
702 *
703 * M = Numerator [1:128]
704 * N = DeNumerator [1:32]
705 * VLD = Divider (Vco Loop Divider) : divide by 1, 2
706 * P = Post Scaler : divide by 1, 2, 3, 4
707 * PSN = Pre Scaler (Reference Divisor Select)
708 *
709 * result in vclk[]
710 */
711 #define Midx 0
712 #define Nidx 1
713 #define VLDidx 2
714 #define Pidx 3
715 #define PSNidx 4
716 #define Fref 14318180
717 /* stability constraints for internal VCO -- MAX_VCO also determines
718 * the maximum Video pixel clock */
719 #define MIN_VCO Fref
720 #define MAX_VCO 135000000
721 #define MAX_VCO_5597 353000000
722 #define MAX_PSN 0 /* no pre scaler for this chip */
723 #define TOLERANCE 0.01 /* search smallest M and N in this tolerance */
724
725 int M_min = 2;
726 int M_max = 128;
727
728 /* abest=10000.0; */
729
730 target = Clock * 1000;
731
732 if ((sis_chiptype == SIS_5597) || (sis_chiptype == SIS_6326)){
733 int low_N = 2;
734 int high_N = 5;
735 int PSN = 1;
736
737 P = 1;
738 if (target < MAX_VCO_5597 / 2)
739 P = 2;
740 if (target < MAX_VCO_5597 / 3)
741 P = 3;
742 if (target < MAX_VCO_5597 / 4)
743 P = 4;
744 if (target < MAX_VCO_5597 / 6)
745 P = 6;
746 if (target < MAX_VCO_5597 / 8)
747 P = 8;
748
749 Fvco = P * target;
750
751 for (N = low_N; N <= high_N; N++){
752 double M_desired = Fvco / Fref * N;
753 if (M_desired > M_max * max_VLD)
754 continue;
755
756 if ( M_desired > M_max ) {
757 M = M_desired / 2 + 0.5;
758 VLD = 2;
759 } else {
760 M = Fvco / Fref * N + 0.5;
761 VLD = 1;
762 };
763
764 Fout = (double)Fref * (M * VLD)/(N * P);
765
766 error = (target - Fout) / target;
767 aerror = (error < 0) ? -error : error;
768 /* if (aerror < abest && abest > TOLERANCE) {*/
769 if (aerror < abest) {
770 abest = aerror;
771 bestError = error;
772 bestM = M;
773 bestN = N;
774 bestP = P;
775 bestPSN = PSN;
776 bestVLD = VLD;
777 bestFout = Fout;
778 }
779 }
780 }
781 else {
782 for (PSNx = 0; PSNx <= MAX_PSN ; PSNx++) {
783 int low_N, high_N;
784 double FrefVLDPSN;
785
786 PSN = !PSNx ? 1 : 4;
787
788 low_N = 2;
789 high_N = 32;
790
791 for ( VLD = 1 ; VLD <= max_VLD ; VLD++ ) {
792
793 FrefVLDPSN = (double)Fref * VLD / PSN;
794 for (N = low_N; N <= high_N; N++) {
795 double tmp = FrefVLDPSN / N;
796
797 for (P = 1; P <= 4; P++) {
798 double Fvco_desired = target * ( P );
799 double M_desired = Fvco_desired / tmp;
800
801 /* Which way will M_desired be rounded?
802 * Do all three just to be safe.
803 */
804 int M_low = M_desired - 1;
805 int M_hi = M_desired + 1;
806
807 if (M_hi < M_min || M_low > M_max)
808 continue;
809
810 if (M_low < M_min)
811 M_low = M_min;
812 if (M_hi > M_max)
813 M_hi = M_max;
814
815 for (M = M_low; M <= M_hi; M++) {
816 Fvco = tmp * M;
817 if (Fvco <= MIN_VCO)
818 continue;
819 if (Fvco > MAX_VCO)
820 break;
821
822 Fout = Fvco / ( P );
823
824 error = (target - Fout) / target;
825 aerror = (error < 0) ? -error : error;
826 if (aerror < abest) {
827 abest = aerror;
828 bestError = error;
829 bestM = M;
830 bestN = N;
831 bestP = P;
832 bestPSN = PSN;
833 bestVLD = VLD;
834 bestFout = Fout;
835 }
836 }
837 }
838 }
839 }
840 }
841 }
842 vclk[Midx] = bestM;
843 vclk[Nidx] = bestN;
844 vclk[VLDidx] = bestVLD;
845 vclk[Pidx] = bestP;
846 vclk[PSNidx] = bestPSN;
847 };
848
849 static void
sisClockLoad(int Clock,unsigned char * regs)850 sisClockLoad(int Clock, unsigned char *regs)
851 {
852 unsigned int vclk[5];
853 unsigned char temp, xr2a, xr2b;
854
855 sisCalcClock(Clock, 2, vclk);
856
857 xr2a = (vclk[Midx] - 1) & 0x7f ;
858 xr2a |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ;
859 xr2b = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */
860 if (vclk[Pidx] <= 4){
861 xr2b |= (vclk[Pidx] -1 ) << 5 ; /* postscale 1,2,3,4 */
862 temp=regs[XR(0x13)];
863 temp &= 0xBF;
864 regs[XR(0x13)]=temp;
865 } else {
866 xr2b |= ((vclk[Pidx] / 2) -1 ) << 5 ; /* postscale 6,8 */
867
868 temp=regs[XR(0x13)];
869 temp |= 0x40;
870 regs[XR(0x13)]=temp;
871 };
872 xr2b |= 0x80 ; /* gain for high frequency */
873
874 regs[XR(0x2a)]=xr2a;
875 regs[XR(0x2b)]=xr2b;
876
877 if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326) {
878 temp=regs[XR(0x23)];
879 if (sis_edo_vram)
880 temp |= 0x40;
881 regs[XR(0x23)]=temp;
882 }
883
884 if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326 || sis_chiptype == SIS_530) {
885 /*write_xr(0x3B, 0x08 );*/
886 if (sis_chiptype == SIS_5597) {
887 temp=regs[XR(0x34)];
888 if (sis_host_bus)
889 temp |= 0x18;
890 else temp &= ~0x18;
891 regs[XR(0x34)]=temp;
892
893 temp=regs[XR(0x3D)];
894 if (sis_host_bus)
895 temp &= 0x0F;
896 regs[XR(0x3D)]=temp;
897 }
898
899 /* One-Cycle VRAM */
900 temp=regs[XR(0x34)];
901 if (sis_fast_vram)
902 regs[XR(0x34)]=temp;
903
904 /* pci burst */
905 temp=regs[XR(0x35)];
906 if (sis_pci_burst_on)
907 temp |= 0x10;
908 else if (sis_pci_burst_off)
909 temp &= ~0x10;
910 regs[XR(0x35)]=temp;
911
912 /* pci burst,also */
913 if (sis_chiptype != SIS_530) {
914 temp=regs[XR(0x26)];
915 if (sis_pci_burst_on)
916 temp |= 0x20;
917 else if (sis_pci_burst_off)
918 temp &= ~0x20;
919 regs[XR(0x26)]=temp;
920 }
921 /* Merge FIFOs */
922 temp=regs[XR(0x07)];
923 temp |= 0x80;
924 regs[XR(0x07)]=temp;
925 };
926
927 }
928
sisMClk(void)929 static int sisMClk(void)
930 { int mclk;
931 unsigned char xr28, xr29, xr13, xr10;
932
933 if (sis_chiptype == SIS_530) {
934 /* The MCLK in SiS530/620 is set by BIOS in SR10 */
935 read_xr(0x10, xr10);
936 switch(xr10 & 0x0f) {
937 case 1:
938 mclk = 75000; /* 75 Mhz */
939 break;
940 case 2:
941 mclk = 83000; /* 83 Mhz */
942 break;
943 case 3:
944 mclk = 100000;/* 100 Mhz */
945 break;
946 case 0:
947 default:
948 mclk = 66000; /* 66 Mhz */
949 }
950 return(mclk);
951 }
952 /* Numerator */
953 read_xr(0x28,xr28);
954 mclk=14318*((xr28 & 0x7f)+1);
955
956 /* Denumerator */
957 read_xr(0x29,xr29);
958 mclk=mclk/((xr29 & 0x1f)+1);
959
960 /* Divider. Does not seem to work for mclk for older cards */
961 if ( (sis_chiptype==SIS_6326) &&
962 ((xr28 & 0x80)!=0 ) ) {
963 mclk = mclk*2;
964 }
965 /* Post-scaler. Values depends on SR13 bit 7 */
966 read_xr(0x13,xr13);
967
968 if ( (xr13 & 0x80)==0 ) {
969 mclk = mclk / (((xr29 & 0x60) >> 5)+1);
970 }
971 else {
972 /* Values 00 and 01 are reserved */
973 if ((xr29 & 0x60) == 0x40) mclk=mclk/6;
974 if ((xr29 & 0x60) == 0x60) mclk=mclk/8;
975 }
976
977 return(mclk);
978 }
979
980 static void
sis_CPUthreshold(int dotClock,int bpp,int * thresholdLow,int * thresholdHigh)981 sis_CPUthreshold(int dotClock,int bpp,int *thresholdLow,int *thresholdHigh)
982 {
983 unsigned char temp;
984 int mclk;
985 int safetymargin, gap;
986 float z, z1, z2; /* Yeou */
987 int factor;
988
989 mclk=sisMClk();
990
991 if (sis_chiptype == SIS_530) /* Yeou for 530 thresholod */
992 {
993 /* z = f *((dotClock * bpp)/(buswidth*mclk);
994 thresholdLow = (z+1)/2 + 4;
995 thresholdHigh = 0x1F;
996
997 where f = 0x60 when UMA (SR0D D[0] = 1)
998 0x30 LFB (SR0D D[0] = 0)
999 */
1000 read_xr (0x0d, temp);
1001 if (temp & 0x01) factor = 0x60;
1002 else factor = 0x30;
1003
1004 z1 = (float)(dotClock * bpp);
1005 z2 = (float)(64.0 * mclk);
1006 z = ((float) factor * (z1 / z2));
1007 *thresholdLow = ((int)z + 1) / 2 + 4 ;
1008 *thresholdHigh = 0x1F;
1009 }
1010 else { /* For sis other product */
1011 /* Adjust thresholds. Safetymargin is to be adjusted by fifo_XXX
1012 options. Try to mantain a fifo margin of gap. At high Vclk*bpp
1013 this isn't possible, so limit the thresholds.
1014
1015 The values I guess are :
1016
1017 FIFO_CONSERVATIVE : safetymargin = 5 ;
1018 FIFO_MODERATE : safetymargin = 3 ;
1019 Default : safetymargin = 1 ; (good enough in many cases)
1020 FIFO_AGGRESSIVE : safetymargin = 0 ;
1021
1022 gap=4 seems to be the best value in either case...
1023 */
1024
1025 safetymargin=3;
1026
1027 gap = 4;
1028 *thresholdLow = ((bpp*dotClock) / mclk)+safetymargin;
1029 *thresholdHigh = ((bpp*dotClock) / mclk)+gap+safetymargin;
1030
1031 /* 24 bpp seems to need lower FIFO limits.
1032 At 16bpp is possible to put a thresholdHigh of 0 (0x10) with
1033 good results on my system(good performance, and virtually no noise) */
1034
1035 if ( *thresholdLow > (bpp < 24 ? 0xe:0x0d) ) {
1036 *thresholdLow = (bpp < 24 ? 0xe:0x0d);
1037 }
1038
1039 if ( *thresholdHigh > (bpp < 24 ? 0x10:0x0f) ) {
1040 *thresholdHigh = (bpp < 24 ? 0x10:0x0f);
1041 }
1042 }; /* sis530 */
1043 }
1044
1045