diff options
Diffstat (limited to 'src/sis_setup.c')
-rw-r--r-- | src/sis_setup.c | 344 |
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; |