Importing vendor version xf86-4_3_99_903 on Wed Feb 26 01:21:00 PST 2004
[xf86-video-sis/mirage.git] / src / sis_dac.c
blobf428947e345c28ae171678bb96eda9f06681dd7e
1 /* $XFree86$ */
2 /*
3 * DAC helper functions (Save/Restore, MemClk, etc)
5 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3) All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: "This product includes
17 * software developed by Thomas Winischhofer, Vienna, Austria."
18 * 4) The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Author: Thomas Winischhofer <thomas@winischhofer.net>
34 * SiS_compute_vclk(), SiSCalcClock() and parts of SiSMclk():
35 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England
36 * Written by:
37 * Alan Hourihane <alanh@fairlite.demon.co.uk>,
38 * Mike Chapman <mike@paranoia.com>,
39 * Juanjo Santamarta <santamarta@ctv.es>,
40 * Mitani Hiroshi <hmitani@drl.mei.co.jp>,
41 * David Thomas <davtom@dream.org.uk>,
42 * Thomas Winischhofer <thomas@winischhofer.net>.
43 * Licensed under the terms of the XFree86 license
44 * (http://www.xfree86.org/current/LICENSE1.html)
48 #include "xf86.h"
49 #include "xf86_OSproc.h"
50 #include "xf86_ansic.h"
51 #include "xf86Version.h"
52 #include "xf86PciInfo.h"
53 #include "xf86Pci.h"
54 #include "xf86DDC.h"
56 #include "sis.h"
57 #include "sis_dac.h"
58 #include "sis_regs.h"
59 #include "sis_vb.h"
61 static void SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg);
62 static void SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
64 static void SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg);
65 static void SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg);
66 static void SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg);
67 static void SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg);
68 static void SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg);
69 static void SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
70 static void SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
71 static void SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
72 static void SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
73 static void SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg);
74 static void SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors,
75 int *indicies, LOCO *colors, VisualPtr pVisual);
76 static void SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr);
78 static const unsigned short ch700xidx[] = {
79 0x00,0x07,0x08,0x0a,0x0b,0x04,0x09,0x20,0x21,0x18,0x19,0x1a,
80 0x1b,0x1c,0x1d,0x1e,0x1f, /* 0x0e, - TW: Don't save the power register */
81 0x01,0x03,0x06,0x0d,0x11,0x13,0x14,0x15,0x17,0x22,0x23,0x24
84 static const unsigned short ch701xidx[] = {
85 0x1c,0x5f,0x64,0x6f,0x70,0x71,0x72,0x73,0x74,0x76,0x78,0x7d,
86 0x67,0x68,0x69,0x6a,0x6b,0x1e,0x00,0x01,0x02,0x04,0x03,0x05,
87 0x06,0x07,0x08,0x15,0x1f,0x0c,0x0d,0x0e,0x0f,0x10,0x66
88 };
90 int SiS_compute_vclk(
91 int Clock,
92 int *out_n,
93 int *out_dn,
94 int *out_div,
95 int *out_sbit,
96 int *out_scale)
98 float f,x,y,t, error, min_error;
99 int n, dn, best_n=0, best_dn=0;
102 * Rules
104 * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator)
105 * Factor = (Divider/Post Scalar)
106 * Divider is 1 or 2
107 * Post Scalar is 1, 2, 3, 4, 6 or 8
108 * Numberator ranged from 1 to 128
109 * DeNumerator ranged from 1 to 32
110 * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz
111 * b. Post Scalar selected from 1, 2, 4 or 8 first.
112 * c. DeNumerator selected from 2.
114 * According to rule a and b, the VCO ranges that can be scaled by
115 * rule b are:
116 * 150 - 250 (Factor = 1)
117 * 75 - 125 (Factor = 2)
118 * 37.5 - 62.5 (Factor = 4)
119 * 18.75 - 31.25 (Factor = 8)
121 * The following ranges use Post Scalar 3 or 6:
122 * 125 - 150 (Factor = 1.5)
123 * 62.5 - 75 (Factor = 3)
124 * 31.25 - 37.5 (Factor = 6)
126 * Steps:
127 * 1. divide the Clock by 2 until the Clock is less or equal to 31.25.
128 * 2. if the divided Clock is range from 18.25 to 31.25, than
129 * the Factor is 1, 2, 4 or 8.
130 * 3. if the divided Clock is range from 15.625 to 18.25, than
131 * the Factor is 1.5, 3 or 6.
132 * 4. select the Numberator and DeNumberator with minimum deviation.
134 * ** this function can select VCLK ranged from 18.75 to 250 Mhz
137 f = (float) Clock;
138 f /= 1000.0;
139 if((f > 250.0) || (f < 18.75))
140 return 0;
142 min_error = f;
143 y = 1.0;
144 x = f;
145 while(x > 31.25) {
146 y *= 2.0;
147 x /= 2.0;
149 if(x >= 18.25) {
150 x *= 8.0;
151 y = 8.0 / y;
152 } else if(x >= 15.625) {
153 x *= 12.0;
154 y = 12.0 / y;
157 t = y;
158 if(t == (float) 1.5) {
159 *out_div = 2;
160 t *= 2.0;
161 } else {
162 *out_div = 1;
164 if(t > (float) 4.0) {
165 *out_sbit = 1;
166 t /= 2.0;
167 } else {
168 *out_sbit = 0;
171 *out_scale = (int) t;
173 for(dn = 2; dn <= 32; dn++) {
174 for(n = 1; n <= 128; n++) {
175 error = x;
176 error -= ((float) 14.318 * (float) n / (float) dn);
177 if(error < (float) 0)
178 error = -error;
179 if(error < min_error) {
180 min_error = error;
181 best_n = n;
182 best_dn = dn;
186 *out_n = best_n;
187 *out_dn = best_dn;
188 PDEBUG(ErrorF("SiS_compute_vclk: Clock=%d, n=%d, dn=%d, div=%d, sbit=%d,"
189 " scale=%d\n", Clock, best_n, best_dn, *out_div,
190 *out_sbit, *out_scale));
191 return 1;
195 void
196 SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk)
198 SISPtr pSiS = SISPTR(pScrn);
199 int M, N, P , PSN, VLD , PSNx ;
200 int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0;
201 double abest = 42.0;
202 double target;
203 double Fvco, Fout;
204 double error, aerror;
205 #ifdef DEBUG
206 double bestFout;
207 #endif
210 * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler)
212 * M = Numerator [1:128]
213 * N = DeNumerator [1:32]
214 * VLD = Divider (Vco Loop Divider) : divide by 1, 2
215 * P = Post Scaler : divide by 1, 2, 3, 4
216 * PSN = Pre Scaler (Reference Divisor Select)
218 * result in vclk[]
220 #define Midx 0
221 #define Nidx 1
222 #define VLDidx 2
223 #define Pidx 3
224 #define PSNidx 4
225 #define Fref 14318180
226 /* stability constraints for internal VCO -- MAX_VCO also determines
227 * the maximum Video pixel clock */
228 #define MIN_VCO Fref
229 #define MAX_VCO 135000000
230 #define MAX_VCO_5597 353000000
231 #define MAX_PSN 0 /* no pre scaler for this chip */
232 #define TOLERANCE 0.01 /* search smallest M and N in this tolerance */
234 int M_min = 2;
235 int M_max = 128;
237 target = clock * 1000;
239 if(pSiS->Chipset == PCI_CHIP_SIS5597 || pSiS->Chipset == PCI_CHIP_SIS6326) {
241 int low_N = 2;
242 int high_N = 5;
244 PSN = 1;
245 P = 1;
246 if(target < MAX_VCO_5597 / 2) P = 2;
247 if(target < MAX_VCO_5597 / 3) P = 3;
248 if(target < MAX_VCO_5597 / 4) P = 4;
249 if(target < MAX_VCO_5597 / 6) P = 6;
250 if(target < MAX_VCO_5597 / 8) P = 8;
252 Fvco = P * target;
254 for(N = low_N; N <= high_N; N++) {
256 double M_desired = Fvco / Fref * N;
257 if(M_desired > M_max * max_VLD) continue;
259 if(M_desired > M_max) {
260 M = M_desired / 2 + 0.5;
261 VLD = 2;
262 } else {
263 M = Fvco / Fref * N + 0.5;
264 VLD = 1;
267 Fout = (double)Fref * (M * VLD)/(N * P);
269 error = (target - Fout) / target;
270 aerror = (error < 0) ? -error : error;
271 if(aerror < abest) {
272 abest = aerror;
273 bestM = M;
274 bestN = N;
275 bestP = P;
276 bestPSN = PSN;
277 bestVLD = VLD;
278 #ifdef DEBUG
279 bestFout = Fout;
280 #endif
284 } else {
286 for(PSNx = 0; PSNx <= MAX_PSN ; PSNx++) {
288 int low_N, high_N;
289 double FrefVLDPSN;
291 PSN = !PSNx ? 1 : 4;
293 low_N = 2;
294 high_N = 32;
296 for(VLD = 1 ; VLD <= max_VLD ; VLD++) {
298 FrefVLDPSN = (double)Fref * VLD / PSN;
300 for(N = low_N; N <= high_N; N++) {
301 double tmp = FrefVLDPSN / N;
303 for(P = 1; P <= 4; P++) {
304 double Fvco_desired = target * ( P );
305 double M_desired = Fvco_desired / tmp;
307 /* Which way will M_desired be rounded?
308 * Do all three just to be safe.
310 int M_low = M_desired - 1;
311 int M_hi = M_desired + 1;
313 if(M_hi < M_min || M_low > M_max) continue;
315 if(M_low < M_min) M_low = M_min;
317 if(M_hi > M_max) M_hi = M_max;
319 for(M = M_low; M <= M_hi; M++) {
320 Fvco = tmp * M;
321 if(Fvco <= MIN_VCO) continue;
322 if(Fvco > MAX_VCO) break;
324 Fout = Fvco / ( P );
326 error = (target - Fout) / target;
327 aerror = (error < 0) ? -error : error;
328 if(aerror < abest) {
329 abest = aerror;
330 bestM = M;
331 bestN = N;
332 bestP = P;
333 bestPSN = PSN;
334 bestVLD = VLD;
335 #ifdef DEBUG
336 bestFout = Fout;
337 #endif
339 #ifdef TWDEBUG
340 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3,
341 "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n",
342 (float)(clock / 1000.), M, N, P, VLD, PSN);
343 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3,
344 "Freq. set: %.2f MHz\n", Fout / 1.0e6);
345 #endif
353 vclk[Midx] = bestM;
354 vclk[Nidx] = bestN;
355 vclk[VLDidx] = bestVLD;
356 vclk[Pidx] = bestP;
357 vclk[PSNidx] = bestPSN;
359 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
360 "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n",
361 (float)(clock / 1000.), vclk[Midx], vclk[Nidx], vclk[VLDidx],
362 vclk[Pidx], vclk[PSNidx]));
363 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
364 "Freq. set: %.2f MHz\n", bestFout / 1.0e6));
365 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
366 "VCO Freq.: %.2f MHz\n", bestFout*bestP / 1.0e6));
370 static void
371 SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)
373 SISPtr pSiS = SISPTR(pScrn);
374 int i,max;
376 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
377 "SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
379 #ifdef UNLOCK_ALWAYS
380 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
381 #endif
383 switch(pSiS->Chipset) {
384 case PCI_CHIP_SIS5597:
385 max=0x3C;
386 break;
387 case PCI_CHIP_SIS6326:
388 case PCI_CHIP_SIS530:
389 max=0x3F;
390 break;
391 default:
392 max=0x37;
393 break;
396 /* Save extended SR registers */
397 for(i = 0x00; i <= max; i++) {
398 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]);
399 #ifdef TWDEBUG
400 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
401 "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]);
402 #endif
405 #ifdef TWDEBUG
406 for(i = 0x00; i <= 0x3f; i++) {
407 inSISIDXREG(SISCR, i, max);
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
409 "CR%02X - %02X \n", i,max);
411 #endif
413 /* Save lock (will not be restored in SiSRestore()!) */
414 inSISIDXREG(SISCR, 0x80, sisReg->sisRegs3D4[0x80]);
416 sisReg->sisRegs3C2 = inSISREG(SISMISCR); /* Misc */
418 /* TW: Save TV registers */
419 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) {
420 outSISIDXREG(SISCR, 0x80, 0x86);
421 for(i = 0x00; i <= 0x44; i++) {
422 sisReg->sis6326tv[i] = SiS6326GetTVReg(pScrn, i);
423 #ifdef TWDEBUG
424 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
425 "VR%02X - %02X \n", i,sisReg->sis6326tv[i]);
426 #endif
431 static void
432 SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
434 SISPtr pSiS = SISPTR(pScrn);
435 int i,max;
436 unsigned char tmp;
438 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
439 "SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
441 #ifdef UNLOCK_ALWAYS
442 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
443 #endif
445 switch(pSiS->Chipset) {
446 case PCI_CHIP_SIS5597:
447 max = 0x3C;
448 break;
449 case PCI_CHIP_SIS6326:
450 case PCI_CHIP_SIS530:
451 max = 0x3F;
452 break;
453 default:
454 max = 0x37;
455 break;
458 /* Disable TV on 6326 before restoring */
459 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) {
460 outSISIDXREG(SISCR, 0x80, 0x86);
461 tmp = SiS6326GetTVReg(pScrn, 0x00);
462 tmp &= ~0x04;
463 SiS6326SetTVReg(pScrn, 0x00, tmp);
466 /* Restore other extended SR registers */
467 for(i = 0x06; i <= max; i++) {
468 if((i == 0x13) || (i == 0x2a) || (i == 0x2b)) continue;
469 outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]);
472 /* Now restore VCLK (with correct SR38 setting) */
473 outSISIDXREG(SISSR, 0x13, sisReg->sisRegs3C4[0x13]);
474 outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]);
475 outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]);
477 /* Misc */
478 outSISREG(SISMISCW, sisReg->sisRegs3C2);
480 /* MemClock needs this to take effect */
481 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */
482 usleep(10000);
483 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */
485 /* TW: Restore TV registers */
486 pSiS->SiS6326Flags &= ~SIS6326_TVON;
487 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) {
488 for(i = 0x01; i <= 0x44; i++) {
489 SiS6326SetTVReg(pScrn, i, sisReg->sis6326tv[i]);
490 #ifdef TWDEBUG
491 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
492 "VR%02x restored to %02x\n",
493 i, sisReg->sis6326tv[i]);
494 #endif
496 tmp = SiS6326GetXXReg(pScrn, 0x13);
497 SiS6326SetXXReg(pScrn, 0x13, 0xfa);
498 tmp = SiS6326GetXXReg(pScrn, 0x14);
499 SiS6326SetXXReg(pScrn, 0x14, 0xc8);
500 if(!(sisReg->sisRegs3C4[0x0D] & 0x04)) {
501 tmp = SiS6326GetXXReg(pScrn, 0x13);
502 SiS6326SetXXReg(pScrn, 0x13, 0xf6);
503 tmp = SiS6326GetXXReg(pScrn, 0x14);
504 SiS6326SetXXReg(pScrn, 0x14, 0xbf);
506 if(sisReg->sis6326tv[0] & 0x04) pSiS->SiS6326Flags |= SIS6326_TVON;
510 /* Save SiS 300 series register contents */
511 static void
512 SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)
514 SISPtr pSiS = SISPTR(pScrn);
515 int i;
517 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
518 "SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
520 #ifdef UNLOCK_ALWAYS
521 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
522 #endif
524 /* Save SR registers */
525 for(i = 0x00; i <= 0x3D; i++) {
526 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]);
527 #ifdef TWDEBUG
528 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
529 "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]);
530 #endif
533 /* Save CR registers */
534 for(i = 0x00; i < 0x40; i++) {
535 inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]);
536 #ifdef TWDEBUG
537 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
538 "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]);
539 #endif
542 /* Save Misc register */
543 sisReg->sisRegs3C2 = inSISREG(SISMISCR);
545 /* Save FQBQ and GUI timer settings */
546 if(pSiS->Chipset == PCI_CHIP_SIS630) {
547 sisReg->sisRegsPCI50 = pciReadLong(0x00000000, 0x50);
548 sisReg->sisRegsPCIA0 = pciReadLong(0x00000000, 0xA0);
549 #ifdef TWDEBUG
550 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
551 "PCI Config 50 = %lx\n", sisReg->sisRegsPCI50);
552 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
553 "PCI Config A0 = %lx\n", sisReg->sisRegsPCIA0);
554 #endif
557 /* Save panel link/video bridge registers */
558 #ifndef TWDEBUG
559 if(!pSiS->UseVESA) {
560 #endif
561 if(pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL))
562 (*pSiS->SiSSaveLVDSChrontel)(pScrn, sisReg);
563 if(pSiS->VBFlags & VB_301)
564 (*pSiS->SiSSave2)(pScrn, sisReg);
565 if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV))
566 (*pSiS->SiSSave3)(pScrn, sisReg);
567 #ifndef TWDEBUG
569 #endif
571 /* Save Mode number */
572 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
573 if(!(pSiS->UseVESA))
574 #endif
575 pSiS->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF);
577 #ifdef TWDEBUG
578 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
579 "BIOS mode ds:449 = 0x%x\n", pSiS->BIOSModeSave);
580 #endif
584 /* Restore SiS300 series register contents */
585 static void
586 SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
588 SISPtr pSiS = SISPTR(pScrn);
589 int i,temp;
590 CARD32 temp1;
592 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
593 "SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
595 #ifdef UNLOCK_ALWAYS
596 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
597 #endif
599 /* Wait for accelerator to finish on-going drawing operations. */
600 inSISIDXREG(SISSR, 0x1E, temp);
601 if(temp & (0x40|0x10|0x02)) {
602 while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){};
603 while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){};
604 while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){};
607 if(!(pSiS->UseVESA)) {
608 if(pSiS->VBFlags & VB_LVDS) {
609 SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
610 SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
614 /* Restore extended CR registers */
615 for(i = 0x19; i < 0x40; i++) {
616 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]);
619 if(pSiS->Chipset != PCI_CHIP_SIS300) {
620 unsigned char val;
621 inSISIDXREG(SISCR, 0x1A, val);
622 if(val == sisReg->sisRegs3D4[0x19])
623 outSISIDXREG(SISCR, 0x1A, sisReg->sisRegs3D4[0x19]);
624 inSISIDXREG(SISCR,0x19,val);
625 if(val == sisReg->sisRegs3D4[0x1A])
626 outSISIDXREG(SISCR, 0x19, sisReg->sisRegs3D4[0x1A]);
629 /* Set (and leave) PCI_IO_ENABLE on if accelerators are on */
630 if(sisReg->sisRegs3C4[0x1e] & 0x50) {
631 sisReg->sisRegs3C4[0x20] |= 0x20;
632 outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]);
635 /* If TQ is switched on, don't switch it off ever again!
636 * Therefore, always restore registers with TQ enabled.
638 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) {
639 temp = (pScrn->videoRam/64) - 8;
640 sisReg->sisRegs3C4[0x26] = temp & 0xFF;
641 sisReg->sisRegs3C4[0x27] = ((temp >> 8) & 3) | 0xF0;
644 /* Restore extended SR registers */
645 for(i = 0x06; i <= 0x3D; i++) {
646 temp = sisReg->sisRegs3C4[i];
647 if(!(pSiS->UseVESA)) {
648 if(pSiS->VBFlags & VB_LVDS) {
649 if(i == 0x11) {
650 inSISIDXREG(SISSR,0x11,temp);
651 temp &= 0x0c;
652 temp |= (sisReg->sisRegs3C4[i] & 0xf3);
656 outSISIDXREG(SISSR, i, temp);
659 /* Restore VCLK and ECLK */
660 if(pSiS->VBFlags & (VB_LVDS | VB_301B | VB_301C)) {
661 outSISIDXREG(SISSR,0x31,0x20);
662 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
663 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
664 outSISIDXREG(SISSR,0x2d,0x80);
665 outSISIDXREG(SISSR,0x31,0x10);
666 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
667 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
668 outSISIDXREG(SISSR,0x2d,0x80);
670 outSISIDXREG(SISSR,0x31,0x00);
671 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
672 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
673 outSISIDXREG(SISSR,0x2d,0x80);
674 if(pSiS->VBFlags & (VB_LVDS | VB_301B | VB_301C)) {
675 outSISIDXREG(SISSR,0x31,0x20);
676 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
677 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
678 outSISIDXREG(SISSR,0x31,0x10);
679 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
680 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
681 outSISIDXREG(SISSR,0x31,0x00);
682 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
683 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
686 /* Restore Misc register */
687 outSISREG(SISMISCW, sisReg->sisRegs3C2);
689 /* Restore FQBQ and GUI timer settings */
690 if(pSiS->Chipset == PCI_CHIP_SIS630) {
691 temp1 = pciReadLong(0x00000000, 0x50);
692 if(pciReadLong(0x00000000, 0x00) == 0x06301039) {
693 temp1 &= 0xf0ffffff;
694 temp1 |= (sisReg->sisRegsPCI50 & ~0xf0ffffff);
695 } else { /* 730 */
696 temp1 &= 0xfffff9ff;
697 temp1 |= (sisReg->sisRegsPCI50 & ~0xfffff9ff);
699 pciWriteLong(0x00000000, 0x50, temp1);
701 temp1 = pciReadLong(0x00000000, 0xA0);
702 if(pciReadLong(0x00000000, 0x00) == 0x06301039) {
703 temp1 &= 0xf0ffffff;
704 temp1 |= (sisReg->sisRegsPCIA0 & ~0xf0ffffff);
705 } else { /* 730 */
706 temp1 &= 0x00ffffff;
707 temp1 |= (sisReg->sisRegsPCIA0 & ~0x00ffffff);
709 pciWriteLong(0x00000000, 0xA0, temp1);
712 /* Restore panel link/video bridge registers */
713 if(!(pSiS->UseVESA)) {
714 if(pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL))
715 (*pSiS->SiSRestoreLVDSChrontel)(pScrn, sisReg);
716 if(pSiS->VBFlags & VB_301)
717 (*pSiS->SiSRestore2)(pScrn, sisReg);
718 if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV))
719 (*pSiS->SiSRestore3)(pScrn, sisReg);
722 /* MemClock needs this to take effect */
723 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */
724 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */
726 /* Restore mode number */
727 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
728 if(!(pSiS->UseVESA))
729 #endif
730 SiS_GetSetModeID(pScrn,pSiS->BIOSModeSave);
733 /* Save SiS315 series register contents */
734 static void
735 SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)
737 SISPtr pSiS = SISPTR(pScrn);
738 int i;
740 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
741 "SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
743 #ifdef UNLOCK_ALWAYS
744 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
745 #endif
747 /* Save SR registers */
748 for(i = 0x00; i <= 0x3F; i++) {
749 inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]);
750 #ifdef TWDEBUG
751 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
752 "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]);
753 #endif
756 /* Save command queue location */
757 sisReg->sisMMIO85C0 = MMIO_IN32(pSiS->IOBase, 0x85C0);
759 /* Save CR registers */
760 for(i = 0x00; i <= 0x7a; i++) {
761 inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]);
762 #ifdef TWDEBUG
763 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
764 "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]);
765 #endif
768 /* Save video capture registers */
769 for(i = 0x00; i <= 0x4f; i++) {
770 inSISIDXREG(SISCAP, i, sisReg->sisCapt[i]);
771 #ifdef TWDEBUG
772 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
773 "Capt%02X Contents - %02X \n", i,sisReg->sisCapt[i]);
774 #endif
777 /* Save video playback registers */
778 for(i = 0x00; i <= 0x3f; i++) {
779 inSISIDXREG(SISVID, i, sisReg->sisVid[i]);
780 #ifdef TWDEBUG
781 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
782 "Vid%02X Contents - %02X \n", i,sisReg->sisVid[i]);
783 #endif
786 /* Save Misc register */
787 sisReg->sisRegs3C2 = inSISREG(SISMISCR);
789 /* Save panel link/video bridge registers */
790 #ifndef TWDEBUG
791 if(!pSiS->UseVESA) {
792 #endif
793 if(pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL))
794 (*pSiS->SiSSaveLVDSChrontel)(pScrn, sisReg);
795 if(pSiS->VBFlags & VB_301)
796 (*pSiS->SiSSave2)(pScrn, sisReg);
797 if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV))
798 (*pSiS->SiSSave3)(pScrn, sisReg);
799 #ifndef TWDEBUG
801 #endif
803 /* Save mode number */
804 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
805 if(!(pSiS->UseVESA))
806 #endif
807 pSiS->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF);
809 #ifdef TWDEBUG
810 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
811 "BIOS mode ds:449 = 0x%x\n", pSiS->BIOSModeSave);
812 #endif
815 /* Restore SiS315/330 series register contents */
816 static void
817 SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
819 SISPtr pSiS = SISPTR(pScrn);
820 int i,temp;
822 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
823 "SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
825 #ifdef UNLOCK_ALWAYS
826 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
827 #endif
829 /* Wait for accelerator to finish on-going drawing operations. */
830 inSISIDXREG(SISSR, 0x1E, temp);
831 if(temp & (0x40|0x10|0x02)) { /* 0x40 = 2D, 0x10 = 3D enabled*/
832 while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){};
833 while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){};
834 while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){};
837 /* We reset the command queue before restoring.
838 * This might be required because we never know what
839 * console driver (like the kernel framebuffer driver)
840 * or application is running and which queue mode it
841 * uses.
843 outSISIDXREG(SISSR, 0x27, 0x1F);
844 outSISIDXREG(SISSR, 0x26, 0x01);
846 /* Restore extended CR registers */
847 for(i = 0x19; i < 0x5C; i++) {
848 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]);
850 if(pSiS->sishw_ext.jChipType < SIS_661) {
851 outSISIDXREG(SISCR, 0x79, sisReg->sisRegs3D4[0x79]);
853 outSISIDXREG(SISCR, pSiS->myCR63, sisReg->sisRegs3D4[pSiS->myCR63]);
855 /* Leave PCI_IO_ENABLE on if accelerators are on (Is this required?) */
856 if(sisReg->sisRegs3C4[0x1e] & 0x50) { /*0x40=2D, 0x10=3D*/
857 sisReg->sisRegs3C4[0x20] |= 0x20;
858 outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]);
861 /* Restore extended SR registers */
862 if(pSiS->sishw_ext.jChipType >= SIS_661) {
863 sisReg->sisRegs3C4[0x11] &= 0x0f;
865 for(i = 0x06; i <= 0x3F; i++) {
866 outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]);
868 /* Restore VCLK and ECLK */
869 andSISIDXREG(SISSR,0x31,0xcf);
870 if(pSiS->VBFlags & VB_LVDS) {
871 orSISIDXREG(SISSR,0x31,0x20);
872 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
873 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
874 outSISIDXREG(SISSR,0x2d,0x80);
875 andSISIDXREG(SISSR,0x31,0xcf);
876 orSISIDXREG(SISSR,0x31,0x10);
877 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
878 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
879 outSISIDXREG(SISSR,0x2d,0x80);
880 andSISIDXREG(SISSR,0x31,0xcf);
881 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
882 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
883 outSISIDXREG(SISSR,0x2d,0x01);
884 outSISIDXREG(SISSR,0x31,0x20);
885 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
886 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
887 outSISIDXREG(SISSR,0x31,0x10);
888 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
889 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
890 outSISIDXREG(SISSR,0x31,0x00);
891 outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]);
892 outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]);
893 } else {
894 outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]);
895 outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]);
896 outSISIDXREG(SISSR,0x2d,0x01);
899 #ifndef SISVRAMQ
900 /* Initialize read/write pointer for command queue */
901 MMIO_OUT32(pSiS->IOBase, 0x85C4, MMIO_IN32(pSiS->IOBase, 0x85C8));
902 #endif
903 /* Restore queue location */
904 MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0);
906 /* Restore Misc register */
907 outSISREG(SISMISCW, sisReg->sisRegs3C2);
909 /* Restore panel link/video bridge registers */
910 if(!(pSiS->UseVESA)) {
911 if(pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL))
912 (*pSiS->SiSRestoreLVDSChrontel)(pScrn, sisReg);
913 if(pSiS->VBFlags & VB_301)
914 (*pSiS->SiSRestore2)(pScrn, sisReg);
915 if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV))
916 (*pSiS->SiSRestore3)(pScrn, sisReg);
919 /* MemClock needs this to take effect */
920 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */
921 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */
923 /* Restore Mode number */
924 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
925 if(!(pSiS->UseVESA))
926 #endif
927 SiS_GetSetModeID(pScrn,pSiS->BIOSModeSave);
930 static void
931 SiSVBSave(ScrnInfoPtr pScrn, SISRegPtr sisReg, int p1, int p2, int p3, int p4)
933 SISPtr pSiS = SISPTR(pScrn);
934 int i;
936 for(i=0; i<=p1; i++) {
937 inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]);
938 #ifdef TWDEBUG
939 xf86DrvMsg(0, X_INFO, "301xSave: Part1Port 0x%02x = 0x%02x\n", i, sisReg->VBPart1[i]);
940 #endif
942 for(i=0; i<=p2; i++) {
943 inSISIDXREG(SISPART2, i, sisReg->VBPart2[i]);
944 #ifdef TWDEBUG
945 xf86DrvMsg(0, X_INFO, "301xSave: Part2Port 0x%02x = 0x%02x\n", i, sisReg->VBPart2[i]);
946 #endif
948 for(i=0; i<=p3; i++) {
949 inSISIDXREG(SISPART3, i, sisReg->VBPart3[i]);
950 #ifdef TWDEBUG
951 xf86DrvMsg(0, X_INFO, "301xSave: Part3Port 0x%02x = 0x%02x\n", i, sisReg->VBPart3[i]);
952 #endif
954 for(i=0; i<=p4; i++) {
955 inSISIDXREG(SISPART4, i, sisReg->VBPart4[i]);
956 #ifdef TWDEBUG
957 xf86DrvMsg(0, X_INFO, "301xSave: Part4Port 0x%02x = 0x%02x\n", i, sisReg->VBPart4[i]);
958 #endif
962 /* Save SiS301 bridge register contents */
963 static void
964 SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)
966 SISPtr pSiS = SISPTR(pScrn);
967 int Part1max, Part2max, Part3max, Part4max;
969 /* Highest register number to save/restore */
970 if(pSiS->VGAEngine == SIS_300_VGA) Part1max = 0x1d;
971 else Part1max = 0x2e; /* 0x23, but we also need 2d-2e */
973 Part2max = 0x45;
974 Part3max = 0x3e;
975 Part4max = 0x1b;
977 SiSVBSave(pScrn, sisReg, Part1max, Part2max, Part3max, Part4max);
979 sisReg->VBPart2[0x00] &= ~0x20; /* Disable VB Processor */
980 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */
983 /* Restore SiS301 bridge register contents */
984 static void
985 SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
987 SISPtr pSiS = SISPTR(pScrn);
988 int Part1max, Part2max, Part3max, Part4max;
990 /* Highest register number to save/restore */
991 if(pSiS->VGAEngine == SIS_300_VGA) Part1max = 0x1d;
992 else Part1max = 0x23;
994 Part2max = 0x45;
995 Part3max = 0x3e;
996 Part4max = 0x1b;
998 SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1000 SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1002 /* Pre-restore Part1 */
1003 outSISIDXREG(SISPART1, 0x04, 0x00);
1004 outSISIDXREG(SISPART1, 0x05, 0x00);
1005 outSISIDXREG(SISPART1, 0x06, 0x00);
1006 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]);
1007 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]);
1009 /* Pre-restore Part4 */
1010 outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]);
1011 outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]);
1013 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) &&
1014 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */
1015 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1016 return;
1019 /* Restore Part1 */
1020 SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02]));
1021 if(pSiS->VGAEngine == SIS_315_VGA) {
1022 /* Restore extra registers on 315 series */
1023 SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C]));
1026 /* Restore Part2 */
1027 SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00]));
1029 /* Restore Part3 */
1030 SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00]));
1032 /* Restore Part4 */
1033 SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E]));
1034 SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13]));
1036 /* Post-restore Part4 (CRT2VCLK) */
1037 outSISIDXREG(SISPART4, 0x0A, 0x01);
1038 outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]);
1039 outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]);
1040 outSISIDXREG(SISPART4, 0x12, 0x00);
1041 outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]);
1043 SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1044 SiS_DisplayOn(pSiS->SiS_Pr);
1045 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1048 /* Save SiS30xB/30xLV bridge register contents */
1049 static void
1050 SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)
1052 SISPtr pSiS = SISPTR(pScrn);
1053 int Part1max, Part2max, Part3max, Part4max;
1055 Part1max = 0x4c;
1056 Part2max = 0x4d;
1057 Part3max = 0x3e;
1058 Part4max = 0x23;
1059 if(pSiS->VBFlags & (VB_301C|VB_302ELV)) {
1060 Part2max = 0xff;
1061 Part4max = 0x3c;
1063 if(pSiS->VBFlags & (VB_301LV|VB_302LV)) {
1064 Part4max = 0x34;
1067 SiSVBSave(pScrn, sisReg, Part1max, Part2max, Part3max, Part4max);
1069 sisReg->VBPart2[0x00] &= ~0x20; /* Disable VB Processor */
1070 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */
1073 /* Restore SiS30xB/30xLV bridge register contents */
1074 static void
1075 SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
1077 SISPtr pSiS = SISPTR(pScrn);
1078 int Part1max, Part2max, Part3max, Part4max;
1080 Part1max = 0x23;
1081 Part2max = 0x4d;
1082 Part3max = 0x3e;
1083 Part4max = 0x22;
1084 if(pSiS->VBFlags & (VB_301C|VB_302ELV)) {
1085 Part2max = 0xff;
1086 Part4max = 0x3c;
1088 if(pSiS->VBFlags & (VB_301LV|VB_302LV)) {
1089 Part4max = 0x34;
1092 SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1094 SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1096 /* Pre-restore Part1 */
1097 outSISIDXREG(SISPART1, 0x04, 0x00);
1098 outSISIDXREG(SISPART1, 0x05, 0x00);
1099 outSISIDXREG(SISPART1, 0x06, 0x00);
1100 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0x00]);
1101 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[0x01]);
1102 /* Mode reg 0x01 became 0x2e on 315 series (0x01 still contains FIFO) */
1103 if(pSiS->VGAEngine == SIS_315_VGA) {
1104 outSISIDXREG(SISPART1, 0x2e, sisReg->VBPart1[0x2e]);
1107 /* Pre-restore Part4 */
1108 outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]);
1109 outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]);
1111 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) &&
1112 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */
1113 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1114 return;
1117 /* Restore Part1 */
1118 SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02]));
1119 if(pSiS->VGAEngine == SIS_315_VGA) {
1120 SetBlock(SISPART1, 0x2C, 0x2D, &(sisReg->VBPart1[0x2C]));
1121 SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35]));
1124 /* Restore Part2 */
1125 SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00]));
1127 /* Restore Part3 */
1128 SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00]));
1130 /* Restore Part4 */
1131 SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E]));
1132 SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13]));
1134 /* Post-restore Part4 (CRT2VCLK) */
1135 outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]);
1136 outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]);
1137 outSISIDXREG(SISPART4, 0x12, 0x00);
1138 outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]);
1140 SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1141 SiS_DisplayOn(pSiS->SiS_Pr);
1142 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1145 /* Save LVDS bridge (+ Chrontel) register contents */
1146 static void
1147 SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)
1149 SISPtr pSiS = SISPTR(pScrn);
1150 int i;
1152 /* Save Part1 */
1153 for(i=0; i<0x46; i++) {
1154 inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]);
1155 #ifdef TWDEBUG
1156 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1157 "LVDSSave: Part1Port 0x%02x = 0x%02x\n",
1158 i, sisReg->VBPart1[i]);
1159 #endif
1162 /* Save Chrontel registers */
1163 if(pSiS->VBFlags & VB_CHRONTEL) {
1164 if(pSiS->ChrontelType == CHRONTEL_700x) {
1165 for(i=0; i<0x1D; i++) {
1166 sisReg->ch70xx[i] = SiS_GetCH700x(pSiS->SiS_Pr, ch700xidx[i]);
1167 #ifdef TWDEBUG
1168 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1169 "LVDSSave: Chrontel 0x%02x = 0x%02x\n",
1170 ch700xidx[i], sisReg->ch70xx[i]);
1171 #endif
1173 } else {
1174 for(i=0; i<35; i++) {
1175 sisReg->ch70xx[i] = SiS_GetCH701x(pSiS->SiS_Pr, ch701xidx[i]);
1176 #ifdef TWDEBUG
1177 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1178 "LVDSSave: Chrontel 0x%02x = 0x%02x\n",
1179 ch701xidx[i], sisReg->ch70xx[i]);
1180 #endif
1185 sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */
1188 /* Restore LVDS bridge (+ Chrontel) register contents */
1189 static void
1190 SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)
1192 SISPtr pSiS = SISPTR(pScrn);
1193 int i;
1194 USHORT wtemp;
1196 SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1197 if(pSiS->sishw_ext.jChipType == SIS_730) {
1198 outSISIDXREG(SISPART1, 0x00, 0x80);
1201 SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1203 if(pSiS->VBFlags & VB_CHRONTEL) {
1204 /* Restore Chrontel registers */
1205 if(pSiS->ChrontelType == CHRONTEL_700x) {
1206 for(i=0; i<0x11; i++) {
1207 wtemp = ((sisReg->ch70xx[i]) << 8) | (ch700xidx[i] & 0x00FF);
1208 SiS_SetCH700x(pSiS->SiS_Pr, wtemp);
1210 } else {
1211 for(i=0; i<34; i++) {
1212 wtemp = ((sisReg->ch70xx[i]) << 8) | (ch701xidx[i] & 0x00FF);
1213 SiS_SetCH701x(pSiS->SiS_Pr, wtemp);
1218 /* pre-restore Part1 */
1219 outSISIDXREG(SISPART1, 0x04, 0x00);
1220 outSISIDXREG(SISPART1, 0x05, 0x00);
1221 outSISIDXREG(SISPART1, 0x06, 0x00);
1222 outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]);
1223 if(pSiS->VGAEngine == SIS_300_VGA) {
1224 outSISIDXREG(SISPART1, 0x01, (sisReg->VBPart1[1] | 0x80));
1225 } else {
1226 outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]);
1229 if((!(sisReg->sisRegs3D4[0x30] & 0x03)) &&
1230 (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */
1231 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1232 return;
1235 /* Restore Part1 */
1236 if(pSiS->VGAEngine == SIS_300_VGA) {
1237 outSISIDXREG(SISPART1, 0x02, (sisReg->VBPart1[2] | 0x40));
1238 } else {
1239 outSISIDXREG(SISPART1, 0x02, sisReg->VBPart1[2]);
1241 SetBlock(SISPART1, 0x03, 0x23, &(sisReg->VBPart1[0x03]));
1242 if(pSiS->VGAEngine == SIS_315_VGA) {
1243 SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C]));
1244 SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35])); /* Panel Link Scaler */
1247 /* For 550 DSTN registers */
1248 if(pSiS->DSTN || pSiS->FSTN) {
1249 SetBlock(SISPART1, 0x25, 0x2E, &(sisReg->VBPart1[0x25]));
1250 SetBlock(SISPART1, 0x30, 0x45, &(sisReg->VBPart1[0x30]));
1253 SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext);
1254 SiS_DisplayOn(pSiS->SiS_Pr);
1255 SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext);
1258 /* Restore output selection registers */
1259 void
1260 SiSRestoreBridge(ScrnInfoPtr pScrn, SISRegPtr sisReg)
1262 SISPtr pSiS = SISPTR(pScrn);
1263 int i;
1265 #ifdef UNLOCK_ALWAYS
1266 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
1267 #endif
1269 for(i = 0x30; i <= 0x3b; i++) {
1270 if(i == 0x34) continue;
1271 outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]);
1274 if(pSiS->VGAEngine == SIS_315_VGA) {
1275 outSISIDXREG(SISCR, pSiS->myCR63, sisReg->sisRegs3D4[pSiS->myCR63]);
1276 if(pSiS->sishw_ext.jChipType < SIS_661) {
1277 outSISIDXREG(SISCR, 0x79, sisReg->sisRegs3D4[0x79]);
1282 #if 0 /* The following function should take a threshold value
1283 * from predefined tables. This is only needed on some
1284 * 530 boards, which have an ESS sound device on-board.
1285 * However, I don't know how to calculate the index to
1286 * be submitted to this function.
1288 unsigned short
1289 SiS_CalcSpecial530Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, int index)
1291 SISPtr pSiS = SISPTR(pScrn);
1292 static const unsigned char t640x480[3][24] = {
1293 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,A9, /* b4 - 9d - depth 8 */
1294 0, 0,11,14,14, 0, 0, 0, 0, 0, 0,9D },
1295 { 0, 0, 0, 0, 0,12,15, 0, 0, 0,92,91, /* 9c - 85 - depth 16 */
1296 0,31,31,31,31, 0, 0, 0, 0, 0, 0,85 },
1297 { 0, 0, 0, 0, 0,17,22,25, 0, 0, 0,79, /* 84 - ? - depth 32 */
1298 0,31,31, 0, 0, 0, 0, 0, 0, 0, 0,6d }
1300 static const unsigned char t800x600[3][24] = {
1301 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,61,
1302 0,18,25,30,27,31,31,31, 0, 0, 0, 0 },
1303 {55, 0, 0, 0, 0, 9,10,15,18,19, 0, 0,
1304 ... to be continued
1306 depthindex = (pSiS->CurrentLayout.bitsPerPixel + 1) >> 3;
1307 if(depthindex == 3) return(0);
1308 if(depthindex == 4) depthindex--;
1309 depthindex--;
1311 switch(mode->HDisplay) {
1312 case 640:
1313 if(mode->VDisplay == 480) {
1314 return(t640x480[depthindex][index];
1315 } else return(0);
1316 case 800:
1317 if(mode->VDisplay == 600) {
1318 return(t800x600[depthindex][index];
1319 } else return(0);
1320 case 1024:
1321 if(mode->VDisplay == 768) {
1322 return(t1024x768[depthindex][index];
1323 } else return(0);
1324 case 1280:
1325 if(mode->VDisplay == 1024) {
1326 return(t1280x1024[depthindex][index];
1327 } else return(0);
1328 case 1600:
1329 if(mode->VDisplay == 1200) {
1330 return(t1600x1200[depthindex][index];
1331 } else return(0);
1332 default: return(0);
1335 #endif
1337 /* Auxiliary function to find real memory clock (in Khz) */
1338 /* Not for 530/620 if UMA (on these, the mclk is stored in SR10) */
1340 SiSMclk(SISPtr pSiS)
1342 int mclk;
1343 unsigned char Num, Denum, Base;
1345 switch (pSiS->Chipset) {
1347 case PCI_CHIP_SIS300:
1348 case PCI_CHIP_SIS540:
1349 case PCI_CHIP_SIS630:
1350 case PCI_CHIP_SIS550:
1351 case PCI_CHIP_SIS650:
1352 case PCI_CHIP_SIS315:
1353 case PCI_CHIP_SIS315H:
1354 case PCI_CHIP_SIS315PRO:
1355 case PCI_CHIP_SIS330:
1356 case PCI_CHIP_SIS660:
1357 /* Numerator */
1358 inSISIDXREG(SISSR, 0x28, Num);
1359 mclk = 14318 * ((Num & 0x7f) + 1);
1361 /* Denumerator */
1362 inSISIDXREG(SISSR, 0x29, Denum);
1363 mclk = mclk / ((Denum & 0x1f) + 1);
1365 /* Divider */
1366 if((Num & 0x80) != 0) mclk *= 2;
1368 /* Post-Scaler */
1369 if((Denum & 0x80) == 0) {
1370 mclk = mclk / (((Denum & 0x60) >> 5) + 1);
1371 } else {
1372 mclk = mclk / ((((Denum & 0x60) >> 5) + 1) * 2);
1374 break;
1376 case PCI_CHIP_SIS5597:
1377 case PCI_CHIP_SIS6326:
1378 case PCI_CHIP_SIS530:
1379 default:
1380 /* Numerator */
1381 inSISIDXREG(SISSR, 0x28, Num);
1382 mclk = 14318 * ((Num & 0x7f) + 1);
1384 /* Denumerator */
1385 inSISIDXREG(SISSR, 0x29, Denum);
1386 mclk = mclk / ((Denum & 0x1f) + 1);
1388 /* Divider. Doesn't work on older cards */
1389 if(pSiS->oldChipset >= OC_SIS5597) {
1390 if(Num & 0x80) mclk *= 2;
1393 /* Post-scaler. Values' meaning depends on SR13 bit 7 */
1394 inSISIDXREG(SISSR, 0x13, Base);
1395 if((Base & 0x80) == 0) {
1396 mclk = mclk / (((Denum & 0x60) >> 5) + 1);
1397 } else {
1398 /* Values 00 and 01 are reserved */
1399 if ((Denum & 0x60) == 0x40) mclk /= 6;
1400 if ((Denum & 0x60) == 0x60) mclk /= 8;
1402 break;
1405 return(mclk);
1408 /* This estimates the CRT2 clock we are going to use.
1409 * The total bandwidth is to be reduced by the value
1410 * returned here in order to get an idea of the maximum
1411 * dotclock left for CRT1.
1412 * Since we don't know yet, what mode the user chose,
1413 * we return the maximum dotclock used by
1414 * - either the LCD attached, or
1415 * - TV
1416 * For VGA2, we share the bandwith equally.
1418 static int
1419 SiSEstimateCRT2Clock(ScrnInfoPtr pScrn, BOOLEAN IsForMergedFBCRT2)
1421 SISPtr pSiS = SISPTR(pScrn);
1423 if(pSiS->VBFlags & CRT2_LCD) {
1424 if(pSiS->VBLCDFlags & (VB_LCD_320x480 | VB_LCD_800x600 | VB_LCD_640x480))
1425 return 40000;
1426 else if(pSiS->VBLCDFlags & (VB_LCD_1024x768 | VB_LCD_1024x600 | VB_LCD_1152x768))
1427 return 65000;
1428 else if(pSiS->VBLCDFlags & VB_LCD_1280x768)
1429 return 81000;
1430 else if(pSiS->VBLCDFlags & VB_LCD_1400x1050) {
1431 /* Must fake clock; built-in mode shows 122 for VGA, but uses only 108 for LCD */
1432 if(IsForMergedFBCRT2) return 123000;
1433 else return 108000;
1434 } else if(pSiS->VBLCDFlags & (VB_LCD_1280x1024 | VB_LCD_1280x960))
1435 return 108000;
1436 else if(pSiS->VBLCDFlags & VB_LCD_1600x1200)
1437 return 162000;
1438 else if((pSiS->VBLCDFlags & VB_LCD_CUSTOM) && (pSiS->SiS_Pr->CP_HaveCustomData))
1439 return pSiS->SiS_Pr->CP_MaxClock;
1440 else
1441 return 108000;
1442 } else if(pSiS->VBFlags & CRT2_TV) {
1443 if(pSiS->VBFlags & VB_CHRONTEL) {
1444 switch(pSiS->VGAEngine) {
1445 case SIS_300_VGA:
1446 return 50000;
1447 case SIS_315_VGA:
1448 default:
1449 return 70000;
1451 } else if(pSiS->VBFlags & VB_SISBRIDGE) {
1452 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)
1453 return 75000;
1454 else
1455 return 70000;
1459 return 0;
1462 /* Calculate the maximum dotclock */
1463 int SiSMemBandWidth(ScrnInfoPtr pScrn, BOOLEAN IsForCRT2)
1465 SISPtr pSiS = SISPTR(pScrn);
1466 #ifdef SISDUALHEAD
1467 SISEntPtr pSiSEnt = pSiS->entityPrivate;
1468 #endif
1470 int bus = pSiS->BusWidth;
1471 int mclk = pSiS->MemClock;
1472 int bpp = pSiS->CurrentLayout.bitsPerPixel;
1473 int bytesperpixel = (bpp + 7) / 8;
1474 float magic=0.0, total, crt2used, maxcrt2;
1475 int crt2clock, max=0;
1476 #ifdef __SUNPRO_C
1477 #define const
1478 #endif
1479 const float magic300[4] = { 1.2, 1.368421, 2.263158, 1.2};
1480 const float magic630[4] = { 1.441177, 1.441177, 2.588235, 1.441177 };
1481 const float magic315[4] = { 1.2, 1.368421, 1.368421, 1.2 };
1482 const float magic550[4] = { 1.441177, 1.441177, 2.588235, 1.441177 };
1483 #ifdef __SUNPRO_C
1484 #undef const
1485 #endif
1486 BOOLEAN DHM, GetForCRT1;
1488 switch(pSiS->Chipset) {
1490 case PCI_CHIP_SIS5597:
1491 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel;
1492 if(total > 135000) total = 135000;
1493 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1494 "Maximum pixel clock at %d bpp is %g MHz\n",
1495 bpp, total/1000);
1496 return(int)(total);
1498 case PCI_CHIP_SIS6326:
1499 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel;
1500 if(total > 175500) total = 175500;
1501 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1502 "Maximum pixel clock at %d bpp is %g MHz\n",
1503 bpp, total/1000);
1504 return(int)(total);
1506 case PCI_CHIP_SIS530:
1507 total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel;
1508 if(total > 230000) total = 230000;
1509 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1510 "Maximum pixel clock at %d bpp is %g MHz\n",
1511 bpp, total/1000);
1512 return(int)(total);
1514 case PCI_CHIP_SIS300:
1515 case PCI_CHIP_SIS540:
1516 case PCI_CHIP_SIS630:
1517 case PCI_CHIP_SIS315:
1518 case PCI_CHIP_SIS315H:
1519 case PCI_CHIP_SIS315PRO:
1520 case PCI_CHIP_SIS550:
1521 case PCI_CHIP_SIS650:
1522 case PCI_CHIP_SIS330:
1523 case PCI_CHIP_SIS660:
1524 switch(pSiS->Chipset) {
1525 case PCI_CHIP_SIS300:
1526 magic = magic300[bus/64];
1527 max = 540000;
1528 break;
1529 case PCI_CHIP_SIS540:
1530 case PCI_CHIP_SIS630:
1531 magic = magic630[bus/64];
1532 max = 540000;
1533 break;
1534 case PCI_CHIP_SIS315:
1535 case PCI_CHIP_SIS315H:
1536 case PCI_CHIP_SIS315PRO:
1537 case PCI_CHIP_SIS330:
1538 magic = magic315[bus/64];
1539 max = 780000;
1540 break;
1541 case PCI_CHIP_SIS550:
1542 magic = magic550[bus/64];
1543 max = 620000;
1544 break;
1545 case PCI_CHIP_SIS650:
1546 magic = magic550[bus/64];
1547 max = 680000;
1548 break;
1549 case PCI_CHIP_SIS660:
1550 if((pSiS->sishw_ext.jChipType >= SIS_660) &&
1551 (!(pSiS->ChipFlags & SiSCF_760UMA))) {
1552 magic = magic315[bus/64];
1553 } else {
1554 magic = magic550[bus/64];
1556 max = 680000;
1559 PDEBUG(ErrorF("mclk: %d, bus: %d, magic: %g, bpp: %d\n",
1560 mclk, bus, magic, bpp));
1562 total = mclk * bus / bpp;
1564 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1565 "Memory bandwidth at %d bpp is %g MHz\n", bpp, total/1000);
1567 if((pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) {
1569 maxcrt2 = 135000;
1570 if(pSiS->VBFlags & (VB_301B|VB_302B)) maxcrt2 = 162000;
1571 else if(pSiS->VBFlags & VB_301C) maxcrt2 = 203000;
1572 /* if(pSiS->VBFlags & VB_30xBDH) maxcrt2 = 100000;
1573 Ignore 301B-DH here; seems the current version is like
1574 301B anyway */
1576 crt2used = 0.0;
1577 crt2clock = SiSEstimateCRT2Clock(pScrn, IsForCRT2);
1578 if(crt2clock) {
1579 crt2used = crt2clock + 2000;
1581 DHM = FALSE;
1582 GetForCRT1 = FALSE;
1584 #ifdef SISDUALHEAD
1585 if((pSiS->DualHeadMode) && (pSiSEnt)) {
1586 DHM = TRUE;
1587 if(pSiS->SecondHead) GetForCRT1 = TRUE;
1589 #endif
1590 #ifdef SISMERGED
1591 if(pSiS->MergedFB && IsForCRT2) {
1592 DHM = TRUE;
1593 GetForCRT1 = FALSE;
1595 #endif
1597 if(DHM) {
1599 if(!GetForCRT1) {
1601 /* TW: First head = CRT2 */
1603 if(crt2clock) {
1604 /* TW: We use the mem bandwidth as max clock; this
1605 * might exceed the 70% limit a bit, but that
1606 * does not matter; we take care of that limit
1607 * when we calc CRT1. Overall, we might use up
1608 * to 85% of the memory bandwidth, which seems
1609 * enough to use accel and video.
1610 * The "* macic" is just to compensate the
1611 * calculation below.
1613 total = crt2used * magic;
1615 } else {
1616 /* We don't know about the second head's
1617 * depth yet. So we assume it uses the
1618 * same. But since the maximum dotclock
1619 * is limited on CRT2, we can assume a
1620 * maximum here.
1622 if((total / 2) > (maxcrt2 + 2000)) {
1623 total = (maxcrt2 + 2000) * magic;
1624 crt2used = maxcrt2 + 2000;
1625 } else {
1626 total /= 2;
1627 crt2used = total;
1632 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1633 "Bandwidth reserved for CRT2 is %g Mhz\n",
1634 crt2used/1000);
1636 } else {
1637 #ifdef SISDUALHEAD
1638 /* TW: Second head = CRT1 */
1640 /* Now We know about the first head's depth,
1641 * so we can calculate more accurately.
1644 if(crt2clock) {
1645 total -= (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp);
1646 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1647 "Bandwidth reserved for CRT2 at %d bpp is %g Mhz\n",
1648 bpp,
1649 (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000);
1650 } else {
1651 total -= (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp);
1652 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1653 "Bandwidth reserved for CRT2 at %d bpp is %d Mhz\n",
1654 bpp,
1655 (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000);
1658 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1659 "Bandwidth available for CRT1 is %g MHz\n", total/1000);
1660 #endif
1663 } else {
1665 if(crt2clock) {
1666 total -= crt2used;
1667 } else {
1668 if((total / 2) > (maxcrt2 + 2000)) {
1669 total -= (maxcrt2 + 2000);
1670 crt2used = maxcrt2 + 2000;
1671 } else {
1672 total /= 2;
1673 crt2used = total;
1676 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1677 "Bandwidth reserved for CRT2 is %g Mhz\n", crt2used/1000);
1679 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1680 "Bandwidth available for CRT1 is %g MHz\n", total/1000);
1685 total /= magic;
1686 if(total > (max / 2)) total = max / 2;
1687 return(int)(total);
1689 default:
1690 return(135000);
1694 /* Load the palette. We do this for all supported color depths
1695 * in order to support gamma correction. We hereby convert the
1696 * given colormap to a complete 24bit color palette and enable
1697 * the correspoding bit in SR7 to enable the 24bit lookup table.
1698 * Gamma correction is only supported on CRT1.
1699 * Why are there 6-bit-RGB values submitted even if bpp is 16 and
1700 * weight is 565? (Maybe because rgbBits is 6?)
1702 void
1703 SISLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1704 VisualPtr pVisual)
1706 SISPtr pSiS = SISPTR(pScrn);
1707 int i, j, index;
1708 unsigned char backup = 0;
1709 Bool dogamma1 = pSiS->CRT1gamma;
1710 Bool resetxvgamma = FALSE;
1711 #ifdef SISDUALHEAD
1712 SISEntPtr pSiSEnt = pSiS->entityPrivate;
1714 if(pSiS->DualHeadMode) dogamma1 = pSiSEnt->CRT1gamma;
1715 #endif
1717 PDEBUG(ErrorF("SiSLoadPalette(%d)\n", numColors));
1719 #ifdef SISDUALHEAD
1720 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) {
1721 #endif
1723 if(pSiS->VGAEngine == SIS_315_VGA) {
1724 inSISIDXREG(SISSR, 0x1f, backup);
1725 andSISIDXREG(SISSR, 0x1f, 0xe7);
1726 if( (pSiS->XvGamma) &&
1727 (pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA) &&
1728 ((pSiS->CurrentLayout.depth == 16) ||
1729 (pSiS->CurrentLayout.depth == 24)) ) {
1730 orSISIDXREG(SISSR, 0x1f, 0x10);
1731 resetxvgamma = TRUE;
1735 switch(pSiS->CurrentLayout.depth) {
1736 #ifdef SISGAMMA
1737 case 15:
1738 if(dogamma1) {
1739 orSISIDXREG(SISSR, 0x07, 0x04);
1740 for(i=0; i<numColors; i++) {
1741 index = indices[i];
1742 if(index < 32) { /* Paranoia */
1743 for(j=0; j<8; j++) {
1744 outSISREG(SISCOLIDX, (index * 8) + j);
1745 outSISREG(SISCOLDATA, colors[index].red << (8- pScrn->rgbBits));
1746 outSISREG(SISCOLDATA, colors[index].green << (8 - pScrn->rgbBits));
1747 outSISREG(SISCOLDATA, colors[index].blue << (8 - pScrn->rgbBits));
1751 } else {
1752 andSISIDXREG(SISSR, 0x07, ~0x04);
1754 break;
1755 case 16:
1756 if(dogamma1) {
1757 orSISIDXREG(SISSR, 0x07, 0x04);
1758 for(i=0; i<numColors; i++) {
1759 index = indices[i];
1760 if(index < 64) { /* Paranoia */
1761 for(j=0; j<4; j++) {
1762 outSISREG(SISCOLIDX, (index * 4) + j);
1763 outSISREG(SISCOLDATA, colors[index/2].red << (8 - pScrn->rgbBits));
1764 outSISREG(SISCOLDATA, colors[index].green << (8 - pScrn->rgbBits));
1765 outSISREG(SISCOLDATA, colors[index/2].blue << (8 - pScrn->rgbBits));
1769 } else {
1770 andSISIDXREG(SISSR, 0x07, ~0x04);
1772 break;
1773 case 24:
1774 if(dogamma1) {
1775 orSISIDXREG(SISSR, 0x07, 0x04);
1776 for(i=0; i<numColors; i++) {
1777 index = indices[i];
1778 if(index < 256) { /* Paranoia */
1779 outSISREG(SISCOLIDX, index);
1780 outSISREG(SISCOLDATA, colors[index].red);
1781 outSISREG(SISCOLDATA, colors[index].green);
1782 outSISREG(SISCOLDATA, colors[index].blue);
1785 } else {
1786 andSISIDXREG(SISSR, 0x07, ~0x04);
1788 break;
1789 #endif
1790 default:
1791 if((pScrn->rgbBits == 8) && (dogamma1))
1792 orSISIDXREG(SISSR, 0x07, 0x04);
1793 else
1794 andSISIDXREG(SISSR, 0x07, ~0x04);
1795 for(i=0; i<numColors; i++) {
1796 index = indices[i];
1797 outSISREG(SISCOLIDX, index);
1798 outSISREG(SISCOLDATA, colors[index].red >> (8 - pScrn->rgbBits));
1799 outSISREG(SISCOLDATA, colors[index].green >> (8 - pScrn->rgbBits));
1800 outSISREG(SISCOLDATA, colors[index].blue >> (8 - pScrn->rgbBits));
1804 if(pSiS->VGAEngine == SIS_315_VGA) {
1805 outSISIDXREG(SISSR, 0x1f, backup);
1806 inSISIDXREG(SISSR, 0x07, backup);
1807 if((backup & 0x04) && (resetxvgamma) && (pSiS->ResetXvGamma)) {
1808 (pSiS->ResetXvGamma)(pScrn);
1812 #ifdef SISDUALHEAD
1815 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
1816 #endif
1818 switch(pSiS->VGAEngine) {
1819 case SIS_300_VGA:
1820 case SIS_315_VGA:
1821 if(pSiS->VBFlags & CRT2_ENABLE) {
1822 /* Only the SiS bridges support a CRT2 palette */
1823 if(pSiS->VBFlags & VB_SISBRIDGE) {
1824 (*pSiS->LoadCRT2Palette)(pScrn, numColors, indices, colors, pVisual);
1829 #ifdef SISDUALHEAD
1831 #endif
1835 static void
1836 SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1837 LOCO *colors, VisualPtr pVisual)
1839 SISPtr pSiS = SISPTR(pScrn);
1840 int i, j, index;
1841 Bool dogamma2 = pSiS->CRT2gamma;
1842 #ifdef SISDUALHEAD
1843 SISEntPtr pSiSEnt = pSiS->entityPrivate;
1845 if(pSiS->DualHeadMode) dogamma2 = pSiSEnt->CRT2gamma;
1846 #endif
1848 PDEBUG(ErrorF("SiS301LoadPalette(%d)\n", numColors));
1850 /* 301B-DH does not support a color palette for LCD */
1851 if((pSiS->VBFlags & VB_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) return;
1853 switch(pSiS->CurrentLayout.depth) {
1854 #ifdef SISGAMMA
1855 case 15:
1856 if(dogamma2) {
1857 orSISIDXREG(SISPART4, 0x0d, 0x08);
1858 for(i=0; i<numColors; i++) {
1859 index = indices[i];
1860 if(index < 32) { /* Paranoia */
1861 for(j=0; j<8; j++) {
1862 outSISREG(SISCOL2IDX, (index * 8) + j);
1863 outSISREG(SISCOL2DATA, colors[index].red << (8- pScrn->rgbBits));
1864 outSISREG(SISCOL2DATA, colors[index].green << (8 - pScrn->rgbBits));
1865 outSISREG(SISCOL2DATA, colors[index].blue << (8 - pScrn->rgbBits));
1869 } else {
1870 andSISIDXREG(SISPART4, 0x0d, ~0x08);
1872 break;
1873 case 16:
1874 if(dogamma2) {
1875 orSISIDXREG(SISPART4, 0x0d, 0x08);
1876 for(i=0; i<numColors; i++) {
1877 index = indices[i];
1878 if(index < 64) { /* Paranoia */
1879 for(j=0; j<4; j++) {
1880 outSISREG(SISCOL2IDX, (index * 4) + j);
1881 outSISREG(SISCOL2DATA, colors[index/2].red << (8 - pScrn->rgbBits));
1882 outSISREG(SISCOL2DATA, colors[index].green << (8 - pScrn->rgbBits));
1883 outSISREG(SISCOL2DATA, colors[index/2].blue << (8 - pScrn->rgbBits));
1887 } else {
1888 andSISIDXREG(SISPART4, 0x0d, ~0x08);
1890 break;
1891 case 24:
1892 if(dogamma2) {
1893 orSISIDXREG(SISPART4, 0x0d, 0x08);
1894 for(i=0; i<numColors; i++) {
1895 index = indices[i];
1896 if(index < 256) { /* Paranoia */
1897 outSISREG(SISCOL2IDX, index);
1898 outSISREG(SISCOL2DATA, colors[index].red);
1899 outSISREG(SISCOL2DATA, colors[index].green);
1900 outSISREG(SISCOL2DATA, colors[index].blue);
1903 } else {
1904 andSISIDXREG(SISPART4, 0x0d, ~0x08);
1906 break;
1907 #endif
1908 default:
1909 if((pScrn->rgbBits == 8) && (dogamma2))
1910 orSISIDXREG(SISPART4, 0x0d, 0x08);
1911 else
1912 andSISIDXREG(SISPART4, 0x0d, ~0x08);
1913 for(i=0; i<numColors; i++) {
1914 index = indices[i];
1915 outSISREG(SISCOL2IDX, index);
1916 outSISREG(SISCOL2DATA, colors[index].red);
1917 outSISREG(SISCOL2DATA, colors[index].green);
1918 outSISREG(SISCOL2DATA, colors[index].blue);
1923 void
1924 SISDACPreInit(ScrnInfoPtr pScrn)
1926 SISPtr pSiS = SISPTR(pScrn);
1928 switch (pSiS->Chipset) {
1929 case PCI_CHIP_SIS550:
1930 case PCI_CHIP_SIS650:
1931 case PCI_CHIP_SIS315:
1932 case PCI_CHIP_SIS315H:
1933 case PCI_CHIP_SIS315PRO:
1934 case PCI_CHIP_SIS330:
1935 case PCI_CHIP_SIS660:
1936 pSiS->MaxClock = SiSMemBandWidth(pScrn, FALSE);
1937 pSiS->SiSSave = SiS315Save;
1938 pSiS->SiSSave2 = SiS301Save;
1939 pSiS->SiSSave3 = SiS301BSave;
1940 pSiS->SiSSaveLVDSChrontel = SiSLVDSChrontelSave;
1941 pSiS->SiSRestore = SiS315Restore;
1942 pSiS->SiSRestore2 = SiS301Restore;
1943 pSiS->SiSRestore3 = SiS301BRestore;
1944 pSiS->SiSRestoreLVDSChrontel = SiSLVDSChrontelRestore;
1945 pSiS->LoadCRT2Palette = SiS301LoadPalette;
1946 break;
1947 case PCI_CHIP_SIS300:
1948 case PCI_CHIP_SIS630:
1949 case PCI_CHIP_SIS540:
1950 pSiS->MaxClock = SiSMemBandWidth(pScrn, FALSE);
1951 pSiS->SiSSave = SiS300Save;
1952 pSiS->SiSSave2 = SiS301Save;
1953 pSiS->SiSSave3 = SiS301BSave;
1954 pSiS->SiSSaveLVDSChrontel = SiSLVDSChrontelSave;
1955 pSiS->SiSRestore = SiS300Restore;
1956 pSiS->SiSRestore2 = SiS301Restore;
1957 pSiS->SiSRestore3 = SiS301BRestore;
1958 pSiS->SiSRestoreLVDSChrontel = SiSLVDSChrontelRestore;
1959 pSiS->LoadCRT2Palette = SiS301LoadPalette;
1960 break;
1961 case PCI_CHIP_SIS5597:
1962 case PCI_CHIP_SIS6326:
1963 case PCI_CHIP_SIS530:
1964 default:
1965 pSiS->MaxClock = SiSMemBandWidth(pScrn, FALSE);
1966 pSiS->SiSRestore = SiSRestore;
1967 pSiS->SiSSave = SiSSave;
1968 break;
1972 static void
1973 SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr)
1975 CARD8 index;
1977 for(index = from; index <= to; index++, DataPtr++) {
1978 outSISIDXREG(port, index, *DataPtr);
1982 void
1983 SiS6326SetTVReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data)
1985 SISPtr pSiS = SISPTR(pScrn);
1986 outSISIDXREG(SISCR, 0xE0, index);
1987 outSISIDXREG(SISCR, 0xE1, data);
1988 #ifdef TWDEBUG
1989 xf86DrvMsg(0, X_INFO, "SiS6326: Setting Tv %02x to %02x\n", index, data);
1990 #endif
1993 unsigned char
1994 SiS6326GetTVReg(ScrnInfoPtr pScrn, CARD8 index)
1996 SISPtr pSiS = SISPTR(pScrn);
1997 unsigned char data;
1999 outSISIDXREG(SISCR, 0xE0, index);
2000 inSISIDXREG(SISCR, 0xE1, data);
2001 return(data);
2004 void
2005 SiS6326SetXXReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data)
2007 SISPtr pSiS = SISPTR(pScrn);
2008 outSISIDXREG(SISCR, 0xE2, index);
2009 outSISIDXREG(SISCR, 0xE3, data);
2012 unsigned char
2013 SiS6326GetXXReg(ScrnInfoPtr pScrn, CARD8 index)
2015 SISPtr pSiS = SISPTR(pScrn);
2016 unsigned char data;
2018 outSISIDXREG(SISCR, 0xE2, index);
2019 inSISIDXREG(SISCR, 0xE3, data);
2020 return(data);