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
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
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)
49 #include "xf86_OSproc.h"
50 #include "xf86_ansic.h"
51 #include "xf86Version.h"
52 #include "xf86PciInfo.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
98 float f
,x
,y
,t
, error
, min_error
;
99 int n
, dn
, best_n
=0, best_dn
=0;
104 * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator)
105 * Factor = (Divider/Post Scalar)
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
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)
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
139 if((f
> 250.0) || (f
< 18.75))
152 } else if(x
>= 15.625) {
158 if(t
== (float) 1.5) {
164 if(t
> (float) 4.0) {
171 *out_scale
= (int) t
;
173 for(dn
= 2; dn
<= 32; dn
++) {
174 for(n
= 1; n
<= 128; n
++) {
176 error
-= ((float) 14.318 * (float) n
/ (float) dn
);
177 if(error
< (float) 0)
179 if(error
< min_error
) {
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
));
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;
204 double error
, aerror
;
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)
225 #define Fref 14318180
226 /* stability constraints for internal VCO -- MAX_VCO also determines
227 * the maximum Video pixel clock */
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 */
237 target
= clock
* 1000;
239 if(pSiS
->Chipset
== PCI_CHIP_SIS5597
|| pSiS
->Chipset
== PCI_CHIP_SIS6326
) {
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;
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;
263 M
= Fvco
/ Fref
* N
+ 0.5;
267 Fout
= (double)Fref
* (M
* VLD
)/(N
* P
);
269 error
= (target
- Fout
) / target
;
270 aerror
= (error
< 0) ? -error
: error
;
286 for(PSNx
= 0; PSNx
<= MAX_PSN
; PSNx
++) {
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
++) {
321 if(Fvco
<= MIN_VCO
) continue;
322 if(Fvco
> MAX_VCO
) break;
326 error
= (target
- Fout
) / target
;
327 aerror
= (error
< 0) ? -error
: error
;
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
);
355 vclk
[VLDidx
] = bestVLD
;
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
));
371 SiSSave(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
373 SISPtr pSiS
= SISPTR(pScrn
);
376 PDEBUG(xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 3,
377 "SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
380 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
383 switch(pSiS
->Chipset
) {
384 case PCI_CHIP_SIS5597
:
387 case PCI_CHIP_SIS6326
:
388 case PCI_CHIP_SIS530
:
396 /* Save extended SR registers */
397 for(i
= 0x00; i
<= max
; i
++) {
398 inSISIDXREG(SISSR
, i
, sisReg
->sisRegs3C4
[i
]);
400 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
401 "SR%02X - %02X \n", i
,sisReg
->sisRegs3C4
[i
]);
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
);
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
);
424 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
425 "VR%02X - %02X \n", i
,sisReg
->sis6326tv
[i
]);
432 SiSRestore(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
434 SISPtr pSiS
= SISPTR(pScrn
);
438 xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 4,
439 "SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
442 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
445 switch(pSiS
->Chipset
) {
446 case PCI_CHIP_SIS5597
:
449 case PCI_CHIP_SIS6326
:
450 case PCI_CHIP_SIS530
:
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);
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]);
478 outSISREG(SISMISCW
, sisReg
->sisRegs3C2
);
480 /* MemClock needs this to take effect */
481 outSISIDXREG(SISSR
, 0x00, 0x01); /* Synchronous Reset */
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
]);
491 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
492 "VR%02x restored to %02x\n",
493 i
, sisReg
->sis6326tv
[i
]);
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 */
512 SiS300Save(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
514 SISPtr pSiS
= SISPTR(pScrn
);
517 PDEBUG(xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 3,
518 "SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
521 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
524 /* Save SR registers */
525 for(i
= 0x00; i
<= 0x3D; i
++) {
526 inSISIDXREG(SISSR
, i
, sisReg
->sisRegs3C4
[i
]);
528 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
529 "SR%02X - %02X \n", i
,sisReg
->sisRegs3C4
[i
]);
533 /* Save CR registers */
534 for(i
= 0x00; i
< 0x40; i
++) {
535 inSISIDXREG(SISCR
, i
, sisReg
->sisRegs3D4
[i
]);
537 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
538 "CR%02X Contents - %02X \n", i
,sisReg
->sisRegs3D4
[i
]);
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);
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
);
557 /* Save panel link/video bridge registers */
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
);
571 /* Save Mode number */
572 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
575 pSiS
->BIOSModeSave
= SiS_GetSetModeID(pScrn
,0xFF);
578 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
579 "BIOS mode ds:449 = 0x%x\n", pSiS
->BIOSModeSave
);
584 /* Restore SiS300 series register contents */
586 SiS300Restore(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
588 SISPtr pSiS
= SISPTR(pScrn
);
592 xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 4,
593 "SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
596 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
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
) {
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
) {
650 inSISIDXREG(SISSR
,0x11,temp
);
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) {
694 temp1
|= (sisReg
->sisRegsPCI50
& ~0xf0ffffff);
697 temp1
|= (sisReg
->sisRegsPCI50
& ~0xfffff9ff);
699 pciWriteLong(0x00000000, 0x50, temp1
);
701 temp1
= pciReadLong(0x00000000, 0xA0);
702 if(pciReadLong(0x00000000, 0x00) == 0x06301039) {
704 temp1
|= (sisReg
->sisRegsPCIA0
& ~0xf0ffffff);
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)
730 SiS_GetSetModeID(pScrn
,pSiS
->BIOSModeSave
);
733 /* Save SiS315 series register contents */
735 SiS315Save(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
737 SISPtr pSiS
= SISPTR(pScrn
);
740 PDEBUG(xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 3,
741 "SiS315Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"));
744 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
747 /* Save SR registers */
748 for(i
= 0x00; i
<= 0x3F; i
++) {
749 inSISIDXREG(SISSR
, i
, sisReg
->sisRegs3C4
[i
]);
751 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
752 "SR%02X - %02X \n", i
,sisReg
->sisRegs3C4
[i
]);
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
]);
763 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
764 "CR%02X Contents - %02X \n", i
,sisReg
->sisRegs3D4
[i
]);
768 /* Save video capture registers */
769 for(i
= 0x00; i
<= 0x4f; i
++) {
770 inSISIDXREG(SISCAP
, i
, sisReg
->sisCapt
[i
]);
772 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
773 "Capt%02X Contents - %02X \n", i
,sisReg
->sisCapt
[i
]);
777 /* Save video playback registers */
778 for(i
= 0x00; i
<= 0x3f; i
++) {
779 inSISIDXREG(SISVID
, i
, sisReg
->sisVid
[i
]);
781 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
782 "Vid%02X Contents - %02X \n", i
,sisReg
->sisVid
[i
]);
786 /* Save Misc register */
787 sisReg
->sisRegs3C2
= inSISREG(SISMISCR
);
789 /* Save panel link/video bridge registers */
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
);
803 /* Save mode number */
804 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
807 pSiS
->BIOSModeSave
= SiS_GetSetModeID(pScrn
,0xFF);
810 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
811 "BIOS mode ds:449 = 0x%x\n", pSiS
->BIOSModeSave
);
815 /* Restore SiS315/330 series register contents */
817 SiS315Restore(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
819 SISPtr pSiS
= SISPTR(pScrn
);
822 xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 4,
823 "SiS315Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n");
826 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
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
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]);
894 outSISIDXREG(SISSR
,0x2b,sisReg
->sisRegs3C4
[0x2b]);
895 outSISIDXREG(SISSR
,0x2c,sisReg
->sisRegs3C4
[0x2c]);
896 outSISIDXREG(SISSR
,0x2d,0x01);
900 /* Initialize read/write pointer for command queue */
901 MMIO_OUT32(pSiS
->IOBase
, 0x85C4, MMIO_IN32(pSiS
->IOBase
, 0x85C8));
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)
927 SiS_GetSetModeID(pScrn
,pSiS
->BIOSModeSave
);
931 SiSVBSave(ScrnInfoPtr pScrn
, SISRegPtr sisReg
, int p1
, int p2
, int p3
, int p4
)
933 SISPtr pSiS
= SISPTR(pScrn
);
936 for(i
=0; i
<=p1
; i
++) {
937 inSISIDXREG(SISPART1
, i
, sisReg
->VBPart1
[i
]);
939 xf86DrvMsg(0, X_INFO
, "301xSave: Part1Port 0x%02x = 0x%02x\n", i
, sisReg
->VBPart1
[i
]);
942 for(i
=0; i
<=p2
; i
++) {
943 inSISIDXREG(SISPART2
, i
, sisReg
->VBPart2
[i
]);
945 xf86DrvMsg(0, X_INFO
, "301xSave: Part2Port 0x%02x = 0x%02x\n", i
, sisReg
->VBPart2
[i
]);
948 for(i
=0; i
<=p3
; i
++) {
949 inSISIDXREG(SISPART3
, i
, sisReg
->VBPart3
[i
]);
951 xf86DrvMsg(0, X_INFO
, "301xSave: Part3Port 0x%02x = 0x%02x\n", i
, sisReg
->VBPart3
[i
]);
954 for(i
=0; i
<=p4
; i
++) {
955 inSISIDXREG(SISPART4
, i
, sisReg
->VBPart4
[i
]);
957 xf86DrvMsg(0, X_INFO
, "301xSave: Part4Port 0x%02x = 0x%02x\n", i
, sisReg
->VBPart4
[i
]);
962 /* Save SiS301 bridge register contents */
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 */
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 */
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;
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
);
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]));
1027 SetBlock(SISPART2
, 0x00, Part2max
, &(sisReg
->VBPart2
[0x00]));
1030 SetBlock(SISPART3
, 0x00, Part3max
, &(sisReg
->VBPart3
[0x00]));
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 */
1050 SiS301BSave(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
1052 SISPtr pSiS
= SISPTR(pScrn
);
1053 int Part1max
, Part2max
, Part3max
, Part4max
;
1059 if(pSiS
->VBFlags
& (VB_301C
|VB_302ELV
)) {
1063 if(pSiS
->VBFlags
& (VB_301LV
|VB_302LV
)) {
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 */
1075 SiS301BRestore(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
1077 SISPtr pSiS
= SISPTR(pScrn
);
1078 int Part1max
, Part2max
, Part3max
, Part4max
;
1084 if(pSiS
->VBFlags
& (VB_301C
|VB_302ELV
)) {
1088 if(pSiS
->VBFlags
& (VB_301LV
|VB_302LV
)) {
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
);
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]));
1125 SetBlock(SISPART2
, 0x00, Part2max
, &(sisReg
->VBPart2
[0x00]));
1128 SetBlock(SISPART3
, 0x00, Part3max
, &(sisReg
->VBPart3
[0x00]));
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 */
1147 SiSLVDSChrontelSave(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
1149 SISPtr pSiS
= SISPTR(pScrn
);
1153 for(i
=0; i
<0x46; i
++) {
1154 inSISIDXREG(SISPART1
, i
, sisReg
->VBPart1
[i
]);
1156 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1157 "LVDSSave: Part1Port 0x%02x = 0x%02x\n",
1158 i
, sisReg
->VBPart1
[i
]);
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
]);
1168 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1169 "LVDSSave: Chrontel 0x%02x = 0x%02x\n",
1170 ch700xidx
[i
], sisReg
->ch70xx
[i
]);
1174 for(i
=0; i
<35; i
++) {
1175 sisReg
->ch70xx
[i
] = SiS_GetCH701x(pSiS
->SiS_Pr
, ch701xidx
[i
]);
1177 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1178 "LVDSSave: Chrontel 0x%02x = 0x%02x\n",
1179 ch701xidx
[i
], sisReg
->ch70xx
[i
]);
1185 sisReg
->sisRegs3C4
[0x32] &= ~0x20; /* Disable Lock Mode */
1188 /* Restore LVDS bridge (+ Chrontel) register contents */
1190 SiSLVDSChrontelRestore(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
1192 SISPtr pSiS
= SISPTR(pScrn
);
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
);
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));
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
);
1236 if(pSiS
->VGAEngine
== SIS_300_VGA
) {
1237 outSISIDXREG(SISPART1
, 0x02, (sisReg
->VBPart1
[2] | 0x40));
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 */
1260 SiSRestoreBridge(ScrnInfoPtr pScrn
, SISRegPtr sisReg
)
1262 SISPtr pSiS
= SISPTR(pScrn
);
1265 #ifdef UNLOCK_ALWAYS
1266 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
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.
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,
1306 depthindex
= (pSiS
->CurrentLayout
.bitsPerPixel
+ 1) >> 3;
1307 if(depthindex
== 3) return(0);
1308 if(depthindex
== 4) depthindex
--;
1311 switch(mode
->HDisplay
) {
1313 if(mode
->VDisplay
== 480) {
1314 return(t640x480
[depthindex
][index
];
1317 if(mode
->VDisplay
== 600) {
1318 return(t800x600
[depthindex
][index
];
1321 if(mode
->VDisplay
== 768) {
1322 return(t1024x768
[depthindex
][index
];
1325 if(mode
->VDisplay
== 1024) {
1326 return(t1280x1024
[depthindex
][index
];
1329 if(mode
->VDisplay
== 1200) {
1330 return(t1600x1200
[depthindex
][index
];
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
)
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
:
1358 inSISIDXREG(SISSR
, 0x28, Num
);
1359 mclk
= 14318 * ((Num
& 0x7f) + 1);
1362 inSISIDXREG(SISSR
, 0x29, Denum
);
1363 mclk
= mclk
/ ((Denum
& 0x1f) + 1);
1366 if((Num
& 0x80) != 0) mclk
*= 2;
1369 if((Denum
& 0x80) == 0) {
1370 mclk
= mclk
/ (((Denum
& 0x60) >> 5) + 1);
1372 mclk
= mclk
/ ((((Denum
& 0x60) >> 5) + 1) * 2);
1376 case PCI_CHIP_SIS5597
:
1377 case PCI_CHIP_SIS6326
:
1378 case PCI_CHIP_SIS530
:
1381 inSISIDXREG(SISSR
, 0x28, Num
);
1382 mclk
= 14318 * ((Num
& 0x7f) + 1);
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);
1398 /* Values 00 and 01 are reserved */
1399 if ((Denum
& 0x60) == 0x40) mclk
/= 6;
1400 if ((Denum
& 0x60) == 0x60) mclk
/= 8;
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
1416 * For VGA2, we share the bandwith equally.
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
))
1426 else if(pSiS
->VBLCDFlags
& (VB_LCD_1024x768
| VB_LCD_1024x600
| VB_LCD_1152x768
))
1428 else if(pSiS
->VBLCDFlags
& VB_LCD_1280x768
)
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;
1434 } else if(pSiS
->VBLCDFlags
& (VB_LCD_1280x1024
| VB_LCD_1280x960
))
1436 else if(pSiS
->VBLCDFlags
& VB_LCD_1600x1200
)
1438 else if((pSiS
->VBLCDFlags
& VB_LCD_CUSTOM
) && (pSiS
->SiS_Pr
->CP_HaveCustomData
))
1439 return pSiS
->SiS_Pr
->CP_MaxClock
;
1442 } else if(pSiS
->VBFlags
& CRT2_TV
) {
1443 if(pSiS
->VBFlags
& VB_CHRONTEL
) {
1444 switch(pSiS
->VGAEngine
) {
1451 } else if(pSiS
->VBFlags
& VB_SISBRIDGE
) {
1452 if(pSiS
->SiS_SD_Flags
& SiS_SD_SUPPORTYPBPR
)
1462 /* Calculate the maximum dotclock */
1463 int SiSMemBandWidth(ScrnInfoPtr pScrn
, BOOLEAN IsForCRT2
)
1465 SISPtr pSiS
= SISPTR(pScrn
);
1467 SISEntPtr pSiSEnt
= pSiS
->entityPrivate
;
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;
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 };
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",
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",
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",
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];
1529 case PCI_CHIP_SIS540
:
1530 case PCI_CHIP_SIS630
:
1531 magic
= magic630
[bus
/64];
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];
1541 case PCI_CHIP_SIS550
:
1542 magic
= magic550
[bus
/64];
1545 case PCI_CHIP_SIS650
:
1546 magic
= magic550
[bus
/64];
1549 case PCI_CHIP_SIS660
:
1550 if((pSiS
->sishw_ext
.jChipType
>= SIS_660
) &&
1551 (!(pSiS
->ChipFlags
& SiSCF_760UMA
))) {
1552 magic
= magic315
[bus
/64];
1554 magic
= magic550
[bus
/64];
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
)) {
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
1577 crt2clock
= SiSEstimateCRT2Clock(pScrn
, IsForCRT2
);
1579 crt2used
= crt2clock
+ 2000;
1585 if((pSiS
->DualHeadMode
) && (pSiSEnt
)) {
1587 if(pSiS
->SecondHead
) GetForCRT1
= TRUE
;
1591 if(pSiS
->MergedFB
&& IsForCRT2
) {
1601 /* TW: First head = CRT2 */
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
;
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
1622 if((total
/ 2) > (maxcrt2
+ 2000)) {
1623 total
= (maxcrt2
+ 2000) * magic
;
1624 crt2used
= maxcrt2
+ 2000;
1632 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
1633 "Bandwidth reserved for CRT2 is %g Mhz\n",
1638 /* TW: Second head = CRT1 */
1640 /* Now We know about the first head's depth,
1641 * so we can calculate more accurately.
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",
1649 (crt2used
* pSiSEnt
->pScrn_1
->bitsPerPixel
/ bpp
)/1000);
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",
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);
1668 if((total
/ 2) > (maxcrt2
+ 2000)) {
1669 total
-= (maxcrt2
+ 2000);
1670 crt2used
= maxcrt2
+ 2000;
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);
1686 if(total
> (max
/ 2)) total
= max
/ 2;
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?)
1703 SISLoadPalette(ScrnInfoPtr pScrn
, int numColors
, int *indices
, LOCO
*colors
,
1706 SISPtr pSiS
= SISPTR(pScrn
);
1708 unsigned char backup
= 0;
1709 Bool dogamma1
= pSiS
->CRT1gamma
;
1710 Bool resetxvgamma
= FALSE
;
1712 SISEntPtr pSiSEnt
= pSiS
->entityPrivate
;
1714 if(pSiS
->DualHeadMode
) dogamma1
= pSiSEnt
->CRT1gamma
;
1717 PDEBUG(ErrorF("SiSLoadPalette(%d)\n", numColors
));
1720 if((!pSiS
->DualHeadMode
) || (pSiS
->SecondHead
)) {
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
) {
1739 orSISIDXREG(SISSR
, 0x07, 0x04);
1740 for(i
=0; i
<numColors
; 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
));
1752 andSISIDXREG(SISSR
, 0x07, ~0x04);
1757 orSISIDXREG(SISSR
, 0x07, 0x04);
1758 for(i
=0; i
<numColors
; 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
));
1770 andSISIDXREG(SISSR
, 0x07, ~0x04);
1775 orSISIDXREG(SISSR
, 0x07, 0x04);
1776 for(i
=0; i
<numColors
; 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
);
1786 andSISIDXREG(SISSR
, 0x07, ~0x04);
1791 if((pScrn
->rgbBits
== 8) && (dogamma1
))
1792 orSISIDXREG(SISSR
, 0x07, 0x04);
1794 andSISIDXREG(SISSR
, 0x07, ~0x04);
1795 for(i
=0; i
<numColors
; 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
);
1815 if((!pSiS
->DualHeadMode
) || (!pSiS
->SecondHead
)) {
1818 switch(pSiS
->VGAEngine
) {
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
);
1836 SiS301LoadPalette(ScrnInfoPtr pScrn
, int numColors
, int *indices
,
1837 LOCO
*colors
, VisualPtr pVisual
)
1839 SISPtr pSiS
= SISPTR(pScrn
);
1841 Bool dogamma2
= pSiS
->CRT2gamma
;
1843 SISEntPtr pSiSEnt
= pSiS
->entityPrivate
;
1845 if(pSiS
->DualHeadMode
) dogamma2
= pSiSEnt
->CRT2gamma
;
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
) {
1857 orSISIDXREG(SISPART4
, 0x0d, 0x08);
1858 for(i
=0; i
<numColors
; 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
));
1870 andSISIDXREG(SISPART4
, 0x0d, ~0x08);
1875 orSISIDXREG(SISPART4
, 0x0d, 0x08);
1876 for(i
=0; i
<numColors
; 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
));
1888 andSISIDXREG(SISPART4
, 0x0d, ~0x08);
1893 orSISIDXREG(SISPART4
, 0x0d, 0x08);
1894 for(i
=0; i
<numColors
; 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
);
1904 andSISIDXREG(SISPART4
, 0x0d, ~0x08);
1909 if((pScrn
->rgbBits
== 8) && (dogamma2
))
1910 orSISIDXREG(SISPART4
, 0x0d, 0x08);
1912 andSISIDXREG(SISPART4
, 0x0d, ~0x08);
1913 for(i
=0; i
<numColors
; i
++) {
1915 outSISREG(SISCOL2IDX
, index
);
1916 outSISREG(SISCOL2DATA
, colors
[index
].red
);
1917 outSISREG(SISCOL2DATA
, colors
[index
].green
);
1918 outSISREG(SISCOL2DATA
, colors
[index
].blue
);
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
;
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
;
1961 case PCI_CHIP_SIS5597
:
1962 case PCI_CHIP_SIS6326
:
1963 case PCI_CHIP_SIS530
:
1965 pSiS
->MaxClock
= SiSMemBandWidth(pScrn
, FALSE
);
1966 pSiS
->SiSRestore
= SiSRestore
;
1967 pSiS
->SiSSave
= SiSSave
;
1973 SetBlock(CARD16 port
, CARD8 from
, CARD8 to
, CARD8
*DataPtr
)
1977 for(index
= from
; index
<= to
; index
++, DataPtr
++) {
1978 outSISIDXREG(port
, index
, *DataPtr
);
1983 SiS6326SetTVReg(ScrnInfoPtr pScrn
, CARD8 index
, CARD8 data
)
1985 SISPtr pSiS
= SISPTR(pScrn
);
1986 outSISIDXREG(SISCR
, 0xE0, index
);
1987 outSISIDXREG(SISCR
, 0xE1, data
);
1989 xf86DrvMsg(0, X_INFO
, "SiS6326: Setting Tv %02x to %02x\n", index
, data
);
1994 SiS6326GetTVReg(ScrnInfoPtr pScrn
, CARD8 index
)
1996 SISPtr pSiS
= SISPTR(pScrn
);
1999 outSISIDXREG(SISCR
, 0xE0, index
);
2000 inSISIDXREG(SISCR
, 0xE1, data
);
2005 SiS6326SetXXReg(ScrnInfoPtr pScrn
, CARD8 index
, CARD8 data
)
2007 SISPtr pSiS
= SISPTR(pScrn
);
2008 outSISIDXREG(SISCR
, 0xE2, index
);
2009 outSISIDXREG(SISCR
, 0xE3, data
);
2013 SiS6326GetXXReg(ScrnInfoPtr pScrn
, CARD8 index
)
2015 SISPtr pSiS
= SISPTR(pScrn
);
2018 outSISIDXREG(SISCR
, 0xE2, index
);
2019 inSISIDXREG(SISCR
, 0xE3, data
);