summaryrefslogtreecommitdiff
path: root/src/sis_vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sis_vga.c')
-rw-r--r--src/sis_vga.c1845
1 files changed, 1057 insertions, 788 deletions
diff --git a/src/sis_vga.c b/src/sis_vga.c
index 0ab8b8d..1e056c7 100644
--- a/src/sis_vga.c
+++ b/src/sis_vga.c
@@ -1,9 +1,11 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_vga.c,v 1.16 2003/01/29 15:42:17 eich Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_vga.c,v 1.38 2003/11/19 00:49:06 twini Exp $ */
/*
- * Mode setup and video bridge detection
+ * Mode setup and basic video bridge detection
*
- * Copyright 1998,1999 by Alan Hourihane, Wigan, England.
- * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria.
+ * Copyright 2001, 2002, 2003 by Thomas Winischhofer, Vienna, Austria.
+ *
+ * Init() function for old series (except for TV and FIFO calculation) based
+ * on code which was Copyright 1998,1999 by Alan Hourihane, Wigan, England.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -23,12 +25,9 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
- * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk
- * Mike Chapman <mike@paranoia.com>,
- * Juanjo Santamarta <santamarta@ctv.es>,
- * Mitani Hiroshi <hmitani@drl.mei.co.jp>
- * David Thomas <davtom@dream.org.uk>.
- * Thomas Winischhofer <thomas@winischhofer.net>
+ * Authors: Thomas Winischhofer <thomas@winischhofer.net>
+ * ...
+ *
*/
#include "xf86.h"
@@ -42,39 +41,43 @@
#include "sis_regs.h"
#include "sis_dac.h"
-#define Midx 0
-#define Nidx 1
-#define VLDidx 2
-#define Pidx 3
-#define PSNidx 4
-#define Fref 14318180
-/* stability constraints for internal VCO -- MAX_VCO also determines
- * the maximum Video pixel clock */
-#define MIN_VCO Fref
-#define MAX_VCO 135000000
-#define MAX_VCO_5597 353000000
-#define MAX_PSN 0 /* no pre scaler for this chip */
-#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */
-
+#if 0
+#define TV6326TEST
+#endif
static Bool SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
static Bool SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode);
-/* TW: To be used internally only */
-int SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch);
-void SISSense30x(ScrnInfoPtr pScrn);
-int SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl);
-void SISSense6326(ScrnInfoPtr pScrn);
-static void SiS6326TVDelay(ScrnInfoPtr pScrn, int delay);
+/* To be used internally only */
+static int SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch);
+static void SISSense30x(ScrnInfoPtr pScrn);
+static int SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl);
+static void SISSense6326(ScrnInfoPtr pScrn);
+static void SiS6326TVDelay(ScrnInfoPtr pScrn, int delay);
+
+const CARD8 SiS6326TVRegs1[14] = {
+ 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43
+};
const CARD8 SiS6326TVRegs1_NTSC[6][14] = {
{0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
{0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
{0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60},
{0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60},
- {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60},
+ {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60}, /* 640x400, 640x480 */
{0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79} /* 640x480u */
};
+#ifdef TV6326TEST
+const CARD8 SiS6326TVRegs1_NTSC_2[6][3] = {
+ { 0x00,0x00,0x00},
+ { 0x00,0x00,0x00},
+ { 0x24,0x92,0x49},
+ { 0x24,0x92,0x49}, /* 8a50 */
+ { 0x24,0x92,0x49}, /* 640x400, 640x480 */ /* 8afc */
+ { 0x21,0xbe,0x75} /* 640x480u */ /* n/a */
+};
+#endif
+
const CARD8 SiS6326TVRegs2_NTSC[6][54] = {
{0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
@@ -111,12 +114,23 @@ const CARD8 SiS6326TVRegs2_NTSC[6][54] = {
const CARD8 SiS6326TVRegs1_PAL[6][14] = {
{0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40},
{0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40},
- {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40},
- {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40},
+ {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, /* 640x480 */
+ {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40}, /* 800x600 */
{0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59}, /* 800x600u */
{0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59} /* 720x540 */
};
+#ifdef TV6326TEST
+const CARD8 SiS6326TVRegs1_PAL_2[6][3] = {
+ { 0x00,0x00,0x00},
+ { 0x00,0x00,0x00},
+ { 0xa4,0x07,0xd9}, /* 640x480 */ /* 887e */
+ { 0xa4,0x08,0x19}, /* 800x600 */ /* 8828 */
+ { 0xa1,0x7e,0xa3}, /* 800x600u */ /* n/a */
+ { 0xa4,0x07,0xd9} /* 720x540 */ /* n/a */
+};
+#endif
+
const CARD8 SiS6326TVRegs2_PAL[6][54] = {
{0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
@@ -128,12 +142,12 @@ const CARD8 SiS6326TVRegs2_PAL[6][54] = {
0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
- {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
+ {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 640x480 */
0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
- {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
+ {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600 */
0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
@@ -150,9 +164,6 @@ const CARD8 SiS6326TVRegs2_PAL[6][54] = {
0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}
};
-const CARD8 SiS6326TVRegs1[14] = {
- 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43
-};
const CARD8 SiS6326CR[9][15] = {
{0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20}, /* PAL 800x600 */
@@ -195,329 +206,380 @@ SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
/* Save the registers for further processing */
(*pSiS->SiSSave)(pScrn, pReg);
- /* TW: Determine if chosen mode is suitable for TV on the 6326
- and if the mode is one of our special hi-res modes.
+ /* Determine if chosen mode is suitable for TV on the 6326
+ * and if the mode is one of our special hi-res modes.
*/
sis6326tvmode = FALSE;
sis6326himode = FALSE;
if(pSiS->Chipset == PCI_CHIP_SIS6326) {
- if(pSiS->SiS6326Flags & SIS6326_HASTV) {
- if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) &&
- ((strcmp(mode->name, "PAL800x600") == 0) || /* TW: Special TV modes */
- (strcmp(mode->name, "PAL800x600U") == 0) ||
- (strcmp(mode->name, "PAL720x540") == 0) ||
- (strcmp(mode->name, "PAL640x480") == 0) ||
- (strcmp(mode->name, "NTSC640x480") == 0) ||
- (strcmp(mode->name, "NTSC640x480U") == 0) ||
- (strcmp(mode->name, "NTSC640x400") == 0))) {
- sis6326tvmode = TRUE;
- } else {
- pReg->sis6326tv[0x00] &= 0xfb;
- }
- }
- if((strcmp(mode->name, "SIS1280x1024-75") == 0) || /* TW: Special high-res modes */
- (strcmp(mode->name, "SIS1600x1200-60") == 0)) {
- sis6326himode = TRUE;
- }
+ if(pSiS->SiS6326Flags & SIS6326_HASTV) {
+ if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) &&
+ ((strcmp(mode->name, "PAL800x600") == 0) || /* Special TV modes */
+ (strcmp(mode->name, "PAL800x600U") == 0) ||
+ (strcmp(mode->name, "PAL720x540") == 0) ||
+ (strcmp(mode->name, "PAL640x480") == 0) ||
+ (strcmp(mode->name, "NTSC640x480") == 0) ||
+ (strcmp(mode->name, "NTSC640x480U") == 0) ||
+ (strcmp(mode->name, "NTSC640x400") == 0))) {
+ sis6326tvmode = TRUE;
+ } else {
+ pReg->sis6326tv[0x00] &= 0xfb;
+ }
+ }
+ if((strcmp(mode->name, "SIS1280x1024-75") == 0) || /* Special high-res modes */
+ (strcmp(mode->name, "SIS1600x1200-60") == 0)) {
+ sis6326himode = TRUE;
+ }
}
#ifdef UNLOCK_ALWAYS
outSISIDXREG(SISSR, 0x05, 0x86);
#endif
- pReg->sisRegs3C4[0x06] &= 0x01;
+ if(!pSiS->UseVESA) {
+ pReg->sisRegs3C4[0x06] &= 0x01;
+ }
/* set interlace */
if(!(mode->Flags & V_INTERLACE)) {
- offset = pSiS->CurrentLayout.displayWidth >> 3;
+ offset = pSiS->CurrentLayout.displayWidth >> 3;
} else {
- offset = pSiS->CurrentLayout.displayWidth >> 2;
- pReg->sisRegs3C4[0x06] |= 0x20;
+ offset = pSiS->CurrentLayout.displayWidth >> 2;
+ if(!pSiS->UseVESA) {
+ pReg->sisRegs3C4[0x06] |= 0x20;
+ }
}
/* Enable Linear and Enhanced Gfx Mode */
- pReg->sisRegs3C4[0x06] |= 0x82;
+ if(!pSiS->UseVESA) {
+ pReg->sisRegs3C4[0x06] |= 0x82;
+ }
/* Enable MMIO at PCI Register 14H (D[6:5]: 11) */
- pReg->sisRegs3C4[0x0B] |= 0x60;
+ if(pSiS->oldChipset >= OC_SIS5597) {
+ pReg->sisRegs3C4[0x0B] |= 0x60;
+ } else {
+ pReg->sisRegs3C4[0x0B] |= 0x20;
+ pReg->sisRegs3C4[0x0B] &= ~0x40;
+ }
- /* Enable 32bit mem access (D7), read-ahead cache (D4) */
- pReg->sisRegs3C4[0x0C] |= 0xA0;
+ if(!pSiS->UseVESA) {
- /* TW: Some speed-up stuff */
- switch(pSiS->Chipset) {
- case PCI_CHIP_SIS5597:
- /* TW: enable host bus */
- if(pSiS->NoHostBus) {
- pReg->sisRegs3C4[0x34] &= ~0x08;
- } else {
- pReg->sisRegs3C4[0x34] |= 0x08;
- }
- /* TW: fall through */
- case PCI_CHIP_SIS6326:
- case PCI_CHIP_SIS530:
- /* TW: Enable "dual segment register mode" (D2) and "i/o gating while
- * write buffer is not empty" (D3)
- */
- pReg->sisRegs3C4[0x0B] |= 0x0C;
- }
+ /* Enable 32bit mem access (D7), read-ahead cache (D5) */
+ pReg->sisRegs3C4[0x0C] |= 0x80;
+ if(pSiS->oldChipset > OC_SIS6225) {
+ pReg->sisRegs3C4[0x0C] |= 0x20;
+ }
- /* set colordepth */
- if(pSiS->Chipset == PCI_CHIP_SIS530) {
- pReg->sisRegs3C4[0x09] &= 0x7F;
- }
- switch(pSiS->CurrentLayout.bitsPerPixel) {
- case 8:
- break;
- case 16:
- offset <<= 1;
- if(pSiS->CurrentLayout.depth == 15)
+ /* Some speed-up stuff */
+ switch(pSiS->Chipset) {
+ case PCI_CHIP_SIS5597:
+ /* enable host bus */
+ if(pSiS->NoHostBus) {
+ pReg->sisRegs3C4[0x34] &= ~0x08;
+ } else {
+ pReg->sisRegs3C4[0x34] |= 0x08;
+ }
+ /* fall through */
+ case PCI_CHIP_SIS6326:
+ case PCI_CHIP_SIS530:
+ /* Enable "dual segment register mode" (D2) and "i/o gating while
+ * write buffer is not empty" (D3)
+ */
+ pReg->sisRegs3C4[0x0B] |= 0x0C;
+ }
+
+ /* set colordepth */
+ if(pSiS->Chipset == PCI_CHIP_SIS530) {
+ pReg->sisRegs3C4[0x09] &= 0x7F;
+ }
+ switch(pSiS->CurrentLayout.bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ offset <<= 1;
+ if(pSiS->CurrentLayout.depth == 15)
pReg->sisRegs3C4[0x06] |= 0x04;
- else
+ else
pReg->sisRegs3C4[0x06] |= 0x08;
- break;
- case 24:
- offset += (offset << 1);
- pReg->sisRegs3C4[0x06] |= 0x10;
- pReg->sisRegs3C4[0x0B] |= 0x90;
- break;
- case 32:
- if(pSiS->Chipset == PCI_CHIP_SIS530) {
+ break;
+ case 24:
+ offset += (offset << 1);
+ pReg->sisRegs3C4[0x06] |= 0x10;
+ pReg->sisRegs3C4[0x0B] |= 0x90;
+ break;
+ case 32:
+ if(pSiS->Chipset == PCI_CHIP_SIS530) {
offset <<= 2;
- pReg->sisRegs3C4[0x06] |= 0x10;
+ if(pSiS->oldChipset != OC_SIS620) {
+ pReg->sisRegs3C4[0x06] |= 0x10;
+ }
pReg->sisRegs3C4[0x0B] |= 0x90;
pReg->sisRegs3C4[0x09] |= 0x80;
- } else return FALSE;
- break;
+ } else return FALSE;
+ break;
+ }
}
/* save screen pitch for acceleration functions */
pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth *
((pSiS->CurrentLayout.bitsPerPixel + 7) / 8);
- /* set linear framebuffer addresses */
- switch(pScrn->videoRam) {
- case 512:
- temp = 0x00; break;
- case 1024:
- temp = 0x20; break;
- case 2048:
- temp = 0x40; break;
- case 4096:
- temp = 0x60; break;
- case 8192:
- temp = 0x80; break;
- default:
- temp = 0x20;
- }
- pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19;
- pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp;
+ if(!pSiS->UseVESA) {
- /* Set screen offset */
- vgaReg->CRTC[0x13] = offset & 0xFF;
+ /* set linear framebuffer addresses */
+ switch(pScrn->videoRam) {
+ case 512: temp = 0x00; break;
+ case 1024: temp = 0x20; break;
+ case 2048: temp = 0x40; break;
+ case 4096: temp = 0x60; break;
+ case 8192: temp = 0x80; break;
+ default: temp = 0x20;
+ }
+ pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19;
+ pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp;
- /* Set CR registers for our built-in TV and hi-res modes */
- if((sis6326tvmode) || (sis6326himode)) {
+ /* Set screen offset */
+ vgaReg->CRTC[0x13] = offset & 0xFF;
- int index,i;
+ /* Set CR registers for our built-in TV and hi-res modes */
+ if((sis6326tvmode) || (sis6326himode)) {
- /* TW: We need our very private data for hi-res and TV modes */
- if(sis6326himode) {
- if(strcmp(mode->name, "SIS1280x1024-75") == 0) index = 7;
- else index = 8;
- } else {
- if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
- switch(width) {
- case 800:
- if((strcmp(mode->name, "PAL800x600U") == 0))
- index = 4;
- else
- index = 0;
- break;
- case 720:
- index = 5;
- break;
- case 640:
- default:
- index = 1;
- }
+ int index,i;
+
+ /* We need our very private data for hi-res and TV modes */
+ if(sis6326himode) {
+ if(strcmp(mode->name, "SIS1280x1024-75") == 0) index = 7;
+ else index = 8;
} else {
- switch(height) {
- case 400:
- index = 3;
- break;
- case 480:
- default:
- if((strcmp(mode->name, "NTSC640x480U") == 0))
- index = 6;
- else
- index = 2;
- }
+ if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
+ switch(width) {
+ case 800:
+ if((strcmp(mode->name, "PAL800x600U") == 0))
+ index = 4;
+ else
+ index = 0;
+ break;
+ case 720:
+ index = 5;
+ break;
+ case 640:
+ default:
+ index = 1;
+ }
+ } else {
+ switch(height) {
+ case 400:
+ index = 3;
+ break;
+ case 480:
+ default:
+ if((strcmp(mode->name, "NTSC640x480U") == 0))
+ index = 6;
+ else
+ index = 2;
+ }
+ }
+ }
+ for(i=0; i<=5; i++) {
+ vgaReg->CRTC[i] = SiS6326CR[index][i];
}
- }
- for(i=0; i<=5; i++) {
- vgaReg->CRTC[i] = SiS6326CR[index][i];
- }
- pReg->sisRegs3C4[0x12] = SiS6326CR[index][6];
- vgaReg->CRTC[6] = SiS6326CR[index][7];
- vgaReg->CRTC[7] = SiS6326CR[index][8];
- vgaReg->CRTC[0x10] = SiS6326CR[index][9];
- vgaReg->CRTC[0x11] = SiS6326CR[index][10];
- vgaReg->CRTC[0x12] = SiS6326CR[index][11];
- vgaReg->CRTC[0x15] = SiS6326CR[index][12];
- vgaReg->CRTC[0x16] = SiS6326CR[index][13];
- vgaReg->CRTC[9] &= ~0x20;
- vgaReg->CRTC[9] |= (SiS6326CR[index][14] & 0x20);
- pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f);
-
- } else {
-
- /* Set extended vertical overflow register */
- pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) |
- (((mode->CrtcVTotal-2) & 0x400) >> 10 ) |
- (((mode->CrtcVDisplay-1) & 0x400) >> 9 ) |
-/* (((mode->CrtcVSyncStart-1) & 0x400) >> 8 ) | */
- (((mode->CrtcVBlankStart-1)& 0x400) >> 8 ) |
-/* (((mode->CrtcVBlankStart-1)& 0x400) >> 7 ); */
- (((mode->CrtcVSyncStart) & 0x400) >> 7 );
-
- /* Set extended horizontal overflow register */
- pReg->sisRegs3C4[0x12] &= 0xE0;
- pReg->sisRegs3C4[0x12] |= (
- (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8 |
- (((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7 |
-/* (((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6 | */
- (((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 6 |
- ((mode->CrtcHSyncStart >> 3) & 0x100) >> 5 |
- (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 2);
- }
+ pReg->sisRegs3C4[0x12] = SiS6326CR[index][6];
+ vgaReg->CRTC[6] = SiS6326CR[index][7];
+ vgaReg->CRTC[7] = SiS6326CR[index][8];
+ vgaReg->CRTC[0x10] = SiS6326CR[index][9];
+ vgaReg->CRTC[0x11] = SiS6326CR[index][10];
+ vgaReg->CRTC[0x12] = SiS6326CR[index][11];
+ vgaReg->CRTC[0x15] = SiS6326CR[index][12];
+ vgaReg->CRTC[0x16] = SiS6326CR[index][13];
+ vgaReg->CRTC[9] &= ~0x20;
+ vgaReg->CRTC[9] |= (SiS6326CR[index][14] & 0x20);
+ pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f);
+
+ } else {
+
+ /* Set extended vertical overflow register */
+ pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) |
+ (((mode->CrtcVTotal-2) & 0x400) >> 10 ) |
+ (((mode->CrtcVDisplay-1) & 0x400) >> 9 ) |
+/* (((mode->CrtcVSyncStart-1) & 0x400) >> 8 ) | */
+ (((mode->CrtcVBlankStart-1)& 0x400) >> 8 ) |
+/* (((mode->CrtcVBlankStart-1)& 0x400) >> 7 ); */
+ (((mode->CrtcVSyncStart) & 0x400) >> 7 );
+
+ /* Set extended horizontal overflow register */
+ pReg->sisRegs3C4[0x12] &= 0xE0;
+ pReg->sisRegs3C4[0x12] |= (
+ (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8 |
+ (((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7 |
+/* (((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6 | */
+ (((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 6 |
+ ((mode->CrtcHSyncStart >> 3) & 0x100) >> 5 |
+ (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 2);
+ }
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "HDisplay %d HSyncStart %d HSyncEnd %d HTotal %d\n",
+ xf86DrvMsg(0, X_INFO, "HDisplay %d HSyncStart %d HSyncEnd %d HTotal %d\n",
mode->CrtcHDisplay, mode->CrtcHSyncStart,
mode->CrtcHSyncEnd, mode->CrtcHTotal);
- xf86DrvMsg(0, X_INFO, "HBlankSt %d HBlankE %d\n",
+ xf86DrvMsg(0, X_INFO, "HBlankSt %d HBlankE %d\n",
mode->CrtcHBlankStart, mode->CrtcHBlankEnd);
- xf86DrvMsg(0, X_INFO, "VDisplay %d VSyncStart %d VSyncEnd %d VTotal %d\n",
+ xf86DrvMsg(0, X_INFO, "VDisplay %d VSyncStart %d VSyncEnd %d VTotal %d\n",
mode->CrtcVDisplay, mode->CrtcVSyncStart,
mode->CrtcVSyncEnd, mode->CrtcVTotal);
- xf86DrvMsg(0, X_INFO, "VBlankSt %d VBlankE %d\n",
+ xf86DrvMsg(0, X_INFO, "VBlankSt %d VBlankE %d\n",
mode->CrtcVBlankStart, mode->CrtcVBlankEnd);
#endif
- /* enable (or disable) line compare */
- if(mode->CrtcVDisplay >= 1024)
- pReg->sisRegs3C4[0x38] |= 0x04;
- else
- pReg->sisRegs3C4[0x38] &= 0xFB;
-
- /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */
- if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) &&
- ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
- (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
- (pSiS->Flags & A6326REVAB) ) ) ||
- (pSiS->oldChipset > OC_SIS6326) ) {
- if( (pSiS->CurrentLayout.bitsPerPixel == 24) ||
- (pSiS->CurrentLayout.bitsPerPixel == 32) ||
- (mode->CrtcHDisplay >= 1280) )
- pReg->sisRegs3C4[0x3E] |= 0x01;
- else
- pReg->sisRegs3C4[0x3E] &= 0xFE;
- }
+ /* enable (or disable) line compare */
+ if(mode->CrtcVDisplay >= 1024)
+ pReg->sisRegs3C4[0x38] |= 0x04;
+ else
+ pReg->sisRegs3C4[0x38] &= 0xFB;
+
+ /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */
+ if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) &&
+ ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
+ (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
+ (pSiS->Flags & A6326REVAB) ) ) ||
+ (pSiS->oldChipset > OC_SIS6326) ) {
+ if( (pSiS->CurrentLayout.bitsPerPixel == 24) ||
+ (pSiS->CurrentLayout.bitsPerPixel == 32) ||
+ (mode->CrtcHDisplay >= 1280) )
+ pReg->sisRegs3C4[0x3E] |= 0x01;
+ else
+ pReg->sisRegs3C4[0x3E] &= 0xFE;
+ }
- /* We use the internal VCLK */
- pReg->sisRegs3C4[0x38] &= 0xFC;
+ /* We use the internal VCLK */
+ pReg->sisRegs3C4[0x38] &= 0xFC;
- /* Set VCLK */
- if((sis6326tvmode) || (sis6326himode)) {
- /* TW: For our built-in modes, the calculation is not suitable */
- if(sis6326himode) {
- if((strcmp(mode->name, "SIS1280x1024-75") == 0)) {
- pReg->sisRegs3C4[0x2A] = 0x5d; /* 1280x1024-75 */
- pReg->sisRegs3C4[0x2B] = 0xa4;
- } else {
- pReg->sisRegs3C4[0x2A] = 0x59; /* 1600x1200-60 */
- pReg->sisRegs3C4[0x2B] = 0xa3;
- }
- pReg->sisRegs3C4[0x13] &= ~0x40;
- } else {
- if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
- /* PAL: 31.500 Mhz */
- if((strcmp(mode->name, "PAL800x600U") == 0)) {
- pReg->sisRegs3C4[0x2A] = 0x46;
- pReg->sisRegs3C4[0x2B] = 0x49;
- } else {
- pReg->sisRegs3C4[0x2A] = 0xab;
- pReg->sisRegs3C4[0x2B] = 0xe9;
- }
- pReg->sisRegs3C4[0x13] &= ~0x40;
- } else {
- /* NTSC: 27.000 Mhz */
- if((strcmp(mode->name, "NTSC640x480U") == 0)) {
- pReg->sisRegs3C4[0x2A] = 0x5a;
- pReg->sisRegs3C4[0x2B] = 0x65;
- } else {
- pReg->sisRegs3C4[0x2A] = 0x29;
- pReg->sisRegs3C4[0x2B] = 0xe2;
- }
- pReg->sisRegs3C4[0x13] |= 0x40;
- }
- }
- } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) {
- pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ;
- pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0;
- pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f);
- pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5);
-
- /* When setting VCLK, we should set SR13 first */
- if(sbit)
- pReg->sisRegs3C4[0x13] |= 0x40;
- else
- pReg->sisRegs3C4[0x13] &= 0xBF;
+ /* Programmable Clock */
+ pReg->sisRegs3C2 = inb(SISMISCR) | 0x0C;
+
+ if(pSiS->oldChipset <= OC_SIS86202) {
+ /* TODO: Handle SR07 for clock selection */
+ /* 86C201 does not even have a programmable clock... */
+ /* pReg->sisRegs3C4[0x07] &= 0x??; */
+ }
+
+ /* Set VCLK */
+ if((sis6326tvmode) || (sis6326himode)) {
+
+ /* For our built-in modes, the calculation is not suitable */
+ if(sis6326himode) {
+ if((strcmp(mode->name, "SIS1280x1024-75") == 0)) {
+ pReg->sisRegs3C4[0x2A] = 0x5d; /* 1280x1024-75 */
+ pReg->sisRegs3C4[0x2B] = 0xa4;
+ } else {
+ pReg->sisRegs3C4[0x2A] = 0x59; /* 1600x1200-60 */
+ pReg->sisRegs3C4[0x2B] = 0xa3;
+ }
+ pReg->sisRegs3C4[0x13] &= ~0x40;
+ } else {
+ if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
+ /* PAL: 31.500 Mhz */
+ if((strcmp(mode->name, "PAL800x600U") == 0)) {
+ pReg->sisRegs3C4[0x2A] = 0x46;
+ pReg->sisRegs3C4[0x2B] = 0x49;
+ } else {
+ pReg->sisRegs3C4[0x2A] = 0xab;
+ pReg->sisRegs3C4[0x2B] = 0xe9;
+ }
+ pReg->sisRegs3C4[0x13] &= ~0x40;
+ } else {
+ /* NTSC: 27.000 Mhz */
+ if((strcmp(mode->name, "NTSC640x480U") == 0)) {
+ pReg->sisRegs3C4[0x2A] = 0x5a;
+ pReg->sisRegs3C4[0x2B] = 0x65;
+ } else {
+ pReg->sisRegs3C4[0x2A] = 0x29;
+ pReg->sisRegs3C4[0x2B] = 0xe2;
+ }
+ pReg->sisRegs3C4[0x13] |= 0x40;
+ }
+ }
+
+ } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) {
+
+ pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ;
+ pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0;
+ pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f);
+ pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5);
+
+ /* When setting VCLK, we should set SR13 first */
+ if(sbit)
+ pReg->sisRegs3C4[0x13] |= 0x40;
+ else
+ pReg->sisRegs3C4[0x13] &= 0xBF;
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n",
+ xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n",
pReg->sisRegs3C4[0x2A], pReg->sisRegs3C4[0x2B], pReg->sisRegs3C4[0x13], clock);
#endif
- } else {
- /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */
- SiSCalcClock(pScrn, clock, 2, vclk);
+ } else {
- pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f;
- pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7;
+ /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */
+ SiSCalcClock(pScrn, clock, 2, vclk);
- /* bits [4:0] contain denumerator */
- pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f;
+#define Midx 0
+#define Nidx 1
+#define VLDidx 2
+#define Pidx 3
+#define PSNidx 4
- if (vclk[Pidx] <= 4){
- /* postscale 1,2,3,4 */
- pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5;
- pReg->sisRegs3C4[0x13] &= 0xBF;
- } else {
- /* postscale 6,8 */
- pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5;
- pReg->sisRegs3C4[0x13] |= 0x40;
- }
- pReg->sisRegs3C4[0x2B] |= 0x80 ; /* gain for high frequency */
- }
+ pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f;
+ pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7;
- /* High speed DAC */
- if(clock > 135000)
- pReg->sisRegs3C4[0x07] |= 0x02;
+ /* bits [4:0] contain denumerator */
+ pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f;
- /* Programmable Clock */
- pReg->sisRegs3C2 = inb(SISMISCR) | 0x0C;
+ if(vclk[Pidx] <= 4){
+ /* postscale 1,2,3,4 */
+ pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5;
+ pReg->sisRegs3C4[0x13] &= 0xBF;
+ } else {
+ /* postscale 6,8 */
+ pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5;
+ pReg->sisRegs3C4[0x13] |= 0x40;
+ }
+ pReg->sisRegs3C4[0x2B] |= 0x80 ; /* gain for high frequency */
- /* 1 or 2 cycle DRAM (set by option FastVram) */
- if(pSiS->newFastVram == -1) {
- pReg->sisRegs3C4[0x34] |= 0x80;
- pReg->sisRegs3C4[0x34] &= ~0x40;
- } else if(pSiS->newFastVram == 1)
- pReg->sisRegs3C4[0x34] |= 0xC0;
- else
- pReg->sisRegs3C4[0x34] &= ~0xC0;
+ }
+
+ /* High speed DAC */
+ if(clock > 135000)
+ pReg->sisRegs3C4[0x07] |= 0x02;
+
+ if(pSiS->oldChipset > OC_SIS6225) {
+ /* 1 or 2 cycle DRAM (set by option FastVram) */
+ if(pSiS->newFastVram == -1) {
+ if(pSiS->oldChipset == OC_SIS620) {
+ /* Use different default on the 620 */
+ pReg->sisRegs3C4[0x34] |= 0x40;
+ pReg->sisRegs3C4[0x34] &= ~0x80;
+ } else {
+ pReg->sisRegs3C4[0x34] |= 0x80;
+ pReg->sisRegs3C4[0x34] &= ~0x40;
+ }
+ } else if(pSiS->newFastVram == 1)
+ pReg->sisRegs3C4[0x34] |= 0xC0;
+ else
+ pReg->sisRegs3C4[0x34] &= ~0xC0;
+
+ if(pSiS->oldChipset == OC_SIS620) {
+ /* Enable SGRAM burst timing (= bit clear) on the 620 */
+ if(pSiS->Flags & SYNCDRAM) {
+ pReg->sisRegs3C4[0x35] &= ~0x20;
+ } else {
+ pReg->sisRegs3C4[0x35] |= 0x20;
+ }
+ }
+ }
+
+ } /* VESA */
/* Logical line length */
pSiS->ValidWidth = TRUE;
@@ -547,254 +609,273 @@ SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
/* Acceleration stuff */
if(!pSiS->NoAccel) {
- pReg->sisRegs3C4[0x27] |= 0x40; /* Enable engine programming registers */
- if( (pSiS->TurboQueue) && /* Handle TurboQueue */
- ( (pSiS->Chipset != PCI_CHIP_SIS530) ||
- (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) {
- pReg->sisRegs3C4[0x27] |= 0x80; /* Enable TQ */
- if((pSiS->Chipset == PCI_CHIP_SIS530) ||
- ((pSiS->Chipset == PCI_CHIP_SIS6326 &&
- (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 ||
- pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 ||
- pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a ||
- pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b ||
- pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) {
- /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */
- pReg->sisRegs3C4[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */
- }
- /* TW: Locate the TQ at the beginning of the last 64K block of
- * video RAM. The address is to be specified in 32K steps.
- */
- pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32;
- if(pSiS->Chipset != PCI_CHIP_SIS530) { /* 530/620: Reserved (don't touch) */
- pReg->sisRegs3C4[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */
- } /* 5597: Must be 0 */
- } else {
- pReg->sisRegs3C4[0x27] &= 0x7F;
+ pReg->sisRegs3C4[0x27] |= 0x40; /* Enable engine programming registers */
+ if( (pSiS->TurboQueue) && /* Handle TurboQueue */
+ (pSiS->oldChipset > OC_SIS6225) &&
+ ( (pSiS->Chipset != PCI_CHIP_SIS530) ||
+ (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) {
+ pReg->sisRegs3C4[0x27] |= 0x80; /* Enable TQ */
+ if((pSiS->Chipset == PCI_CHIP_SIS530) ||
+ ((pSiS->Chipset == PCI_CHIP_SIS6326 &&
+ (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 ||
+ pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 ||
+ pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a ||
+ pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b ||
+ pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) {
+ /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */
+ pReg->sisRegs3C4[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */
}
+ /* Locate the TQ at the beginning of the last 64K block of
+ * video RAM. The address is to be specified in 32K steps.
+ */
+ pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32;
+ if(pSiS->Chipset != PCI_CHIP_SIS530) { /* 530/620: Reserved (don't touch) */
+ pReg->sisRegs3C4[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */
+ } /* 5597: Must be 0 */
+ } else {
+ pReg->sisRegs3C4[0x27] &= 0x7F;
+ }
}
- /* TW: No idea what this does. The Windows driver does it, so we do it as well */
- if(pSiS->Chipset == PCI_CHIP_SIS6326) {
- if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
- (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
- (pSiS->Flags & A6326REVAB)) {
- if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) {
- if(!(pReg->sisRegs3C4[0x0E] & 0x03)) {
- pReg->sisRegs3C4[0x3E] |= 0x02;
+
+ if(!pSiS->UseVESA) {
+
+ /* TW: No idea what this does. The Windows driver does it, so we do it as well */
+ if(pSiS->Chipset == PCI_CHIP_SIS6326) {
+ if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
+ (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
+ (pSiS->Flags & A6326REVAB)) {
+ if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) {
+ if(!(pReg->sisRegs3C4[0x0E] & 0x03)) {
+ pReg->sisRegs3C4[0x3E] |= 0x02;
+ }
}
- }
+ }
}
- }
-
- /* Set memclock */
+ /* Set memclock */
#if 0
- /* TW: We don't need to do this; the SetMClk option was not used since 4.0. */
- if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) {
- if(pSiS->MemClock > 66000) {
- SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk);
-
- pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ;
- pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ;
- pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */
- if(vclk[Pidx] <= 4) {
- pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */
- pReg->sisRegs3C4[0x13] &= 0x7F;
- } else {
- pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ; /* postscale 6,8 */
- pReg->sisRegs3C4[0x13] |= 0x80;
- }
- /* Check programmed memory clock. Enable only to check the above code */
+ /* We don't need to do this; the SetMClk option was not used since 4.0. */
+ if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) {
+ if(pSiS->MemClock > 66000) {
+ SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk);
+
+ pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ;
+ pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ;
+ pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */
+ if(vclk[Pidx] <= 4) {
+ pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */
+ pReg->sisRegs3C4[0x13] &= 0x7F;
+ } else {
+ pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ; /* postscale 6,8 */
+ pReg->sisRegs3C4[0x13] |= 0x80;
+ }
+ /* Check programmed memory clock. Enable only to check the above code */
/*
- mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1);
- mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1);
- if(!(pReg->sisRegs3C4[0x13] & 0x80)) {
- mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1);
- } else {
- if ((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6;
- if ((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8;
- }
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2,
+ mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1);
+ mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1);
+ if(!(pReg->sisRegs3C4[0x13] & 0x80)) {
+ mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1);
+ } else {
+ if((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6;
+ if((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2,
"Setting memory clock to %.3f MHz\n",
mclk/1000.0);
*/
- }
- }
+ }
+ }
#endif
- /* TW: set threshold values (rewritten) */
- /*
- * CPU/CRT Threshold: FIFO
- * MCLK ___________ VCLK
- * cpu/engine <---o o--------->|___________| -----------> CRT
- * ^ ^ ^ ^
- * \ / | |
- * \ / |< gap >|
- * \ / | |
- * selector switch Thrsh. low high
- *
- * CRT consumes the data in the FIFO during scanline display. When the
- * amount of data in the FIFO reaches the Threshold low value, the selector
- * switch will switch to the right, and the FIFO will be refilled with data.
- * When the amount of data in the FIFO reaches the Threshold high value, the
- * selector switch will switch to the left and allows the CPU and the chip
- * engines to access video RAM.
- *
- * The Threshold low values should be increased at higher bpps, simply because
- * there is more data needed for the CRT. When Threshold low and high are very
- * close to each other, the selector switch will be activated more often, which
- * decreases performance.
- *
- */
- switch(pSiS->Chipset) {
- case PCI_CHIP_SIS5597: factor = 65; break;
- case PCI_CHIP_SIS6326: factor = 30; break;
- case PCI_CHIP_SIS530: factor = (pSiS->Flags & UMA) ? 60 : 30; break;
- default: factor = (pScrn->videoRam > (1024*1024)) ? 24 : 12;
- }
- a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8);
- b = (mclk / 1000) * 999488.0 * (buswidth / 8);
- c = ((a / b) + 1.0) / 2;
- d = (int)c + 2;
+ /* Set threshold values */
+ /*
+ * CPU/CRT Threshold: FIFO
+ * MCLK ___________ VCLK
+ * cpu/engine <---o o--------->|___________| -----------> CRT
+ * ^ ^ ^ ^
+ * \ / | |
+ * \ / |< gap >|
+ * \ / | |
+ * selector switch Thrsh. low high
+ *
+ * CRT consumes the data in the FIFO during scanline display. When the
+ * amount of data in the FIFO reaches the Threshold low value, the selector
+ * switch will switch to the right, and the FIFO will be refilled with data.
+ * When the amount of data in the FIFO reaches the Threshold high value, the
+ * selector switch will switch to the left and allows the CPU and the chip
+ * engines to access the video RAM.
+ *
+ * The Threshold low values should be increased at higher bpps, simply because
+ * there is more data needed for the CRT. When Threshold low and high are very
+ * close to each other, the selector switch will be activated more often, which
+ * decreases performance.
+ *
+ */
+ switch(pSiS->Chipset) {
+ case PCI_CHIP_SIS5597: factor = 65; break;
+ case PCI_CHIP_SIS6326: factor = 30; break;
+ case PCI_CHIP_SIS530: factor = (pSiS->Flags & UMA) ? 60 : 30; break;
+ default: factor = (pScrn->videoRam > 1024) ? 24 : 12;
+ }
+ a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8);
+ b = (mclk / 1000) * 999488.0 * (buswidth / 8);
+ c = ((a / b) + 1.0) / 2;
+ d = (int)c + 2;
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO,
- "Debug: w %d h %d r %d mclk %d bus %d factor %d bpp %d\n",
- width, height, rate, mclk/1000, buswidth, factor,
- pSiS->CurrentLayout.bitsPerPixel);
- xf86DrvMsg(0, X_INFO, "Debug: a %f b %f c %f d %d (flags %x)\n",
- a, b, c, d, pSiS->Flags);
+ xf86DrvMsg(0, X_INFO,
+ "Debug: w %d h %d r %d mclk %d bus %d factor %d bpp %d\n",
+ width, height, rate, mclk/1000, buswidth, factor,
+ pSiS->CurrentLayout.bitsPerPixel);
+ xf86DrvMsg(0, X_INFO, "Debug: a %f b %f c %f d %d (flags %x)\n",
+ a, b, c, d, pSiS->Flags);
#endif
- CRT_CPUthresholdLow = d;
- if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) {
- CRT_CPUthresholdLow += 2;
- }
- CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3;
+ CRT_CPUthresholdLow = d;
+ if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) {
+ CRT_CPUthresholdLow += 2;
+ }
+ CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3;
- CRT_ENGthreshold = 0x0F;
+ CRT_ENGthreshold = 0x0F;
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "Debug: Thlow %d thhigh %d\n",
- CRT_CPUthresholdLow, CRT_CPUthresholdHigh);
+ xf86DrvMsg(0, X_INFO, "Debug: Thlow %d thhigh %d\n",
+ CRT_CPUthresholdLow, CRT_CPUthresholdHigh);
#endif
-#if 0 /* TW: See comment in sis_dac.c on why this is commented */
- if(pSiS->Chipset == PCI_CHIP_SIS530) {
- if((pSiS->oldChipset == OC_SIS530A) &&
- (pSiS->Flags & UMA) &&
- (mclk == 100000) &&
- (pSiS->Flags & ESS137xPRESENT)) {
- if(!(pSiS->Flags & SECRETFLAG)) index = 0;
- if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) {
- CRT_CPUthresholdLow = temp;
- break;
- }
+#if 0 /* See comment in sis_dac.c on why this is commented */
+ if(pSiS->Chipset == PCI_CHIP_SIS530) {
+ if((pSiS->oldChipset == OC_SIS530A) &&
+ (pSiS->Flags & UMA) &&
+ (mclk == 100000) &&
+ (pSiS->Flags & ESS137xPRESENT)) {
+ if(!(pSiS->Flags & SECRETFLAG)) index = 0;
+ if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) {
+ CRT_CPUthresholdLow = temp;
+ break;
+ }
+ }
}
- }
#endif
- switch(pSiS->Chipset) {
- case PCI_CHIP_SIS530:
- if(CRT_CPUthresholdLow > 0x1f) CRT_CPUthresholdLow = 0x1f;
- CRT_CPUthresholdHigh = 0x1f;
- break;
- case PCI_CHIP_SIS5597:
- case PCI_CHIP_SIS6326:
- default:
- if(CRT_CPUthresholdLow > 0x0f) CRT_CPUthresholdLow = 0x0f;
- if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f;
- }
+ switch(pSiS->Chipset) {
+ case PCI_CHIP_SIS530:
+ if(CRT_CPUthresholdLow > 0x1f) CRT_CPUthresholdLow = 0x1f;
+ CRT_CPUthresholdHigh = 0x1f;
+ break;
+ case PCI_CHIP_SIS5597:
+ case PCI_CHIP_SIS6326:
+ default:
+ if(CRT_CPUthresholdLow > 0x0f) CRT_CPUthresholdLow = 0x0f;
+ if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f;
+ }
- pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) |
- (CRT_ENGthreshold & 0x0F);
+ pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) |
+ (CRT_ENGthreshold & 0x0F);
- pReg->sisRegs3C4[0x09] &= 0xF0;
- pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F);
+ pReg->sisRegs3C4[0x09] &= 0xF0;
+ pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F);
- pReg->sisRegs3C4[0x3F] &= 0xEB;
- pReg->sisRegs3C4[0x3F] |= (CRT_CPUthresholdHigh & 0x10) |
- ((CRT_CPUthresholdLow & 0x10) >> 2);
+ pReg->sisRegs3C4[0x3F] &= 0xEB;
+ pReg->sisRegs3C4[0x3F] |= (CRT_CPUthresholdHigh & 0x10) |
+ ((CRT_CPUthresholdLow & 0x10) >> 2);
- if(pSiS->oldChipset >= OC_SIS530A) {
- pReg->sisRegs3C4[0x3F] &= 0xDF;
- pReg->sisRegs3C4[0x3F] |= 0x58;
- }
+ if(pSiS->oldChipset >= OC_SIS530A) {
+ pReg->sisRegs3C4[0x3F] &= 0xDF;
+ pReg->sisRegs3C4[0x3F] |= 0x58;
+ }
- /* TW: Set SiS6326 TV registers */
- if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) {
- unsigned char tmp;
- int index=0, i, j, k;
-
- if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
- pReg->sisRegs3C4[0x0D] |= 0x04;
- switch(width) {
- case 800:
- if((strcmp(mode->name, "PAL800x600U") == 0)) index = 4;
- else index = 3;
- break;
- case 720:
- index = 5;
- break;
- case 640:
- default:
- index = 2;
- break;
- }
- for(i=0; i<14; i++) {
- pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i];
- }
- } else {
- pReg->sisRegs3C4[0x0D] &= ~0x04;
- if((strcmp(mode->name, "NTSC640x480U") == 0)) index = 5;
- else index = 4;
- for(i=0; i<14; i++) {
- pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i];
- }
- }
- tmp = pReg->sis6326tv[0x43];
- if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10;
- tmp |= 0x08;
- pReg->sis6326tv[0x43] = tmp;
- j = 0; k = 0;
- for(i=0; i<=0x44; i++) {
- if(SiS6326TVRegs1[j] == i) {
+ /* Set SiS6326 TV registers */
+ if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) {
+ unsigned char tmp;
+ int index=0, i, j, k;
+ int fsc;
+
+ if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
+ pReg->sisRegs3C4[0x0D] |= 0x04;
+ switch(width) {
+ case 800:
+ if((strcmp(mode->name, "PAL800x600U") == 0)) index = 4;
+ else index = 3;
+ break;
+ case 720: index = 5; break;
+ case 640:
+ default: index = 2;
+ }
+ for(i=0; i<14; i++) {
+ pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i];
+ }
+#ifdef TV6326TEST
+ for(i=0, j=2; i<3; i++, j++) {
+ pReg->sis6326tv[j] = SiS6326TVRegs1_PAL_2[index][i];
+ }
+#endif
+ fsc = (SiS6326TVRegs1_PAL[index][2] << 16) |
+ (SiS6326TVRegs1_PAL[index][3] << 8) |
+ (SiS6326TVRegs1_PAL[index][4]);
+ } else {
+ pReg->sisRegs3C4[0x0D] &= ~0x04;
+ if((strcmp(mode->name, "NTSC640x480U") == 0)) index = 5;
+ else index = 4;
+ for(i=0; i<14; i++) {
+ pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i];
+ }
+#ifdef TV6326TEST
+ for(i=0, j=2; i<3; i++, j++) {
+ pReg->sis6326tv[j] = SiS6326TVRegs1_NTSC_2[index][i];
+ }
+#endif
+ fsc = (SiS6326TVRegs1_NTSC[index][2] << 16) |
+ (SiS6326TVRegs1_NTSC[index][3] << 8) |
+ (SiS6326TVRegs1_NTSC[index][4]);
+ }
+ if(pSiS->sis6326fscadjust) {
+ fsc += pSiS->sis6326fscadjust;
+ pReg->sis6326tv[2] = (fsc >> 16) & 0xff;
+ pReg->sis6326tv[3] = (fsc >> 8) & 0xff;
+ pReg->sis6326tv[4] = fsc & 0xff;
+ }
+ tmp = pReg->sis6326tv[0x43];
+ if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10;
+ tmp |= 0x08;
+ pReg->sis6326tv[0x43] = tmp;
+ j = 0; k = 0;
+ for(i=0; i<=0x44; i++) {
+ if(SiS6326TVRegs1[j] == i) {
j++;
continue;
- }
- if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
+ }
+ if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
tmp = SiS6326TVRegs2_PAL[index][k];
- } else {
+ } else {
tmp = SiS6326TVRegs2_NTSC[index][k];
- }
- pReg->sis6326tv[i] = tmp;
- k++;
- }
- pReg->sis6326tv[0x43] |= 0x08;
- if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) {
- pReg->sis6326tv[0x43] &= ~0x08;
- }
-
- tmp = pReg->sis6326tv[0];
- tmp |= 0x18;
- if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp &= ~0x10;
- else tmp &= ~0x08;
- tmp |= 0x04;
- pReg->sis6326tv[0] = tmp;
- }
+ }
+ pReg->sis6326tv[i] = tmp;
+ k++;
+ }
+ pReg->sis6326tv[0x43] |= 0x08;
+ if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) {
+ pReg->sis6326tv[0x43] &= ~0x08;
+ }
+
+ tmp = pReg->sis6326tv[0];
+ tmp |= 0x18;
+ if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp &= ~0x10;
+ if(pSiS->SiS6326Flags & SIS6326_TVSVIDEO) tmp &= ~0x08;
+ tmp |= 0x04;
+ pReg->sis6326tv[0] = tmp;
+ }
+
+ } /* VESA */
return(TRUE);
}
-/* TW: Init a mode for SiS 300 and 310/325 series
- * The original intention of the followling procedure was
- * to initialize various registers for the selected mode.
- * This was actually done to a structure, not the hardware.
- * (SiSRestore would write the structure to the hardware
- * registers.)
- * This function is now only used for setting up some
- * variables (eg. scrnOffset).
+/* Init a mode for SiS 300, 315 and 330 series
+ * This function is now only used for setting up some
+ * variables (eg. scrnOffset).
*/
Bool
SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
@@ -802,22 +883,33 @@ SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
SISPtr pSiS = SISPTR(pScrn);
SISRegPtr pReg = &pSiS->ModeReg;
unsigned short temp;
+ DisplayModePtr realmode = mode;
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n");
+ PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n"));
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
"virtualX = %d depth = %d Logical width = %d\n",
pScrn->virtualX, pSiS->CurrentLayout.bitsPerPixel,
pScrn->virtualX * pSiS->CurrentLayout.bitsPerPixel/8);
+#ifdef SISMERGED
+ if(pSiS->MergedFB) {
+ realmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
+ }
+#endif
+
/* Copy current register settings to structure */
(*pSiS->SiSSave)(pScrn, pReg);
- /* TW: Calculate Offset/Display Pitch */
+ /* Calculate Offset/Display Pitch */
pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth *
- ((pSiS->CurrentLayout.bitsPerPixel+7)/8);
- pSiS->scrnPitch = pSiS->scrnOffset;
- if (mode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1;
+ ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8);
+
+ pSiS->scrnPitch = pSiS->scrnPitch2 = pSiS->scrnOffset;
+ if(!(pSiS->VBFlags & CRT1_LCDA)) {
+ if(realmode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1;
+ }
+ /* CRT2 mode can never be interlaced */
#ifdef UNLOCK_ALWAYS
outSISIDXREG(SISSR, 0x05, 0x86);
@@ -843,30 +935,32 @@ SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
break;
}
- /* TW: Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */
+ /* Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */
pReg->sisRegs3C4[0x20] = 0xA1;
-/* TW: Now initialize TurboQueue. TB is always located at the very top of
- * the videoRAM (notably NOT the x framebuffer memory, which can/should
- * be limited by MaxXFbMem when using DRI). Also, enable the accelerators.
- */
- if (!pSiS->NoAccel) {
- pReg->sisRegs3C4[0x1E] |= 0x42; /* TW: Enable 2D accelerator */
- pReg->sisRegs3C4[0x1E] |= 0x18; /* TW: Enable 3D accelerator */
- switch (pSiS->VGAEngine) {
+ /* Now initialize TurboQueue. TB is always located at the very top of
+ * the videoRAM (notably NOT the x framebuffer memory, which can/should
+ * be limited by MaxXFbMem when using DRI). Also, enable the accelerators.
+ */
+ if(!pSiS->NoAccel) {
+ pReg->sisRegs3C4[0x1E] |= 0x42; /* Enable 2D accelerator */
+ pReg->sisRegs3C4[0x1E] |= 0x18; /* Enable 3D accelerator */
+ switch(pSiS->VGAEngine) {
case SIS_300_VGA:
- if(pSiS->TurboQueue) { /* set Turbo Queue as 512k */
- temp = ((pScrn->videoRam/64)-8); /* TW: 8=512k, 4=256k, 2=128k, 1=64k */
+ if(pSiS->TurboQueue) { /* set Turbo Queue as 512k */
+ temp = ((pScrn->videoRam/64)-8); /* 8=512k, 4=256k, 2=128k, 1=64k */
pReg->sisRegs3C4[0x26] = temp & 0xFF;
pReg->sisRegs3C4[0x27] =
(pReg->sisRegs3C4[0x27] & 0xfc) | (((temp >> 8) & 3) | 0xF0);
- } /* TW: line above new for saving D2&3 of status register */
+ } /* line above new for saving D2&3 of status register */
break;
case SIS_315_VGA:
+#ifndef SISVRAMQ
/* See comments in sis_driver.c */
pReg->sisRegs3C4[0x27] = 0x1F;
pReg->sisRegs3C4[0x26] = 0x22;
pReg->sisMMIO85C0 = (pScrn->videoRam - 512) * 1024;
+#endif
break;
}
}
@@ -874,7 +968,7 @@ SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
return(TRUE);
}
-int
+static int
SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch)
{
SISPtr pSiS = SISPTR(pScrn);
@@ -883,199 +977,218 @@ SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch)
outSISIDXREG(SISPART4,0x11,tempbl);
temp = tempbh | tempcl;
setSISIDXREG(SISPART4,0x10,0xe0,temp);
- usleep(200000);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x1000);
tempch &= 0x7f;
inSISIDXREG(SISPART4,0x03,temp);
temp ^= 0x0e;
temp &= tempch;
- return(temp);
+ return((temp == tempch));
}
-/* TW: Sense connected devices on 30x */
-void SISSense30x(ScrnInfoPtr pScrn)
+/* Sense connected devices on 30x */
+static void
+SISSense30x(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- unsigned char backupP4_0d,biosflag;
- unsigned char testsvhs_tempbl, testsvhs_tempbh;
- unsigned char testsvhs_tempcl, testsvhs_tempch;
- unsigned char testcvbs_tempbl, testcvbs_tempbh;
- unsigned char testcvbs_tempcl, testcvbs_tempch;
- unsigned char testvga2_tempbl, testvga2_tempbh;
- unsigned char testvga2_tempcl, testvga2_tempch;
- int myflag, result;
+ unsigned char backupP4_0d,backupP2_00,biosflag;
+ unsigned char svhs_bl, svhs_bh;
+ unsigned char svhs_cl, svhs_ch;
+ unsigned char cvbs_bl, cvbs_bh;
+ unsigned char cvbs_cl, cvbs_ch;
+ unsigned char vga2_bl, vga2_bh;
+ unsigned char vga2_cl, vga2_ch;
+ int myflag, result=0, i, j;
unsigned short temp;
inSISIDXREG(SISPART4,0x0d,backupP4_0d);
outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(pSiS->sishw_ext.UseROM) {
- temp = 0xf3;
- if(pSiS->Chipset == PCI_CHIP_SIS330) temp = 0x11b;
- if(pSiS->BIOS[temp] & 0x08) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "SiS30x: Video bridge has (unsupported) DVI combo connector\n");
- orSISIDXREG(SISCR, 0x32, 0x80);
- } else {
- andSISIDXREG(SISCR, 0x32, 0x7f);
- }
+ inSISIDXREG(SISPART2,0x00,backupP2_00);
+ outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
+
+ SISDoSense(pScrn, 0, 0, 0, 0);
+
+ if(pSiS->Chipset != PCI_CHIP_SIS660) {
+ if((pSiS->VGAEngine == SIS_315_VGA) ||
+ (pSiS->Chipset == PCI_CHIP_SIS300)) {
+ if(pSiS->sishw_ext.UseROM) {
+ if(pSiS->VGAEngine == SIS_300_VGA) temp = 0xfe;
+ else if(pSiS->Chipset == PCI_CHIP_SIS330) temp = 0x11b;
+ else temp = 0xf3;
+ if(pSiS->BIOS[temp] & 0x08) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Video bridge has DVI-I TMDS/VGA combo connector\n");
+ orSISIDXREG(SISCR, 0x32, 0x80);
+ } else {
+ andSISIDXREG(SISCR, 0x32, 0x7f);
+ }
+ }
}
}
if(pSiS->VGAEngine == SIS_300_VGA) {
if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xf9]; testvga2_tempbl = pSiS->BIOS[0xf8];
- testsvhs_tempbh = pSiS->BIOS[0xfb]; testsvhs_tempbl = pSiS->BIOS[0xfa];
- testcvbs_tempbh = pSiS->BIOS[0xfd]; testcvbs_tempbl = pSiS->BIOS[0xfc];
+ vga2_bh = pSiS->BIOS[0xf9]; vga2_bl = pSiS->BIOS[0xf8];
+ svhs_bh = pSiS->BIOS[0xfb]; svhs_bl = pSiS->BIOS[0xfa];
+ cvbs_bh = pSiS->BIOS[0xfd]; cvbs_bl = pSiS->BIOS[0xfc];
biosflag = pSiS->BIOS[0xfe];
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
- biosflag = 0;
+ vga2_bh = 0x00; vga2_bl = 0xd1;
+ svhs_bh = 0x00; svhs_bl = 0xb9;
+ cvbs_bh = 0x00; cvbs_bl = 0xb3;
+ biosflag = 2;
}
- if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x74;
}
inSISIDXREG(SISPART4,0x01,myflag);
if(myflag & 0x04) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+ vga2_bh = 0x00; vga2_bl = 0xfd;
+ svhs_bh = 0x00; svhs_bl = 0xdd;
+ cvbs_bh = 0x00; cvbs_bl = 0xee;
+ }
+ vga2_ch = 0x0e; vga2_cl = 0x08;
+ svhs_ch = 0x04; svhs_cl = 0x04;
+ cvbs_ch = 0x08; cvbs_cl = 0x04;
+
+ if(pSiS->Chipset == PCI_CHIP_SIS300) {
+ inSISIDXREG(SISSR,0x3b,myflag);
+ if(!(myflag & 0x01)) {
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
+ }
}
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
- } else if((pSiS->Chipset == PCI_CHIP_SIS315) ||
- (pSiS->Chipset == PCI_CHIP_SIS315H) ||
- (pSiS->Chipset == PCI_CHIP_SIS315PRO)) {
+ } else if(pSiS->Chipset == PCI_CHIP_SIS660) {
- if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xbe]; testvga2_tempbl = pSiS->BIOS[0xbd];
- testsvhs_tempbh = pSiS->BIOS[0xc0]; testsvhs_tempbl = pSiS->BIOS[0xbf];
- testcvbs_tempbh = pSiS->BIOS[0xc2]; testcvbs_tempbl = pSiS->BIOS[0xc1];
- biosflag = pSiS->BIOS[0xf3];
+ if(pSiS->sishw_ext.UseROM) {
+ biosflag = pSiS->BIOS[0x58];
+ temp = pSiS->BIOS[0x254] | (pSiS->BIOS[0x255] << 8);
+ if(pSiS->VBFlags & VB_301) temp += 6;
+ else if(pSiS->VBFlags & VB_301B) temp += 12;
+ else if(pSiS->VBFlags & VB_301C) temp += 18;
+ else if(pSiS->VBFlags & VB_301LV) temp += 12;
+ else if(pSiS->VBFlags & VB_302LV) temp += 12;
+ else if(pSiS->VBFlags & VB_302ELV) temp += 18;
+ vga2_bh = pSiS->BIOS[temp+1]; vga2_bl = pSiS->BIOS[temp];
+ svhs_bh = pSiS->BIOS[temp+3]; svhs_bl = pSiS->BIOS[temp+2];
+ cvbs_bh = pSiS->BIOS[temp+5]; cvbs_bl = pSiS->BIOS[temp+4];
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
- biosflag = 0;
- }
- if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) {
- if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xc4]; testvga2_tempbl = pSiS->BIOS[0xc3];
- testsvhs_tempbh = pSiS->BIOS[0xc6]; testsvhs_tempbl = pSiS->BIOS[0xc5];
- testcvbs_tempbh = pSiS->BIOS[0xc8]; testcvbs_tempbl = pSiS->BIOS[0xc7];
+ biosflag = 2;
+ if(pSiS->VBFlags & (VB_301B | VB_301LV | VB_302LV)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b; /* Are these really correct for LV? */
+ cvbs_bh = 0x01; cvbs_bl = 0x74;
+ } else if(pSiS->VBFlags & (VB_301C | VB_302ELV)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x10;
} else {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ vga2_bh = 0x00; vga2_bl = 0xfd;
+ svhs_bh = 0x00; svhs_bl = 0xdd;
+ cvbs_bh = 0x00; cvbs_bl = 0xee;
}
}
- inSISIDXREG(SISPART4,0x01,myflag);
- if(myflag & 0x04) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+
+ vga2_ch = 0x0e; vga2_cl = 0x08;
+ svhs_ch = 0x04; svhs_cl = 0x04;
+ cvbs_ch = 0x08; cvbs_cl = 0x04;
+
+ if(pSiS->VBFlags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
+ svhs_ch = 0x04; svhs_cl = 0x08;
+ cvbs_ch = 0x08; cvbs_cl = 0x08;
}
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
- } else if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ } else {
if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xe6]; testvga2_tempbl = pSiS->BIOS[0xe5];
- testsvhs_tempbh = pSiS->BIOS[0xe8]; testsvhs_tempbl = pSiS->BIOS[0xe7];
- testcvbs_tempbh = pSiS->BIOS[0xea]; testcvbs_tempbl = pSiS->BIOS[0xe9];
- biosflag = pSiS->BIOS[0x11b];
+ if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ vga2_bh = pSiS->BIOS[0xe6]; vga2_bl = pSiS->BIOS[0xe5];
+ svhs_bh = pSiS->BIOS[0xe8]; svhs_bl = pSiS->BIOS[0xe7];
+ cvbs_bh = pSiS->BIOS[0xea]; cvbs_bl = pSiS->BIOS[0xe9];
+ biosflag = pSiS->BIOS[0x11b];
+ } else {
+ vga2_bh = pSiS->BIOS[0xbe]; vga2_bl = pSiS->BIOS[0xbd];
+ svhs_bh = pSiS->BIOS[0xc0]; svhs_bl = pSiS->BIOS[0xbf];
+ cvbs_bh = pSiS->BIOS[0xc2]; cvbs_bl = pSiS->BIOS[0xc1];
+ biosflag = pSiS->BIOS[0xf3];
+ }
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
- biosflag = 0;
+ vga2_bh = 0x00; vga2_bl = 0xd1;
+ svhs_bh = 0x00; svhs_bl = 0xb9;
+ cvbs_bh = 0x00; cvbs_bl = 0xb3;
+ biosflag = 2;
}
- if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) {
+
+ if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) {
if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xec]; testvga2_tempbl = pSiS->BIOS[0xeb];
- testsvhs_tempbh = pSiS->BIOS[0xee]; testsvhs_tempbl = pSiS->BIOS[0xed];
- testcvbs_tempbh = pSiS->BIOS[0xf0]; testcvbs_tempbl = pSiS->BIOS[0xef];
+ if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ vga2_bh = pSiS->BIOS[0xec]; vga2_bl = pSiS->BIOS[0xeb];
+ svhs_bh = pSiS->BIOS[0xee]; svhs_bl = pSiS->BIOS[0xed];
+ cvbs_bh = pSiS->BIOS[0xf0]; cvbs_bl = pSiS->BIOS[0xef];
+ } else {
+ vga2_bh = pSiS->BIOS[0xc4]; vga2_bl = pSiS->BIOS[0xc3];
+ svhs_bh = pSiS->BIOS[0xc6]; svhs_bl = pSiS->BIOS[0xc5];
+ cvbs_bh = pSiS->BIOS[0xc8]; cvbs_bl = pSiS->BIOS[0xc7];
+ }
} else {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ if(pSiS->VBFlags & (VB_301B|VB_301C|VB_302B)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x74;
+ } else {
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ svhs_bh = 0x02; svhs_bl = 0x00;
+ cvbs_bh = 0x01; cvbs_bl = 0x00;
+ }
}
}
- inSISIDXREG(SISPART4,0x01,myflag);
- if(myflag & 0x04) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+
+ if(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)) {
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(myflag & 0x04) {
+ vga2_bh = 0x00; vga2_bl = 0xfd;
+ svhs_bh = 0x00; svhs_bl = 0xdd;
+ cvbs_bh = 0x00; cvbs_bl = 0xee;
+ }
}
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
-
- } else { /* 550?, 650, 740 */
-
- if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xbe]; testvga2_tempbl = pSiS->BIOS[0xbd];
- testsvhs_tempbh = pSiS->BIOS[0xc0]; testsvhs_tempbl = pSiS->BIOS[0xbf];
- testcvbs_tempbh = pSiS->BIOS[0xc2]; testcvbs_tempbl = pSiS->BIOS[0xc1];
- biosflag = pSiS->BIOS[0xf3];
+
+ if(pSiS->VBFlags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ /* TW: No VGA2 or SCART on LV bridges */
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
+ svhs_ch = 0x04; svhs_cl = 0x08;
+ cvbs_ch = 0x08; cvbs_cl = 0x08;
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
- biosflag = 0;
- }
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
-
- /* TW: Different BIOS versions use different values for the 301LV.
- These values are from the newest versions 1.10.6? and 1.10.7?.
- I have no idea if these values are suitable for the 301B as well.
- */
-
- if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) {
- if(pSiS->sishw_ext.UseROM) {
- testvga2_tempbh = pSiS->BIOS[0xc4]; testvga2_tempbl = pSiS->BIOS[0xc3];
- testsvhs_tempbh = pSiS->BIOS[0xc6]; testsvhs_tempbl = pSiS->BIOS[0xc5];
- testcvbs_tempbh = pSiS->BIOS[0xc8]; testcvbs_tempbl = pSiS->BIOS[0xc7];
- biosflag = pSiS->BIOS[0xf3];
- } else {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
- biosflag = 0;
- }
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
+ vga2_ch = 0x0e; vga2_cl = 0x08;
+ svhs_ch = 0x04; svhs_cl = 0x04;
+ cvbs_ch = 0x08; cvbs_cl = 0x04;
}
- }
-
- /* TW: No VGA2 or SCART on LV bridges */
- if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) {
- testvga2_tempbh = testvga2_tempbl = 0x00;
- testvga2_tempch = testvga2_tempcl = 0x00;
- }
+ }
- if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
+ andSISIDXREG(SISCR, 0x32, ~0x14);
+ pSiS->postVBCR32 &= ~0x14;
+ if(vga2_ch || vga2_cl || vga2_bh || vga2_bl) {
#ifdef TWDEBUG
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"SiS30x: Scanning for VGA2/SCART (%x %x %x %x)\n",
- testvga2_tempbh, testvga2_tempbl, testvga2_tempch, testvga2_tempcl);
+ vga2_bh, vga2_bl, vga2_ch, vga2_cl);
#endif
- result = SISDoSense(pScrn, testvga2_tempbl, testvga2_tempbh,
- testvga2_tempcl, testvga2_tempch);
+ for(j = 0; j < 10; j++) {
+ result = 0;
+ for(i = 0; i < 3; i++) {
+ if(SISDoSense(pScrn, vga2_bl, vga2_bh, vga2_cl, vga2_ch))
+ result++;
+ }
+ if((result == 0) || (result >= 2)) break;
+ }
if(result) {
if(biosflag & 0x01) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
@@ -1083,7 +1196,7 @@ void SISSense30x(ScrnInfoPtr pScrn)
pSiS->VBFlags |= TV_SCART;
orSISIDXREG(SISCR, 0x32, 0x04);
pSiS->postVBCR32 |= 0x04;
- } else if(!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX))) {
+ } else {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS30x: Detected secondary VGA connection\n");
pSiS->VBFlags |= VGA2_CONNECTED;
@@ -1091,41 +1204,61 @@ void SISSense30x(ScrnInfoPtr pScrn)
pSiS->postVBCR32 |= 0x10;
}
}
+ if(biosflag & 0x01) pSiS->SiS_SD_Flags |= SiS_SD_VBHASSCART;
}
#ifdef TWDEBUG
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"SiS30x: Scanning for TV (%x %x %x %x; %x %x %x %x)\n",
- testsvhs_tempbh, testsvhs_tempbl, testsvhs_tempch, testsvhs_tempcl,
- testcvbs_tempbh, testcvbs_tempbl, testcvbs_tempch, testcvbs_tempcl);
+ svhs_bh, svhs_bl, svhs_ch, svhs_cl,
+ cvbs_bh, cvbs_bl, cvbs_ch, cvbs_cl);
#endif
- result = SISDoSense(pScrn, testsvhs_tempbl, testsvhs_tempbh,
- testsvhs_tempcl, testsvhs_tempch);
+ andSISIDXREG(SISCR, 0x32, ~0x03);
+ pSiS->postVBCR32 &= ~0x03;
+
+ if(pSiS->VBFlags & (VB_301C | VB_302ELV)) {
+ orSISIDXREG(SISPART4,0x0d,0x04);
+ }
+
+ for(j = 0; j < 10; j++) {
+ result = 0;
+ for(i = 0; i < 3; i++) {
+ if(SISDoSense(pScrn, svhs_bl, svhs_bh, svhs_cl, svhs_ch))
+ result++;
+ }
+ if((result == 0) || (result >= 2)) break;
+ }
if(result) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "SiS30x: Detected TV connected to SVIDEO output\n");
- /* TW: So we can be sure that there IS a SVIDEO output */
- pSiS->VBFlags |= TV_SVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x02);
- pSiS->postVBCR32 |= 0x02;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected TV connected to SVIDEO output\n");
+ pSiS->VBFlags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
+ pSiS->postVBCR32 |= 0x02;
}
if((biosflag & 0x02) || (!(result))) {
- result = SISDoSense(pScrn, testcvbs_tempbl, testcvbs_tempbh,
- testcvbs_tempcl, testcvbs_tempch);
- if(result) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ for(j = 0; j < 10; j++) {
+ result = 0;
+ for(i = 0; i < 3; i++) {
+ if(SISDoSense(pScrn, cvbs_bl, cvbs_bh, cvbs_cl, cvbs_ch))
+ result++;
+ }
+ if((result == 0) || (result >= 2)) break;
+ }
+ if(result) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS30x: Detected TV connected to COMPOSITE output\n");
- /* TW: So we can be sure that there IS a CVBS output */
- pSiS->VBFlags |= TV_AVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x01);
- pSiS->postVBCR32 |= 0x01;
- }
+ pSiS->VBFlags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
+ pSiS->postVBCR32 |= 0x01;
+ }
}
+
SISDoSense(pScrn, 0, 0, 0, 0);
+ outSISIDXREG(SISPART2,0x00,backupP2_00);
outSISIDXREG(SISPART4,0x0d,backupP4_0d);
}
@@ -1139,9 +1272,10 @@ SiS6326TVDelay(ScrnInfoPtr pScrn, int delay)
for(i=0; i<delay; i++) {
inSISIDXREG(SISSR, 0x05, temp);
}
+ (void)temp;
}
-int
+static int
SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl)
{
unsigned char temp;
@@ -1161,7 +1295,7 @@ SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl
return(tempcl);
}
-void
+static void
SISSense6326(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
@@ -1183,22 +1317,29 @@ SISSense6326(ScrnInfoPtr pScrn)
pSiS->SiS6326Flags |= SIS6326_TVDETECTED;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS6326: Detected TV connected to %s output\n",
- (pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ?
- "SVIDEO" : "COMPOSITE");
+ (((pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ==
+ (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ?
+ "both SVIDEO and COMPOSITE" :
+ ((pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ?
+ "SVIDEO" : "COMPOSITE")));
} else {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS6326: No TV detected\n");
}
}
-/* TW: Detect video bridge and set VBFlags accordingly */
+/* Detect video bridge and set VBFlags accordingly */
void SISVGAPreInit(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- int temp,temp1,temp2;
+ int temp,temp1,temp2, i;
int upperlimitlvds, lowerlimitlvds;
int upperlimitch, lowerlimitch;
- int chronteltype, chrontelidreg;
+ int chronteltype, chrontelidreg, upperlimitvb;
+ unsigned char test[3];
+#if 0
+ unsigned char sr17=0;
+#endif
static const char *ChrontelTypeStr[] = {
"7004",
"7005",
@@ -1221,6 +1362,7 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
case PCI_CHIP_SIS315H:
case PCI_CHIP_SIS315PRO:
case PCI_CHIP_SIS330:
+ case PCI_CHIP_SIS660:
pSiS->ModeInit = SIS300Init;
break;
default:
@@ -1237,33 +1379,53 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
}
pSiS->VBFlags = 0; /* reset VBFlags */
+ pSiS->SiS_Pr->SiS_UseLCDA = FALSE;
+ pSiS->SiS_Pr->Backup = FALSE;
- /* TW: Videobridges only available for 300/310/325 series */
+ /* Videobridges only available for 300/315 series */
if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA))
return;
-
+
inSISIDXREG(SISPART4, 0x00, temp);
temp &= 0x0F;
- if (temp == 1) {
+ if(temp == 1) {
inSISIDXREG(SISPART4, 0x01, temp1);
temp1 &= 0xff;
- if (temp1 >= 0xE0) {
- pSiS->VBFlags |= VB_30xLVX;
- pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LVX;
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS301LVX video bridge (Revision 0x%x)\n",
+ if(temp1 >= 0xE0) {
+ inSISIDXREG(SISPART4, 0x39, temp2);
+ if(temp2 == 0xff) {
+ pSiS->VBFlags |= VB_302LV;
+ pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected SiS302LV video bridge (ID 1; Revision 0x%x)\n",
+ temp1);
+ } else {
+ pSiS->VBFlags |= VB_302ELV;
+ pSiS->sishw_ext.ujVBChipID = VB_CHIP_302ELV;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected SiS302ELV video bridge (ID 1; Revision 0x%x)\n",
temp1);
- } else if (temp1 >= 0xD0) {
- pSiS->VBFlags |= VB_30xLV;
+ }
+ } else if(temp1 >= 0xD0) {
+ pSiS->VBFlags |= VB_301LV;
pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LV;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS301LV video bridge (Revision 0x%x)\n",
+ "Detected SiS301LV video bridge (ID 1; Revision 0x%x)\n",
+ temp1);
+ } else if(temp1 >= 0xC0) {
+ pSiS->VBFlags |= VB_301C;
+ pSiS->sishw_ext.ujVBChipID = VB_CHIP_301C;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected SiS301C video bridge (ID 1; Revision 0x%x)\n",
temp1);
- } else if (temp1 >= 0xB0) {
+ } else if(temp1 >= 0xB0) {
pSiS->VBFlags |= VB_301B;
pSiS->sishw_ext.ujVBChipID = VB_CHIP_301B;
+ inSISIDXREG(SISPART4, 0x23, temp2);
+ if(!(temp2 & 0x02)) pSiS->VBFlags |= VB_30xBDH;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS301B video bridge (Revision 0x%x)\n",
+ "Detected SiS301B%s video bridge (Revision 0x%x)\n",
+ (temp2 & 0x02) ? "" : " (DH)",
temp1);
} else {
pSiS->VBFlags |= VB_301;
@@ -1272,113 +1434,88 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
"Detected SiS301 video bridge (Revision 0x%x)\n",
temp1);
}
- if (pSiS->VBFlags & (VB_30xLV | VB_30xLVX)) {
- inSISIDXREG(SISCR, 0x38, temp);
- if((temp & 0x03) == 0x03) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "[SiS301LV/LVX: LCD channel A]\n");
- }
- }
- SISSense30x(pScrn);
+ SISSense30x(pScrn);
} else if (temp == 2) {
inSISIDXREG(SISPART4, 0x01, temp1);
temp1 &= 0xff;
- if (temp1 >= 0xE0) {
- pSiS->VBFlags |= VB_30xLVX;
- pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LVX;
+ if(temp1 >= 0xE0) {
+ pSiS->VBFlags |= VB_302LV;
+ pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS302LVX video bridge (Revision 0x%x)\n",
+ "Detected SiS302LV video bridge (ID 2; Revision 0x%x)\n",
temp1);
- } else if (temp1 >= 0xD0) {
- pSiS->VBFlags |= VB_30xLV;
- pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV;
+ } else if(temp1 >= 0xD0) {
+ pSiS->VBFlags |= VB_301LV;
+ pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LV;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS302LV video bridge (Revision 0x%x)\n",
+ "Detected SiS301LV video bridge (ID 2; Revision 0x%x)\n",
temp1);
} else {
pSiS->VBFlags |= VB_302B;
pSiS->sishw_ext.ujVBChipID = VB_CHIP_302B;
+ inSISIDXREG(SISPART4, 0x23, temp2);
+ if(!(temp & 0x02)) pSiS->VBFlags |= VB_30xBDH;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS302B video bridge (Revision 0x%x)\n",
+ "Detected SiS302B%s video bridge (Revision 0x%x)\n",
+ (temp2 & 0x02) ? "" : " (DH)",
temp1);
}
- if (pSiS->VBFlags & (VB_302B | VB_30xLV | VB_30xLVX)) {
- inSISIDXREG(SISCR, 0x38, temp);
- if((temp & 0x03) == 0x03) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "[SiS302B/LV/LVX: LCD channel A]\n");
- }
- }
SISSense30x(pScrn);
} else if (temp == 3) {
- pSiS->VBFlags |= VB_303;
- pSiS->sishw_ext.ujVBChipID = VB_CHIP_303;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS303 video bridge\n");
+ "Detected SiS303 video bridge - not supported\n");
} else {
pSiS->sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
- inSISIDXREG(SISCR, 0x37, temp);
- temp = (temp >> 1) & 0x07;
-#if 0 /* TW: This does not seem to be used on any machine */
- if ( (temp == 0) || (temp == 1)) {
- pSiS->VBFlags|=VB_301; /* TW: 301 ? */
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected SiS301 video bridge (Irregular bridge type %d)\n", temp);
+ if(pSiS->Chipset == PCI_CHIP_SIS660) {
+ inSISIDXREG(SISCR, 0x38, temp);
+ temp = (temp >> 5) & 0x07;
+ } else {
+ inSISIDXREG(SISCR, 0x37, temp);
+ temp = (temp >> 1) & 0x07;
}
-#endif
if(pSiS->VGAEngine == SIS_300_VGA) {
lowerlimitlvds = 2; upperlimitlvds = 4;
lowerlimitch = 4; upperlimitch = 5;
chronteltype = 1; chrontelidreg = 0x25;
+ upperlimitvb = upperlimitlvds;
} else {
lowerlimitlvds = 2; upperlimitlvds = 3;
lowerlimitch = 3; upperlimitch = 3;
chronteltype = 2; chrontelidreg = 0x4b;
+ upperlimitvb = upperlimitlvds;
+ if(pSiS->Chipset == PCI_CHIP_SIS660) {
+ upperlimitvb = 4;
+ }
}
if((temp >= lowerlimitlvds) && (temp <= upperlimitlvds)) {
pSiS->VBFlags |= VB_LVDS;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Detected LVDS transmitter (Bridge type %d)\n", temp);
- if(pSiS->Chipset == PCI_CHIP_SIS650) {
- inSISIDXREG(SISCR, 0x38, temp1);
- if(temp1 & 0x02) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "[LVDS: LCD channel A]\n");
- }
- if(temp1 & 0x08) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "[LVDS: HDTV]\n");
- }
- if(temp1 & 0x08) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "[LVDS: SCART]\n");
- }
- }
}
if((temp >= lowerlimitch) && (temp <= upperlimitch)) {
- /* TW: Set global for init301.c */
+ /* Set global for init301.c */
pSiS->SiS_Pr->SiS_IF_DEF_CH70xx = chronteltype;
if(chronteltype == 1) {
- /* TW: Do something mysterious (found in Mitac BIOS) */
- SiS_WhatIsThis(pSiS->SiS_Pr, 0x9c);
+ /* Set general purpose IO for Chrontel communication */
+ SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c);
}
- /* TW: Read Chrontel version number */
+ /* Read Chrontel version number */
temp1 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg);
if(chronteltype == 1) {
- /* TW: See Chrontel TB31 for explanation */
+ /* See Chrontel TB31 for explanation */
temp2 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e);
- if(((temp2 & 0x07) == 0x01) || (temp & 0x04)) {
+ if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
SiS_SetCH700x(pSiS->SiS_Pr, 0x0b0e);
SiS_DDC2Delay(pSiS->SiS_Pr, 300);
}
@@ -1388,6 +1525,8 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
if(temp1 == 0xFFFF) { /* 0xFFFF = error reading DDC port */
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Detected Chrontel 70xx, but encountered error reading I2C port\n");
+ andSISIDXREG(SISCR, 0x32, ~0x07);
+ pSiS->postVBCR32 &= ~0x07;
}
/* TW: We only support device ids 0x19-200; other values may indicate DDC problems */
else if((temp1 >= 0x19) && (temp1 <= 200)) {
@@ -1407,42 +1546,54 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
"Detected Chrontel %s TV encoder (ID 0x%02x; bridge type %d)\n",
ChrontelTypeStr[temp2], temp1, temp);
- /* TW: Sense connected TV's */
+ /* Sense connected TV's */
if(chronteltype == 1) {
/* Chrontel 700x */
- /* TW: Read power status */
+ /* Read power status */
temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); /* Power status */
if((temp1 & 0x03) != 0x03) {
/* TW: Power all outputs */
SiS_SetCH700x(pSiS->SiS_Pr, 0x0B0E);
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
}
- /* TW: Sense connected TV devices */
- SiS_SetCH700x(pSiS->SiS_Pr, 0x0110);
- SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
- SiS_SetCH700x(pSiS->SiS_Pr, 0x0010);
- SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
- temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10);
- if(!(temp1 & 0x08)) temp1 = 0x02;
- else if(!(temp1 & 0x02)) temp1 = 0x01;
- else temp1 = 0;
+ /* Sense connected TV devices */
+ for(i = 0; i < 3; i++) {
+ SiS_SetCH700x(pSiS->SiS_Pr, 0x0110);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ SiS_SetCH700x(pSiS->SiS_Pr, 0x0010);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10);
+ if(!(temp1 & 0x08)) test[i] = 0x02;
+ else if(!(temp1 & 0x02)) test[i] = 0x01;
+ else test[i] = 0;
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ }
+
+ if(test[0] == test[1]) temp1 = test[0];
+ else if(test[0] == test[2]) temp1 = test[0];
+ else if(test[1] == test[2]) temp1 = test[1];
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "TV detection unreliable - test results varied\n");
+ temp1 = test[2];
+ }
} else {
/* Chrontel 701x */
- /* TW: Backup Power register */
+ /* Backup Power register */
temp1 = SiS_GetCH701x(pSiS->SiS_Pr, 0x49);
- /* TW: Enable TV path */
+ /* Enable TV path */
SiS_SetCH701x(pSiS->SiS_Pr, 0x2049);
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
- /* TW: Sense connected TV devices */
+ /* Sense connected TV devices */
temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
temp2 |= 0x01;
SiS_SetCH701x(pSiS->SiS_Pr, (temp2 << 8) | 0x20);
@@ -1456,7 +1607,7 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
- /* TW: Restore Power register */
+ /* Restore Power register */
SiS_SetCH701x(pSiS->SiS_Pr, (temp1 << 8) | 0x49);
temp1 = 0;
@@ -1472,18 +1623,20 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
case 0x01:
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Chrontel: Detected TV connected to COMPOSITE output\n");
- /* TW: So we can be sure that there IS a CVBS output */
pSiS->VBFlags |= TV_AVIDEO;
orSISIDXREG(SISCR, 0x32, 0x01);
+ andSISIDXREG(SISCR, 0x32, ~0x06);
pSiS->postVBCR32 |= 0x01;
+ pSiS->postVBCR32 &= ~0x06;
break;
case 0x02:
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Chrontel: Detected TV connected to SVIDEO output\n");
- /* TW: So we can be sure that there IS a SVIDEO output */
pSiS->VBFlags |= TV_SVIDEO;
orSISIDXREG(SISCR, 0x32, 0x02);
+ andSISIDXREG(SISCR, 0x32, ~0x05);
pSiS->postVBCR32 |= 0x02;
+ pSiS->postVBCR32 &= ~0x05;
break;
case 0x04:
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
@@ -1503,33 +1656,149 @@ void SISVGAPreInit(ScrnInfoPtr pScrn)
default:
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Chrontel: No TV detected.\n");
+ andSISIDXREG(SISCR, 0x32, ~0x07);
+ pSiS->postVBCR32 &= ~0x07;
}
} else if(temp1==0) {
- /* TW: This indicates a communication problem, but it only occures if there
- * is no TV attached.
+ /* This indicates a communication problem, but it only occures if there
+ * is no TV attached. So we don't use TV in this case.
*/
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected Chrontel TV encoder in promiscuous state (DDC/I2C mix-up)\n");
+ andSISIDXREG(SISCR, 0x32, ~0x07);
+ pSiS->postVBCR32 &= ~0x07;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Chrontel: Unsupported device id (%d) detected\n",temp1);
+ andSISIDXREG(SISCR, 0x32, ~0x07);
+ pSiS->postVBCR32 &= ~0x07;
}
if(chronteltype == 1) {
- /* TW: Do something mysterious (found in Mitac BIOS) */
- SiS_WhatIsThis(pSiS->SiS_Pr, 0x00);
+ /* Set general purpose IO for Chrontel communication */
+ SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00);
}
}
- if ((pSiS->VGAEngine == SIS_300_VGA) && (temp == 3)) {
- pSiS->VBFlags |= VB_TRUMPION;
+ if((pSiS->Chipset == PCI_CHIP_SIS660) && (temp == 4)) {
+ pSiS->VBFlags |= VB_CONEXANT;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected Conexant video bridge - UNSUPPORTED\n");
+ }
+ if((pSiS->VGAEngine == SIS_300_VGA) && (temp == 3)) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected Trumpion Zurac (I/II/III) LVDS scaler\n");
+ "Detected Trumpion Zurac (I/II/III) LVDS scaler - UNSUPPORTED\n");
}
- if (temp > upperlimitlvds) {
+ if(temp > upperlimitvb) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Detected unknown bridge type (%d)\n", temp);
}
}
+
+ /* Old BIOSes store the detected CRT2 type in SR17, 16 and 13
+ * instead of CR32. However, since our detection routines
+ * store their results to CR32, we now copy the
+ * remaining bits (for LCD and VGA) to CR32 for unified usage.
+ * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2
+ * [4] AVIDEO [5] SVIDEO
+ * SR13[0] SCART [1] HiVision
+ * SR16[5] PAL/NTSC [6] LCD-SCALE [7] OVERSCAN
+ */
+
+#if 0
+ inSISIDXREG(SISSR, 0x17, sr17);
+ if( (pSiS->VGAEngine == SIS_300_VGA) &&
+ (pSiS->Chipset != PCI_CHIP_SIS300) &&
+ (sr17 & 0x0F) ) {
+
+ unsigned char cr32;
+ inSISIDXREG(SISCR, 0x32, cr32);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Converting SR17 (%02x) to CR32 (%02x)\n", sr17, cr32);
+
+ if(sr17 & 0x01) { /* CRT1 */
+ orSISIDXREG(SISCR, 0x32, 0x20);
+ pSiS->postVBCR32 |= 0x20;
+ } else {
+ andSISIDXREG(SISCR, 0x32, ~0x20);
+ pSiS->postVBCR32 &= ~0x20;
+ }
+
+ if(sr17 & 0x02) { /* LCD */
+ orSISIDXREG(SISCR, 0x32, 0x08);
+ pSiS->postVBCR32 |= 0x08;
+ } else {
+ andSISIDXREG(SISCR, 0x32, ~0x08);
+ pSiS->postVBCR32 &= ~0x08;
+ }
+
+ /* No Hivision, no DVI here */
+ andSISIDXREG(SISCR,0x32,~0xc0);
+ pSiS->postVBCR32 &= ~0xc0;
+ }
+#endif
+
+ /* Try to find out if the bridge uses LCDA for low resolution and
+ * text modes. If sisfb saved this for us, use it. Otherwise,
+ * check if we are running on a low mode on LCD and read the
+ * relevant registers ourselves.
+ */
+ if(pSiS->VGAEngine == SIS_315_VGA) {
+
+ if(pSiS->VBFlags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
+ if(pSiS->sisfblcda != 0xff) {
+ if((pSiS->sisfblcda & 0x03) == 0x03) {
+ pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+ pSiS->ChipFlags |= SiSCF_UseLCDA;
+ }
+ } else {
+ inSISIDXREG(SISCR,0x34,temp);
+ if(temp <= 0x13) {
+ inSISIDXREG(SISCR,0x38,temp);
+ if((temp & 0x03) == 0x03) {
+ pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+ pSiS->ChipFlags |= SiSCF_UseLCDA;
+ pSiS->SiS_Pr->Backup = TRUE;
+ } else {
+ inSISIDXREG(SISCR,0x35,temp);
+ if(temp & 0x01) {
+ pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+ pSiS->ChipFlags |= SiSCF_UseLCDA;
+ pSiS->SiS_Pr->Backup = TRUE;
+ } else {
+ inSISIDXREG(SISCR,0x30,temp);
+ if(temp & 0x20) {
+ orSISIDXREG(SISPART1,0x2f,0x01); /* Unlock CRT2 */
+ inSISIDXREG(SISPART1,0x13,temp);
+ if(temp & 0x04) {
+ pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+ pSiS->ChipFlags |= SiSCF_UseLCDA;
+ pSiS->SiS_Pr->Backup = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ if(pSiS->ChipFlags & SiSCF_UseLCDA) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Bridge uses LCDA for low resolution and text modes\n");
+ if(pSiS->SiS_Pr->Backup == TRUE) {
+ inSISIDXREG(SISCR,0x34,pSiS->SiS_Pr->Backup_Mode);
+ inSISIDXREG(SISPART1,0x14,pSiS->SiS_Pr->Backup_14);
+ inSISIDXREG(SISPART1,0x15,pSiS->SiS_Pr->Backup_15);
+ inSISIDXREG(SISPART1,0x16,pSiS->SiS_Pr->Backup_16);
+ inSISIDXREG(SISPART1,0x17,pSiS->SiS_Pr->Backup_17);
+ inSISIDXREG(SISPART1,0x18,pSiS->SiS_Pr->Backup_18);
+ inSISIDXREG(SISPART1,0x19,pSiS->SiS_Pr->Backup_19);
+ inSISIDXREG(SISPART1,0x1a,pSiS->SiS_Pr->Backup_1a);
+ inSISIDXREG(SISPART1,0x1b,pSiS->SiS_Pr->Backup_1b);
+ inSISIDXREG(SISPART1,0x1c,pSiS->SiS_Pr->Backup_1c);
+ inSISIDXREG(SISPART1,0x1d,pSiS->SiS_Pr->Backup_1d);
+ }
+ }
+ }
+ }
}