summaryrefslogtreecommitdiff
path: root/src/sis_setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sis_setup.c')
-rw-r--r--src/sis_setup.c344
1 files changed, 253 insertions, 91 deletions
diff --git a/src/sis_setup.c b/src/sis_setup.c
index 150ad12..019729f 100644
--- a/src/sis_setup.c
+++ b/src/sis_setup.c
@@ -1,28 +1,35 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_setup.c,v 1.18 2003/08/27 23:32:50 twini Exp $ */
+/* $XFree86$ */
+/* $XdotOrg$ */
/*
* Basic hardware and memory detection
*
- * Copyright 2001, 2002, 2003 by Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
*
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the copyright holder not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. The copyright holder makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1) Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2) Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3) The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Ideas and methods for old series based on code by Can-Ru Yeou, SiS Inc.
*
*/
@@ -58,12 +65,13 @@ static const char *dramTypeStr[] = {
"SDR SDRAM",
"SGRAM",
"ESDRAM",
- "DDR SDRAM", /* for 550/650 */
- "DDR SDRAM", /* for 550/650 */
- "VCM" /* for 630 */
+ "DDR SDRAM", /* for 550/650/etc */
+ "DDR SDRAM", /* for 550/650/etc */
+ "VCM", /* for 630 */
+ "DDR2 SDRAM",
"" };
-/* TW: MCLK tables for SiS6326 */
+/* MCLK tables for SiS6326 */
static const int SiS6326MCLKIndex[4][8] = {
{ 10, 12, 14, 16, 17, 18, 19, 7 }, /* SGRAM */
{ 4, 6, 8, 10, 11, 12, 13, 3 }, /* Fast Page */
@@ -110,7 +118,7 @@ sisOldSetup(ScrnInfoPtr pScrn)
int ramtype[4] = { 5, 0, 1, 3 };
int config;
int temp, i;
- unsigned char sr23, sr33, sr34, sr37;
+ unsigned char sr23, sr33, sr37;
#if 0
unsigned char newsr13, newsr28, newsr29;
#endif
@@ -160,7 +168,7 @@ sisOldSetup(ScrnInfoPtr pScrn)
i = SiS6326MCLKIndex[i][temp];
pSiS->MemClock = SiS6326MCLK[i].mclk;
#if 0
- /* TW: Correct invalid MCLK settings by old BIOSes */
+ /* Correct invalid MCLK settings by old BIOSes */
newsr13 = SiS6326MCLK[i].sr13;
newsr28 = SiS6326MCLK[i].sr28;
newsr29 = SiS6326MCLK[i].sr29;
@@ -193,7 +201,6 @@ sisOldSetup(ScrnInfoPtr pScrn)
if(pSiS->oldChipset >= OC_SIS82204) {
inSISIDXREG(SISSR, 0x23, sr23);
inSISIDXREG(SISSR, 0x33, sr33);
- inSISIDXREG(SISSR, 0x34, sr34);
if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08;
if(sr33 & 0x09) { /* 5597: Sync DRAM timing | One cycle EDO ram; */
pSiS->Flags |= (sr33 & SYNCDRAM); /* 6326: Enable SGRam timing | One cycle EDO ram */
@@ -267,7 +274,7 @@ sis300Setup(ScrnInfoPtr pScrn)
unsigned int config, pciconfig, sr3a, ramtype;
unsigned char temp;
int cpubuswidth;
- int from = X_PROBED;
+ MessageType from = X_PROBED;
pSiS->MemClock = SiSMclk(pSiS);
@@ -345,7 +352,7 @@ sis300Setup(ScrnInfoPtr pScrn)
pSiS->BusWidth);
}
-/* For 315, 315H, 315PRO, 330 */
+/* For 315, 315H, 315PRO, 330, 340 */
static void
sis315Setup(ScrnInfoPtr pScrn)
{
@@ -355,14 +362,14 @@ sis315Setup(ScrnInfoPtr pScrn)
int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
unsigned int config, config1, config2, sr3a;
char *dramTypeStr315[] = {
- "Single Channel 1 rank SDR SDRAM",
- "Single Channel 1 rank SDR SGRAM",
- "Single Channel 1 rank DDR SDRAM",
- "Single Channel 1 rank DDR SGRAM",
- "Single Channel 2 rank SDR SDRAM",
- "Single Channel 2 rank SDR SGRAM",
- "Single Channel 2 rank DDR SDRAM",
- "Single Channel 2 rank DDR SGRAM",
+ "Single channel 1 rank SDR SDRAM",
+ "Single channel 1 rank SDR SGRAM",
+ "Single channel 1 rank DDR SDRAM",
+ "Single channel 1 rank DDR SGRAM",
+ "Single channel 2 rank SDR SDRAM",
+ "Single channel 2 rank SDR SGRAM",
+ "Single channel 2 rank DDR SDRAM",
+ "Single channel 2 rank DDR SGRAM",
"Asymmetric SDR SDRAM",
"Asymmetric SDR SGRAM",
"Asymmetric DDR SDRAM",
@@ -388,6 +395,23 @@ sis315Setup(ScrnInfoPtr pScrn)
"",
"Dual channel DDR SDRAM",
""};
+ char *dramTypeStr340[] = {
+ "Single channel 1 Rank DDR SDRAM",
+ "Single channel 1 Rank DDR2 SDRAM",
+ "Single channel 1 Rank DDR2x SDRAM",
+ "",
+ "Single channel 2 Rank DDR SDRAM",
+ "Single channel 2 Rank DDR2 SDRAM",
+ "Single channel 2 Rank DDR2x SDRAM",
+ "",
+ "Dual channel 1 rank DDR SDRAM",
+ "Dual channel 1 rank DDR2 SDRAM",
+ "Dual channel 1 rank DDR2x SDRAM",
+ "",
+ "Quad channel 1 rank DDR SDRAM",
+ "Quad channel 1 rank DDR2 SDRAM",
+ "Quad channel 1 rank DDR2x SDRAM",
+ ""};
inSISIDXREG(SISSR, 0x14, config);
config1 = (config & 0x0C) >> 2;
@@ -396,40 +420,75 @@ sis315Setup(ScrnInfoPtr pScrn)
pScrn->videoRam = (1 << ((config & 0xF0) >> 4)) * 1024;
- if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ if(pSiS->Chipset == PCI_CHIP_SIS340) {
+
+ pSiS->IsAGPCard = TRUE;
+
+ if(config1 == 0x02) pScrn->videoRam <<= 1; /* dual rank */
+ else if(config1 == 0x03) pScrn->videoRam <<= 2; /* quad rank */
+
+ inSISIDXREG(SISSR, 0x39, config2);
+ config2 &= 0x02;
+ if(!config2) {
+ inSISIDXREG(SISSR, 0x3a, config2);
+ config2 = (config2 & 0x02) >> 1;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DRAM type: %s\n", dramTypeStr340[(config1 * 4) + (config2 & 0x03)]);
+
+ } else if(pSiS->Chipset == PCI_CHIP_SIS330) {
pSiS->IsAGPCard = TRUE;
if(config1) pScrn->videoRam <<= 1;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DRAM type: %s\n", dramTypeStr330[(config1 * 4) + (config2 & 0x02)]);
} else {
pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
/* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */
- if((config1 == 0x01) || (config1 == 0x03))
+ if((config1 == 0x01) || (config1 == 0x03)) {
pScrn->videoRam <<= 1;
+ }
/* If DDR asymetric -> mem * 1,5 */
- if(config1 == 0x02)
- pScrn->videoRam += pScrn->videoRam/2;
+ if(config1 == 0x02) pScrn->videoRam += pScrn->videoRam/2;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DRAM type: %s\n", dramTypeStr315[(config1 * 4) + config2]);
}
pSiS->MemClock = SiSMclk(pSiS);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "DRAM type: %s\n",
- (pSiS->Chipset == PCI_CHIP_SIS330) ?
- dramTypeStr330[(config1 * 4) + (config2 & 0x02)] :
- dramTypeStr315[(config1 * 4) + config2]);
-
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Memory clock: %3.3f MHz\n",
pSiS->MemClock/1000.0);
- /* TW: DDR -> mclk * 2 - needed for bandwidth calculation */
- if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ /* DDR -> mclk * 2 - needed for bandwidth calculation */
+ if(pSiS->Chipset == PCI_CHIP_SIS340) {
+
+ pSiS->MemClock *= 2; /* at least DDR */
+
+ inSISIDXREG(SISCR,0x97,config);
+ if(!(config & 0x10)) {
+ inSISIDXREG(SISSR,0x39,config);
+ config = (config & 0x02) >> 1;
+ } else config &= 0x01;
+
+ if(config) {
+ pSiS->MemClock *= 2; /* DDR2 ? */
+ pSiS->BusWidth = 32;
+ } else {
+ pSiS->BusWidth = 64;
+ }
+
+ } else if(pSiS->Chipset == PCI_CHIP_SIS330) {
+
if(config2 & 0x02) {
pSiS->MemClock *= 2;
if(config1 == 0x02) {
@@ -444,7 +503,9 @@ sis315Setup(ScrnInfoPtr pScrn)
pSiS->BusWidth = busSDR[(config & 0x02)];
}
}
+
} else {
+
if(config2 & 0x02) pSiS->MemClock *= 2;
if(config1 == 0x02)
pSiS->BusWidth = busDDRA[(config & 0x03)];
@@ -452,6 +513,7 @@ sis315Setup(ScrnInfoPtr pScrn)
pSiS->BusWidth = busDDR[(config & 0x03)];
else
pSiS->BusWidth = busSDR[(config & 0x03)];
+
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
@@ -459,7 +521,7 @@ sis315Setup(ScrnInfoPtr pScrn)
pSiS->BusWidth);
}
-/* For 550, 65x, 74x, 660 */
+/* For 550, 65x, 740, 661, 741, 660, 760 */
static void
sis550Setup(ScrnInfoPtr pScrn)
{
@@ -469,32 +531,106 @@ sis550Setup(ScrnInfoPtr pScrn)
BOOLEAN alldone = FALSE;
pSiS->IsAGPCard = TRUE;
+ pSiS->ChipFlags &= ~SiSCF_760UMA;
pSiS->MemClock = SiSMclk(pSiS);
if(pSiS->Chipset == PCI_CHIP_SIS660) {
- /* TODO - this is entirely guessed */
+ if(pSiS->sishw_ext.jChipType >= SIS_660) {
- pciconfig = pciReadByte(0x00000000, 0x64);
- if(pciconfig & 0x80) {
- pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024;
- pSiS->BusWidth = 64;
- for(i=0; i<=3; i++) {
- if(pciconfig & (1 << i)) {
- temp = pciReadByte(0x00000000, 0x60 + i);
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "DIMM%d is %s SDRAM\n",
- i, (temp & 0x40) ? "DDR" : "SDR");
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "DIMM%d is not installed\n", i);
+ /* UMA - shared fb */
+ pciconfig = pciReadByte(0x00000000, 0x4c);
+ if(pciconfig & 0xe0) {
+ pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768;
+ pSiS->ChipFlags |= SiSCF_760UMA;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "%dK shared video RAM (UMA)\n",
+ pScrn->videoRam);
+ } else pScrn->videoRam = 0;
+
+ /* LFB - local framebuffer: PCI reg hold total RAM (but configurable in BIOS) */
+ pciconfig = pciReadByte(0x00000800, 0xcd);
+ pciconfig = (pciconfig >> 1) & 0x03;
+ i = 0;
+ if(pciconfig == 0x01) i = 32768;
+ else if(pciconfig == 0x03) i = 65536;
+ if(i) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK total local framebuffer RAM (LFB)\n", i);
+ }
+
+ /* LFB: CR78 holds amount of LFB memory configured in the BIOS setup */
+ inSISIDXREG(SISCR, 0x78, config);
+ config &= 0x30;
+ if(config) {
+ i = 0;
+ if(config == 0x10) i = 32768;
+ else if(config == 0x30) i = 65536;
+ if(i) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK configured local framebuffer RAM (LFB)\n", i);
+ pScrn->videoRam += i;
+ pSiS->ChipFlags |= SiSCF_760LFB;
}
}
- pciconfig = pciReadByte(0x00000000, 0x7c);
- if(pciconfig & 0x02) ramtype = 8;
- else ramtype = 4;
- alldone = TRUE;
+
+ if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal video RAM size (%dK) detected, using BIOS provided setting\n",
+ pScrn->videoRam);
+ pSiS->ChipFlags &= ~(SiSCF_760LFB | SiSCF_760UMA);
+ } else {
+ pSiS->BusWidth = 64;
+ ramtype = 8;
+ alldone = TRUE;
+ }
+
+ } else {
+
+ int dimmnum;
+
+ if(pSiS->sishw_ext.jChipType == SIS_741) {
+ dimmnum = 4;
+ } else { /* 661 */
+ dimmnum = 3;
+ }
+
+ pciconfig = pciReadByte(0x00000000, 0x64);
+ if(pciconfig & 0x80) {
+ pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768;
+ if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal video RAM size (%dK) detected, using BIOS provided setting\n",
+ pScrn->videoRam);
+ } else {
+ pSiS->BusWidth = 64;
+ for(i=0; i<=(dimmnum - 1); i++) {
+ if(pciconfig & (1 << i)) {
+ temp = pciReadByte(0x00000000, 0x60 + i);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DIMM%d is %s SDRAM\n",
+ i, (temp & 0x40) ? "DDR" : "SDR");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DIMM%d is not installed\n", i);
+ }
+ }
+ pciconfig = pciReadByte(0x00000000, 0x7c);
+ ramtype = (pciconfig & 0x02) ? 8 : 4;
+#if 0
+ if(pSiS->sishw_ext.jChipType == SIS_741) {
+ /* Is this really correct? - Doesn't seem so*/
+ ramtype = 12 - ramtype;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS741 PCI RamType %d\n", ramtype);
+ /* For now, we don't trust it */
+ inSISIDXREG(SISCR, 0x79, config);
+ ramtype = (config & 0x01) ? 8 : 4;
+ }
+#endif
+ alldone = TRUE;
+ }
+ }
+
}
} else if(pSiS->Chipset == PCI_CHIP_SIS650) {
@@ -536,17 +672,42 @@ sis550Setup(ScrnInfoPtr pScrn)
}
+ /* Fall back to BIOS detection results in case of problems: */
+
if(!alldone) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Shared Memory Area is disabled - awaiting doom\n");
- inSISIDXREG(SISSR, 0x14, config);
- pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
- if(pSiS->Chipset == PCI_CHIP_SIS650) {
- ramtype = (((config & 0x80) >> 7) << 2) + 4;
- pSiS->BusWidth = 64; /* (config & 0x40) ? 128 : 64; */
+
+ if(pSiS->Chipset == PCI_CHIP_SIS660) {
+ inSISIDXREG(SISCR, 0x79, config);
+ pSiS->BusWidth = (config & 0x04) ? 128 : 64;
+ ramtype = (config & 0x01) ? 8 : 4;
+ if(pSiS->sishw_ext.jChipType >= SIS_660) {
+ pScrn->videoRam = 0;
+ if(config & 0xf0) {
+ pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
+ pSiS->ChipFlags |= SiSCF_760UMA;
+ }
+ inSISIDXREG(SISCR, 0x78, config);
+ config &= 0x30;
+ if(config) {
+ if(config == 0x10) pScrn->videoRam += 32768;
+ else pScrn->videoRam += 65536;
+ pSiS->ChipFlags |= SiSCF_760LFB;
+ }
+ } else {
+ pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
+ }
} else {
- ramtype = 4;
- pSiS->BusWidth = 64;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Shared Memory Area is disabled - awaiting doom\n");
+ inSISIDXREG(SISSR, 0x14, config);
+ pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
+ if(pSiS->Chipset == PCI_CHIP_SIS650) {
+ ramtype = (((config & 0x80) >> 7) << 2) + 4;
+ pSiS->BusWidth = 64; /* (config & 0x40) ? 128 : 64; */
+ } else {
+ ramtype = 4;
+ pSiS->BusWidth = 64;
+ }
}
}
@@ -562,7 +723,7 @@ sis550Setup(ScrnInfoPtr pScrn)
"DRAM bus width: %d bit\n",
pSiS->BusWidth);
- /* TW: DDR -> Mclk * 2 - needed for bandwidth calculation */
+ /* DDR -> Mclk * 2 - needed for bandwidth calculation */
if(ramtype == 8) pSiS->MemClock *= 2;
}
@@ -574,26 +735,27 @@ SiSSetup(ScrnInfoPtr pScrn)
pSiS->Flags = 0;
pSiS->VBFlags = 0;
- switch (SISPTR(pScrn)->Chipset) {
- case PCI_CHIP_SIS300:
- case PCI_CHIP_SIS630: /* +730 */
- case PCI_CHIP_SIS540:
+ switch (SISPTR(pScrn)->Chipset) {
+ case PCI_CHIP_SIS300:
+ case PCI_CHIP_SIS630: /* +730 */
+ case PCI_CHIP_SIS540:
sis300Setup(pScrn);
break;
- case PCI_CHIP_SIS315:
- case PCI_CHIP_SIS315H:
- case PCI_CHIP_SIS315PRO:
- case PCI_CHIP_SIS330:
+ case PCI_CHIP_SIS315:
+ case PCI_CHIP_SIS315H:
+ case PCI_CHIP_SIS315PRO:
+ case PCI_CHIP_SIS330:
+ case PCI_CHIP_SIS340:
sis315Setup(pScrn);
break;
- case PCI_CHIP_SIS550:
- case PCI_CHIP_SIS650: /* + 740 */
- case PCI_CHIP_SIS660: /* + 760 */
+ case PCI_CHIP_SIS550:
+ case PCI_CHIP_SIS650: /* + 740,M650,651 */
+ case PCI_CHIP_SIS660: /* + (M)661,(M)741,(M)760 */
sis550Setup(pScrn);
break;
- case PCI_CHIP_SIS5597:
- case PCI_CHIP_SIS6326:
- case PCI_CHIP_SIS530:
+ case PCI_CHIP_SIS5597:
+ case PCI_CHIP_SIS6326:
+ case PCI_CHIP_SIS530:
default:
sisOldSetup(pScrn);
break;