172b676d7Smrg/* 272b676d7Smrg * Basic hardware and memory detection 372b676d7Smrg * 472b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 572b676d7Smrg * 672b676d7Smrg * Redistribution and use in source and binary forms, with or without 772b676d7Smrg * modification, are permitted provided that the following conditions 872b676d7Smrg * are met: 972b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1072b676d7Smrg * notice, this list of conditions and the following disclaimer. 1172b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1272b676d7Smrg * notice, this list of conditions and the following disclaimer in the 1372b676d7Smrg * documentation and/or other materials provided with the distribution. 1472b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 1572b676d7Smrg * derived from this software without specific prior written permission. 1672b676d7Smrg * 1772b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1872b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1972b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2072b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2172b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2272b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2372b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2472b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2572b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2672b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2772b676d7Smrg * 2872b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 2972b676d7Smrg * 3072b676d7Smrg * Ideas and methods for old series based on code by Can-Ru Yeou, SiS Inc. 3172b676d7Smrg * 3272b676d7Smrg */ 3372b676d7Smrg 3472b676d7Smrg#ifdef HAVE_CONFIG_H 3572b676d7Smrg#include "config.h" 3672b676d7Smrg#endif 3772b676d7Smrg 3872b676d7Smrg#include "sis.h" 3972b676d7Smrg#define SIS_NEED_inSISREGW 4072b676d7Smrg#define SIS_NEED_inSISREGL 4172b676d7Smrg#define SIS_NEED_outSISREGW 4272b676d7Smrg#define SIS_NEED_outSISREGL 4372b676d7Smrg#define SIS_NEED_inSISIDXREG 4472b676d7Smrg#define SIS_NEED_outSISIDXREG 4572b676d7Smrg#include "sis_regs.h" 4672b676d7Smrg 4772b676d7Smrgextern int SiSMclk(SISPtr pSiS); 4872b676d7Smrg 4972b676d7Smrgstatic const char *dramTypeStr[] = { 5072b676d7Smrg "Fast Page DRAM", 5172b676d7Smrg "2 cycle EDO RAM", 5272b676d7Smrg "1 cycle EDO RAM", 5372b676d7Smrg "SDRAM/SGRAM", 5472b676d7Smrg "SDR SDRAM", 5572b676d7Smrg "SGRAM", 5672b676d7Smrg "ESDRAM", 5772b676d7Smrg "DDR SDRAM", /* for 550/650/etc */ 5872b676d7Smrg "DDR SDRAM", /* for 550/650/etc */ 5972b676d7Smrg "VCM", /* for 630 */ 6072b676d7Smrg "DDR2 SDRAM", /* for 340 */ 6172b676d7Smrg "" 6272b676d7Smrg}; 6372b676d7Smrg 6472b676d7Smrg/* MCLK tables for SiS6326 */ 6572b676d7Smrgstatic const int SiS6326MCLKIndex[4][8] = { 6672b676d7Smrg { 10, 12, 14, 16, 17, 18, 19, 7 }, /* SGRAM */ 6772b676d7Smrg { 4, 6, 8, 10, 11, 12, 13, 3 }, /* Fast Page */ 6872b676d7Smrg { 9, 11, 12, 13, 15, 16, 5, 7 }, /* 2 cycle EDO */ 6972b676d7Smrg { 10, 12, 14, 16, 17, 18, 19, 7 } /* ? (Not 1 cycle EDO) */ 7072b676d7Smrg}; 7172b676d7Smrg 7272b676d7Smrgstatic const struct _sis6326mclk { 7372b676d7Smrg CARD16 mclk; 7472b676d7Smrg UChar sr13; 7572b676d7Smrg UChar sr28; 7672b676d7Smrg UChar sr29; 7772b676d7Smrg} SiS6326MCLK[] = { 7872b676d7Smrg { 0, 0, 0, 0 }, 7972b676d7Smrg { 0, 0, 0, 0 }, 8072b676d7Smrg { 0, 0, 0, 0 }, 8172b676d7Smrg { 45, 0, 0x2b, 0x26 }, 8272b676d7Smrg { 53, 0, 0x49, 0xe4 }, 8372b676d7Smrg { 55, 0, 0x7c, 0xe7 }, 8472b676d7Smrg { 56, 0, 0x7c, 0xe7 }, 8572b676d7Smrg { 60, 0, 0x42, 0xe3 }, 8672b676d7Smrg { 61, 0, 0x21, 0xe1 }, 8772b676d7Smrg { 65, 0, 0x5a, 0xe4 }, 8872b676d7Smrg { 66, 0, 0x5a, 0xe4 }, 8972b676d7Smrg { 70, 0, 0x61, 0xe4 }, 9072b676d7Smrg { 75, 0, 0x3e, 0xe2 }, 9172b676d7Smrg { 80, 0, 0x42, 0xe2 }, 9272b676d7Smrg { 83, 0, 0xb3, 0xc5 }, 9372b676d7Smrg { 85, 0, 0x5e, 0xe3 }, 9472b676d7Smrg { 90, 0, 0xae, 0xc4 }, 9572b676d7Smrg {100, 0, 0x37, 0xe1 }, 9672b676d7Smrg {115, 0, 0x78, 0x0e }, 9772b676d7Smrg {134, 0, 0x4a, 0xa3 } 9872b676d7Smrg}; 9972b676d7Smrg 1001fd23544Smrg#ifdef XSERVER_LIBPCIACCESS 1011fd23544Smrgstruct pci_device * 1021fd23544Smrgsis_get_device (int device) 1031fd23544Smrg{ 1041fd23544Smrg struct pci_slot_match bridge_match = { 1051fd23544Smrg 0, 0, device, PCI_MATCH_ANY, 0 1061fd23544Smrg }; 1071fd23544Smrg struct pci_device_iterator *slot_iterator; 1081fd23544Smrg struct pci_device *bridge; 1091fd23544Smrg 1101fd23544Smrg slot_iterator = pci_slot_match_iterator_create (&bridge_match); 1111fd23544Smrg bridge = pci_device_next (slot_iterator); 1121fd23544Smrg pci_iterator_destroy (slot_iterator); 1131fd23544Smrg return bridge; 1141fd23544Smrg} 1151fd23544Smrg 1161fd23544Smrgunsigned int 1171fd23544Smrgsis_pci_read_device_u32(int device, int offset) 1181fd23544Smrg{ 1191fd23544Smrg struct pci_device *host_bridge = sis_get_device(device); 1201fd23544Smrg unsigned int result; 1211fd23544Smrg 1221fd23544Smrg pci_device_cfg_read_u32(host_bridge, &result, offset); 1231fd23544Smrg return result; 1241fd23544Smrg} 1251fd23544Smrg 1261fd23544Smrgunsigned char 1271fd23544Smrgsis_pci_read_device_u8(int device, int offset) 1281fd23544Smrg{ 1291fd23544Smrg struct pci_device *host_bridge = sis_get_device(device); 1301fd23544Smrg unsigned char result; 1311fd23544Smrg 1321fd23544Smrg pci_device_cfg_read_u8(host_bridge, &result, offset); 1331fd23544Smrg return result; 1341fd23544Smrg} 1351fd23544Smrg 1361fd23544Smrgvoid 1371fd23544Smrgsis_pci_write_host_bridge_u32(int offset, unsigned int value) 1381fd23544Smrg{ 1391fd23544Smrg struct pci_device *host_bridge = sis_get_device(0); 1401fd23544Smrg pci_device_cfg_write_u32(host_bridge, value, offset); 1411fd23544Smrg} 1421fd23544Smrg 1431fd23544Smrgvoid 1441fd23544Smrgsis_pci_write_host_bridge_u8(int offset, unsigned char value) 1451fd23544Smrg{ 1461fd23544Smrg struct pci_device *host_bridge = sis_get_device(0); 1471fd23544Smrg pci_device_cfg_write_u8(host_bridge, value, offset); 1481fd23544Smrg} 1491fd23544Smrg 1501fd23544Smrg#else 1511fd23544Smrgunsigned int 1521fd23544Smrgsis_pci_read_device_u32(int device, int offset) 1531fd23544Smrg{ 1541fd23544Smrg PCITAG tag = pciTag(0, device, 0); 1551fd23544Smrg return pciReadLong(tag, offset); 1561fd23544Smrg} 1571fd23544Smrg 1581fd23544Smrgunsigned char 1591fd23544Smrgsis_pci_read_device_u8(int device, int offset) 1601fd23544Smrg{ 1611fd23544Smrg PCITAG tag = pciTag(0, device, 0); 1621fd23544Smrg return pciReadByte(tag, offset); 1631fd23544Smrg} 1641fd23544Smrg 1651fd23544Smrgvoid 1661fd23544Smrgsis_pci_write_host_bridge_u32(int offset, unsigned int value) 1671fd23544Smrg{ 1681fd23544Smrg pciWriteLong(0x00000000, offset, value); 1691fd23544Smrg} 1701fd23544Smrg 1711fd23544Smrgvoid 1721fd23544Smrgsis_pci_write_host_bridge_u8(int offset, unsigned char value) 1731fd23544Smrg{ 1741fd23544Smrg pciWriteByte(0x00000000, offset, value); 1751fd23544Smrg} 1761fd23544Smrg 1771fd23544Smrg 1781fd23544Smrg#endif 1791fd23544Smrg 1801fd23544Smrgunsigned int 1811fd23544Smrgsis_pci_read_host_bridge_u32(int offset) 1821fd23544Smrg{ 1831fd23544Smrg return sis_pci_read_device_u32(0, offset); 1841fd23544Smrg} 1851fd23544Smrg 1861fd23544Smrgunsigned char 1871fd23544Smrgsis_pci_read_host_bridge_u8(int offset) 1881fd23544Smrg{ 1891fd23544Smrg return sis_pci_read_device_u8(0, offset); 1901fd23544Smrg} 1911fd23544Smrg 1921fd23544Smrgstatic int sisESSPresent(ScrnInfoPtr pScrn) 1931fd23544Smrg{ 1941fd23544Smrg int flags = 0; 1951fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 1961fd23544Smrg int i; 1971fd23544Smrg pciConfigPtr pdptr, *systemPCIdevices = NULL; 1981fd23544Smrg 1991fd23544Smrg if((systemPCIdevices = xf86GetPciConfigInfo())) { 2001fd23544Smrg i = 0; 2011fd23544Smrg while((pdptr = systemPCIdevices[i])) { 2021fd23544Smrg if((pdptr->pci_vendor == 0x1274) && 2031fd23544Smrg ((pdptr->pci_device == 0x5000) || 2041fd23544Smrg ((pdptr->pci_device & 0xFFF0) == 0x1370))) { 2051fd23544Smrg flags |= ESS137xPRESENT; 2061fd23544Smrg break; 2071fd23544Smrg } 2081fd23544Smrg i++; 2091fd23544Smrg } 2101fd23544Smrg } 2111fd23544Smrg return flags; 2121fd23544Smrg#else 2131fd23544Smrg struct pci_id_match id_match = { 0x1274, PCI_MATCH_ANY, 2141fd23544Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, 2151fd23544Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, 2161fd23544Smrg 0 }; 2171fd23544Smrg struct pci_device_iterator *id_iterator; 2181fd23544Smrg struct pci_device *ess137x; 2191fd23544Smrg 2201fd23544Smrg id_iterator = pci_id_match_iterator_create(&id_match); 2211fd23544Smrg 2221fd23544Smrg ess137x = pci_device_next(id_iterator); 2231fd23544Smrg while (ess137x) { 2241fd23544Smrg if ((ess137x->device_id == 0x5000) || 2251fd23544Smrg ((ess137x->device_id & 0xfff0) == 0x1370)) { 2261fd23544Smrg flags |= ESS137xPRESENT; 2271fd23544Smrg } 2281fd23544Smrg ess137x = pci_device_next(id_iterator); 2291fd23544Smrg } 2301fd23544Smrg return flags; 2311fd23544Smrg#endif 2321fd23544Smrg} 2331fd23544Smrg 23472b676d7Smrg/* For old chipsets, 5597, 6326, 530/620 */ 23572b676d7Smrgstatic void 23672b676d7SmrgsisOldSetup(ScrnInfoPtr pScrn) 23772b676d7Smrg{ 23872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 23972b676d7Smrg int ramsize[8] = { 1, 2, 4, 0, 0, 2, 4, 8}; 24072b676d7Smrg int buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 }; 24172b676d7Smrg int clockTable[4] = { 66, 75, 83, 100 }; 24272b676d7Smrg int ramtype[4] = { 5, 0, 1, 3 }; 24372b676d7Smrg int config, temp, i; 24472b676d7Smrg UChar sr23, sr33, sr37; 24572b676d7Smrg#if 0 24672b676d7Smrg UChar newsr13, newsr28, newsr29; 24772b676d7Smrg#endif 2481fd23544Smrg 24972b676d7Smrg 25072b676d7Smrg if(pSiS->oldChipset <= OC_SIS6225) { 25172b676d7Smrg inSISIDXREG(SISSR, 0x0F, temp); 25272b676d7Smrg pScrn->videoRam = (1 << (temp & 0x03)) * 1024; 25372b676d7Smrg if(pScrn->videoRam > 4096) pScrn->videoRam = 4096; 25472b676d7Smrg pSiS->BusWidth = 32; 25572b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS5597) { 25672b676d7Smrg inSISIDXREG(SISSR, 0x2F, temp); 25772b676d7Smrg pScrn->videoRam = ((temp & 0x07) + 1) * 256; 25872b676d7Smrg inSISIDXREG(SISSR, 0x0C, temp); 25972b676d7Smrg if(temp & 0x06) { 26072b676d7Smrg pScrn->videoRam *= 2; 26172b676d7Smrg pSiS->BusWidth = 64; 26272b676d7Smrg } else pSiS->BusWidth = 32; 26372b676d7Smrg } else { 26472b676d7Smrg inSISIDXREG(SISSR, 0x0C, temp); 26572b676d7Smrg config = ((temp & 0x10) >> 2 ) | ((temp & 0x06) >> 1); 26672b676d7Smrg pScrn->videoRam = ramsize[config] * 1024; 26772b676d7Smrg pSiS->BusWidth = buswidth[config]; 26872b676d7Smrg } 26972b676d7Smrg 27072b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 27172b676d7Smrg 27272b676d7Smrg inSISIDXREG(SISSR, 0x0D, temp); 27372b676d7Smrg pSiS->Flags &= ~(UMA); 27472b676d7Smrg if(temp & 0x01) { 27572b676d7Smrg pSiS->Flags |= UMA; /* Shared fb mode */ 27672b676d7Smrg inSISIDXREG(SISSR, 0x10, temp); 27772b676d7Smrg pSiS->MemClock = clockTable[temp & 0x03] * 1000; 27872b676d7Smrg } else { 27972b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); /* Local fb mode */ 28072b676d7Smrg } 28172b676d7Smrg 28272b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 28372b676d7Smrg 28472b676d7Smrg inSISIDXREG(SISSR,0x0e,temp); 28572b676d7Smrg 28672b676d7Smrg i = temp & 0x03; 28772b676d7Smrg 28872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 28972b676d7Smrg "DRAM type: %s\n", 29072b676d7Smrg dramTypeStr[ramtype[i]]); 29172b676d7Smrg 29272b676d7Smrg temp = (temp >> 5) & 0x07; 29372b676d7Smrg i = SiS6326MCLKIndex[i][temp]; 29472b676d7Smrg pSiS->MemClock = SiS6326MCLK[i].mclk; 29572b676d7Smrg#if 0 29672b676d7Smrg /* Correct invalid MCLK settings by old BIOSes */ 29772b676d7Smrg newsr13 = SiS6326MCLK[i].sr13; 29872b676d7Smrg newsr28 = SiS6326MCLK[i].sr28; 29972b676d7Smrg newsr29 = SiS6326MCLK[i].sr29; 30072b676d7Smrg if((pSiS->ChipRev == 0x92) || 30172b676d7Smrg (pSiS->ChipRev == 0xd1) || 30272b676d7Smrg (pSiS->ChipRev == 0xd2)) { 30372b676d7Smrg if(pSiS->MemClock == 60) { 30472b676d7Smrg newsr28 = 0xae; 30572b676d7Smrg newsr29 = 0xc4; 30672b676d7Smrg } 30772b676d7Smrg } 30872b676d7Smrg#endif 30972b676d7Smrg pSiS->MemClock *= 1000; 31072b676d7Smrg#if 0 31172b676d7Smrg inSISIDXREG(SISSR, 0x13, temp); 31272b676d7Smrg temp &= 0x80; 31372b676d7Smrg temp |= (newsr13 & 0x80); 31472b676d7Smrg outSISIDXREG(SISSR,0x13,temp); 31572b676d7Smrg outSISIDXREG(SISSR,0x28,newsr28); 31672b676d7Smrg outSISIDXREG(SISSR,0x29,newsr29); 31772b676d7Smrg#endif 31872b676d7Smrg 31972b676d7Smrg } else { 32072b676d7Smrg 32172b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 32272b676d7Smrg 32372b676d7Smrg } 32472b676d7Smrg 32572b676d7Smrg pSiS->Flags &= ~(SYNCDRAM | RAMFLAG); 32672b676d7Smrg if(pSiS->oldChipset >= OC_SIS82204) { 32772b676d7Smrg inSISIDXREG(SISSR, 0x23, sr23); 32872b676d7Smrg inSISIDXREG(SISSR, 0x33, sr33); 32972b676d7Smrg if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08; 33072b676d7Smrg if(sr33 & 0x09) { /* 5597: Sync DRAM timing | One cycle EDO ram; */ 33172b676d7Smrg pSiS->Flags |= (sr33 & SYNCDRAM); /* 6326: Enable SGRam timing | One cycle EDO ram */ 33272b676d7Smrg pSiS->Flags |= RAMFLAG; /* 530: Enable SGRAM timing | reserved (0) */ 33372b676d7Smrg } else if((pSiS->oldChipset < OC_SIS530A) && (sr23 & 0x20)) { 33472b676d7Smrg pSiS->Flags |= SYNCDRAM; /* 5597, 6326: EDO DRAM enabled */ 33572b676d7Smrg } /* 530/620: reserved (0) */ 33672b676d7Smrg } 33772b676d7Smrg 33872b676d7Smrg pSiS->Flags &= ~(ESS137xPRESENT); 33972b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 34072b676d7Smrg if(pSiS->oldChipset == OC_SIS530A) { 3411fd23544Smrg pSiS->Flags |= sisESSPresent(pScrn); 3421fd23544Smrg } 3431fd23544Smrg if(pSiS->Flags & ESS137xPRESENT) { 3441fd23544Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3451fd23544Smrg "SiS530/620: Found ESS device\n"); 34672b676d7Smrg } 34772b676d7Smrg } 34872b676d7Smrg 34972b676d7Smrg pSiS->Flags &= ~(SECRETFLAG); 35072b676d7Smrg if(pSiS->oldChipset >= OC_SIS5597) { 35172b676d7Smrg inSISIDXREG(SISSR, 0x37, sr37); 35272b676d7Smrg if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG; 35372b676d7Smrg } 35472b676d7Smrg 35572b676d7Smrg pSiS->Flags &= ~(A6326REVAB); 35672b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS6326) { 35772b676d7Smrg if(((pSiS->ChipRev & 0x0f) == 0x0a) || 35872b676d7Smrg ((pSiS->ChipRev & 0x0f) == 0x0b)) { 35972b676d7Smrg pSiS->Flags |= A6326REVAB; 36072b676d7Smrg } 36172b676d7Smrg } 36272b676d7Smrg 36372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 36472b676d7Smrg "Memory clock: %3.3f MHz\n", 36572b676d7Smrg pSiS->MemClock/1000.0); 36672b676d7Smrg 36772b676d7Smrg if(pSiS->oldChipset > OC_SIS6225) { 36872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 36972b676d7Smrg "DRAM bus width: %d bit\n", 37072b676d7Smrg pSiS->BusWidth); 37172b676d7Smrg } 37272b676d7Smrg 37372b676d7Smrg#ifdef TWDEBUG 37472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 37572b676d7Smrg "oldChipset = %d, Flags %x\n", pSiS->oldChipset, pSiS->Flags); 37672b676d7Smrg#endif 37772b676d7Smrg} 37872b676d7Smrg 37972b676d7Smrgstatic void 38072b676d7Smrgsis300Setup(ScrnInfoPtr pScrn) 38172b676d7Smrg{ 38272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 38372b676d7Smrg const int bus[4] = {32, 64, 128, 32}; 38472b676d7Smrg const int adaptermclk[8] = { 66, 83, 100, 133, 38572b676d7Smrg 100, 100, 100, 100}; 38672b676d7Smrg const int adaptermclk300[8] = { 125, 125, 125, 100, 38772b676d7Smrg 100, 100, 100, 100}; 38872b676d7Smrg unsigned int config, pciconfig, sr3a, ramtype; 38972b676d7Smrg UChar temp; 39072b676d7Smrg int cpubuswidth; 39172b676d7Smrg MessageType from = X_PROBED; 39272b676d7Smrg 39372b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 39472b676d7Smrg 39572b676d7Smrg inSISIDXREG(SISSR, 0x14, config); 39672b676d7Smrg cpubuswidth = bus[config >> 6]; 39772b676d7Smrg 39872b676d7Smrg inSISIDXREG(SISSR, 0x3A, sr3a); 39972b676d7Smrg ramtype = (sr3a & 0x03) + 4; 40072b676d7Smrg 40172b676d7Smrg pSiS->IsPCIExpress = FALSE; 40272b676d7Smrg 40372b676d7Smrg switch(pSiS->Chipset) { 40472b676d7Smrg case PCI_CHIP_SIS300: 40572b676d7Smrg pScrn->videoRam = ((config & 0x3F) + 1) * 1024; 40672b676d7Smrg pSiS->LFBsize = pScrn->videoRam; 40772b676d7Smrg pSiS->BusWidth = cpubuswidth; 40872b676d7Smrg pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE; 40972b676d7Smrg break; 41072b676d7Smrg case PCI_CHIP_SIS540: 41172b676d7Smrg case PCI_CHIP_SIS630: 41272b676d7Smrg pSiS->IsAGPCard = TRUE; 4131fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x63); 41472b676d7Smrg if(pciconfig & 0x80) { 41572b676d7Smrg pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024; 41672b676d7Smrg pSiS->BusWidth = 64; 4171fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x64); 41872b676d7Smrg if((pciconfig & 0x30) == 0x30) { 41972b676d7Smrg pSiS->BusWidth = 128; 42072b676d7Smrg pScrn->videoRam <<= 1; 42172b676d7Smrg } 4221fd23544Smrg ramtype = sis_pci_read_host_bridge_u8(0x65); 42372b676d7Smrg ramtype &= 0x03; 42472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 42572b676d7Smrg "Shared Memory Area is on DIMM%d\n", ramtype); 4261fd23544Smrg ramtype = sis_pci_read_host_bridge_u8(0x60 + ramtype); 42772b676d7Smrg if(ramtype & 0x80) ramtype = 9; 42872b676d7Smrg else ramtype = 4; 42972b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 43072b676d7Smrg } else { 43172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 43272b676d7Smrg "Shared Memory Area is disabled - awaiting doom\n"); 43372b676d7Smrg pScrn->videoRam = ((config & 0x3F) + 1) * 1024; 43472b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 43572b676d7Smrg pSiS->BusWidth = 64; 43672b676d7Smrg ramtype = 4; 43772b676d7Smrg from = X_INFO; 43872b676d7Smrg } 43972b676d7Smrg break; 44072b676d7Smrg default: 44172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 44272b676d7Smrg "Internal error: sis300setup() called with invalid chipset!\n"); 44372b676d7Smrg pSiS->BusWidth = 64; 44472b676d7Smrg from = X_INFO; 44572b676d7Smrg } 44672b676d7Smrg 44772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 44872b676d7Smrg "DRAM type: %s\n", 44972b676d7Smrg dramTypeStr[ramtype]); 45072b676d7Smrg 45172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 45272b676d7Smrg "Memory clock: %3.3f MHz\n", 45372b676d7Smrg pSiS->MemClock/1000.0); 45472b676d7Smrg 45572b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS300) { 45672b676d7Smrg if(pSiS->ChipRev > 0x13) { 45772b676d7Smrg inSISIDXREG(SISSR, 0x3A, temp); 45872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 45972b676d7Smrg "(Adapter assumes MCLK being %d Mhz)\n", 46072b676d7Smrg adaptermclk300[(temp & 0x07)]); 46172b676d7Smrg } 46272b676d7Smrg } else { 46372b676d7Smrg inSISIDXREG(SISSR, 0x1A, temp); 46472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 46572b676d7Smrg "(Adapter assumes MCLK being %d Mhz)\n", 46672b676d7Smrg adaptermclk[(temp & 0x07)]); 46772b676d7Smrg } 46872b676d7Smrg 46972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, 47072b676d7Smrg "DRAM bus width: %d bit\n", 47172b676d7Smrg pSiS->BusWidth); 47272b676d7Smrg} 47372b676d7Smrg 47472b676d7Smrg/* For 315, 315H, 315PRO/E, 330, 340 */ 47572b676d7Smrgstatic void 47672b676d7Smrgsis315Setup(ScrnInfoPtr pScrn) 47772b676d7Smrg{ 47872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 47972b676d7Smrg int busSDR[4] = {64, 64, 128, 128}; 48072b676d7Smrg int busDDR[4] = {32, 32, 64, 64}; 48172b676d7Smrg int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; 48272b676d7Smrg unsigned int config, config1, config2, sr3a, cr5f; 48372b676d7Smrg char *dramTypeStr315[] = { 48472b676d7Smrg "Single channel 1 rank SDR SDRAM", 48572b676d7Smrg "Single channel 1 rank SDR SGRAM", 48672b676d7Smrg "Single channel 1 rank DDR SDRAM", 48772b676d7Smrg "Single channel 1 rank DDR SGRAM", 48872b676d7Smrg "Single channel 2 rank SDR SDRAM", 48972b676d7Smrg "Single channel 2 rank SDR SGRAM", 49072b676d7Smrg "Single channel 2 rank DDR SDRAM", 49172b676d7Smrg "Single channel 2 rank DDR SGRAM", 49272b676d7Smrg "Asymmetric SDR SDRAM", 49372b676d7Smrg "Asymmetric SDR SGRAM", 49472b676d7Smrg "Asymmetric DDR SDRAM", 49572b676d7Smrg "Asymmetric DDR SGRAM", 49672b676d7Smrg "Dual channel SDR SDRAM", 49772b676d7Smrg "Dual channel SDR SGRAM", 49872b676d7Smrg "Dual channel DDR SDRAM", 49972b676d7Smrg "Dual channel DDR SGRAM" 50072b676d7Smrg }; 50172b676d7Smrg char *dramTypeStr330[] = { 50272b676d7Smrg "Single Channel SDR SDRAM", 50372b676d7Smrg "", 50472b676d7Smrg "Single Channel DDR SDRAM", 50572b676d7Smrg "", 50672b676d7Smrg "--unknown--", 50772b676d7Smrg "", 50872b676d7Smrg "--unknown--", 50972b676d7Smrg "", 51072b676d7Smrg "Asymetric Dual Channel SDR SDRAM", 51172b676d7Smrg "", 51272b676d7Smrg "Asymetric Dual Channel DDR SDRAM", 51372b676d7Smrg "", 51472b676d7Smrg "Dual channel SDR SDRAM", 51572b676d7Smrg "", 51672b676d7Smrg "Dual channel DDR SDRAM", 51772b676d7Smrg "" 51872b676d7Smrg }; 51972b676d7Smrg char *dramTypeStr340[] = { 52072b676d7Smrg "Single channel DDR SDRAM", 52172b676d7Smrg "Single channel DDR2 SDRAM", 52272b676d7Smrg "Single channel DDR2x SDRAM", 52372b676d7Smrg "", 52472b676d7Smrg "Dual channel DDR SDRAM", 52572b676d7Smrg "Dual channel DDR2 SDRAM", 52672b676d7Smrg "Dual channel DDR2x SDRAM", 52772b676d7Smrg "", 52872b676d7Smrg "Dual channel DDR SDRAM", 52972b676d7Smrg "Dual channel DDR2 SDRAM", 53072b676d7Smrg "Dual channel DDR2x SDRAM", 53172b676d7Smrg "", 53272b676d7Smrg "Quad channel DDR SDRAM", 53372b676d7Smrg "Quad channel DDR2 SDRAM", 53472b676d7Smrg "Quad channel DDR2x SDRAM", 53572b676d7Smrg "" 53672b676d7Smrg }; 53772b676d7Smrg 53872b676d7Smrg inSISIDXREG(SISSR, 0x14, config); 53972b676d7Smrg config1 = (config & 0x0C) >> 2; 54072b676d7Smrg 54172b676d7Smrg inSISIDXREG(SISSR, 0x3a, sr3a); 54272b676d7Smrg config2 = sr3a & 0x03; 54372b676d7Smrg 54472b676d7Smrg inSISIDXREG(SISCR,0x5f,cr5f); 54572b676d7Smrg 54672b676d7Smrg pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024; 54772b676d7Smrg 54872b676d7Smrg pSiS->IsPCIExpress = FALSE; 54972b676d7Smrg 55072b676d7Smrg switch(pSiS->Chipset) { 55172b676d7Smrg 55272b676d7Smrg case PCI_CHIP_SIS340: 55372b676d7Smrg case PCI_CHIP_XGIXG20: 55472b676d7Smrg case PCI_CHIP_XGIXG40: 55572b676d7Smrg 55672b676d7Smrg if(pSiS->ChipType != XGI_20) { /* SIS340, XGI_40 */ 55772b676d7Smrg 55872b676d7Smrg pSiS->IsAGPCard = TRUE; 55972b676d7Smrg 56072b676d7Smrg if(pSiS->ChipRev == 2) { 56172b676d7Smrg if(config1 & 0x01) config1 = 0x02; 56272b676d7Smrg else config1 = 0x00; 56372b676d7Smrg } 56472b676d7Smrg if(config1 == 0x02) pScrn->videoRam <<= 1; /* dual rank */ 56572b676d7Smrg else if(config1 == 0x03) pScrn->videoRam <<= 2; /* quad rank */ 56672b676d7Smrg 56772b676d7Smrg inSISIDXREG(SISSR, 0x39, config2); 56872b676d7Smrg config2 &= 0x02; 56972b676d7Smrg if(!config2) { 57072b676d7Smrg inSISIDXREG(SISSR, 0x3a, config2); 57172b676d7Smrg config2 = (config2 & 0x02) >> 1; 57272b676d7Smrg } 57372b676d7Smrg 57472b676d7Smrg pSiS->BusWidth = (config & 0x02) ? 64 : 32; 57572b676d7Smrg 57672b676d7Smrg } else { /* XGI_20 (Z7) */ 57772b676d7Smrg 57872b676d7Smrg config1 = 0x00; 57972b676d7Smrg inSISIDXREG(SISCR, 0x97, config2); 58072b676d7Smrg config2 &= 0x01; 58172b676d7Smrg config2 <<= 1; /* 0 or 2 */ 58272b676d7Smrg 58372b676d7Smrg pSiS->BusWidth = (config & 0x02) ? 32 : 58472b676d7Smrg ((config & 0x01) ? 16 : 8); 58572b676d7Smrg 58672b676d7Smrg } 58772b676d7Smrg 58872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 58972b676d7Smrg "DRAM type: %s\n", dramTypeStr340[(config1 * 4) + (config2 & 0x03)]); 59072b676d7Smrg 59172b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 59272b676d7Smrg 59372b676d7Smrg pSiS->MemClock *= 2; /* at least DDR */ 59472b676d7Smrg 59572b676d7Smrg break; 59672b676d7Smrg 59772b676d7Smrg case PCI_CHIP_SIS330: 59872b676d7Smrg 59972b676d7Smrg pSiS->IsAGPCard = TRUE; 60072b676d7Smrg 60172b676d7Smrg if(config1) pScrn->videoRam <<= 1; 60272b676d7Smrg 60372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 60472b676d7Smrg "DRAM type: %s\n", dramTypeStr330[(config1 * 4) + (config2 & 0x02)]); 60572b676d7Smrg 60672b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 60772b676d7Smrg 60872b676d7Smrg if(config2 & 0x02) { 60972b676d7Smrg pSiS->MemClock *= 2; 61072b676d7Smrg if(config1 == 0x02) { 61172b676d7Smrg pSiS->BusWidth = busDDRA[0]; 61272b676d7Smrg } else { 61372b676d7Smrg pSiS->BusWidth = busDDR[(config & 0x02)]; 61472b676d7Smrg } 61572b676d7Smrg } else { 61672b676d7Smrg if(config1 == 0x02) { 61772b676d7Smrg pSiS->BusWidth = busDDRA[2]; 61872b676d7Smrg } else { 61972b676d7Smrg pSiS->BusWidth = busSDR[(config & 0x02)]; 62072b676d7Smrg } 62172b676d7Smrg } 62272b676d7Smrg 62372b676d7Smrg break; 62472b676d7Smrg 62572b676d7Smrg default: /* 315 */ 62672b676d7Smrg 62772b676d7Smrg pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE; 62872b676d7Smrg 62972b676d7Smrg if(cr5f & 0x10) pSiS->ChipFlags |= SiSCF_Is315E; 63072b676d7Smrg 63172b676d7Smrg /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */ 63272b676d7Smrg if((config1 == 0x01) || (config1 == 0x03)) pScrn->videoRam <<= 1; 63372b676d7Smrg 63472b676d7Smrg /* If DDR asymetric -> mem * 1,5 */ 63572b676d7Smrg if(config1 == 0x02) pScrn->videoRam += pScrn->videoRam/2; 63672b676d7Smrg 63772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 63872b676d7Smrg "DRAM type: %s\n", dramTypeStr315[(config1 * 4) + config2]); 63972b676d7Smrg 64072b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 64172b676d7Smrg 64272b676d7Smrg /* If DDR -> memclock * 2 */ 64372b676d7Smrg if(config2 & 0x02) pSiS->MemClock *= 2; 64472b676d7Smrg 64572b676d7Smrg if(config1 == 0x02) 64672b676d7Smrg pSiS->BusWidth = busDDRA[(config & 0x03)]; 64772b676d7Smrg else if(config2 & 0x02) 64872b676d7Smrg pSiS->BusWidth = busDDR[(config & 0x03)]; 64972b676d7Smrg else 65072b676d7Smrg pSiS->BusWidth = busSDR[(config & 0x03)]; 65172b676d7Smrg 65272b676d7Smrg if(pSiS->ChipFlags & SiSCF_Is315E) { 65372b676d7Smrg inSISIDXREG(SISSR,0x15,config); 65472b676d7Smrg if(config & 0x10) pSiS->BusWidth = 32; 65572b676d7Smrg } 65672b676d7Smrg 65772b676d7Smrg } 65872b676d7Smrg 65972b676d7Smrg pSiS->LFBsize = pScrn->videoRam; 66072b676d7Smrg 66172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 66272b676d7Smrg "Memory clock: %3.3f MHz\n", 66372b676d7Smrg pSiS->MemClock/1000.0); 66472b676d7Smrg 66572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 66672b676d7Smrg "DRAM bus width: %d bit\n", 66772b676d7Smrg pSiS->BusWidth); 66872b676d7Smrg} 66972b676d7Smrg 67072b676d7Smrg/* For 550, 65x, 740, 661, 741, 660, 760, 761 */ 67172b676d7Smrgstatic void 67272b676d7Smrgsis550Setup(ScrnInfoPtr pScrn) 67372b676d7Smrg{ 67472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 67572b676d7Smrg unsigned int config, ramtype=0, i; 67672b676d7Smrg CARD8 pciconfig, temp; 67772b676d7Smrg Bool alldone = FALSE; 67872b676d7Smrg Bool ddrtimes2 = TRUE; 67972b676d7Smrg 68072b676d7Smrg pSiS->IsAGPCard = TRUE; 68172b676d7Smrg pSiS->IsPCIExpress = FALSE; 68272b676d7Smrg pSiS->ChipFlags &= ~(SiSCF_760UMA | SiSCF_760LFB); 68372b676d7Smrg 68472b676d7Smrg pSiS->MemClock = SiSMclk(pSiS); 68572b676d7Smrg 68672b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS660) { 68772b676d7Smrg 68872b676d7Smrg if(pSiS->ChipType >= SIS_660) { 68972b676d7Smrg 69072b676d7Smrg /* UMA - shared fb */ 69172b676d7Smrg pScrn->videoRam = 0; 6921fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x4c); 69372b676d7Smrg if(pciconfig & 0xe0) { 69472b676d7Smrg pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768; 69572b676d7Smrg pSiS->ChipFlags |= SiSCF_760UMA; 69672b676d7Smrg pSiS->SiS76xUMASize = pScrn->videoRam * 1024; 69772b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 69872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 69972b676d7Smrg "%dK shared video RAM (UMA)\n", 70072b676d7Smrg pScrn->videoRam); 70172b676d7Smrg } 70272b676d7Smrg 70372b676d7Smrg /* LFB - local framebuffer: PCI reg hold total RAM (but configurable in BIOS) */ 7041fd23544Smrg /* TODO */ 7051fd23544Smrg pciconfig = sis_pci_read_device_u8(1, 0xcd); 70672b676d7Smrg pciconfig = (pciconfig >> 1) & 0x03; 70772b676d7Smrg i = 0; 70872b676d7Smrg if(pciconfig == 0x01) i = 32768; 70972b676d7Smrg else if(pciconfig == 0x03) i = 65536; 71072b676d7Smrg if(i) { 71172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK total local video RAM (LFB)\n", i); 71272b676d7Smrg } 71372b676d7Smrg 71472b676d7Smrg /* LFB: CR78 holds amount of LFB memory configured in the BIOS setup */ 71572b676d7Smrg inSISIDXREG(SISCR, 0x78, config); 71672b676d7Smrg config &= 0x30; 71772b676d7Smrg if(config) { 71872b676d7Smrg i = 0; 71972b676d7Smrg if(config == 0x10) i = 32768; 72072b676d7Smrg else if(config == 0x30) i = 65536; 72172b676d7Smrg if(i) { 72272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK configured local video RAM (LFB)\n", i); 72372b676d7Smrg pScrn->videoRam += i; 72472b676d7Smrg pSiS->ChipFlags |= SiSCF_760LFB; 72572b676d7Smrg pSiS->SiS76xLFBSize = i * 1024; 72672b676d7Smrg pSiS->LFBsize = i; 72772b676d7Smrg } 72872b676d7Smrg } 72972b676d7Smrg 73072b676d7Smrg if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) { 73172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 73272b676d7Smrg "Illegal video RAM size (%dK) detected, using BIOS provided setting\n", 73372b676d7Smrg pScrn->videoRam); 73472b676d7Smrg pSiS->ChipFlags &= ~(SiSCF_760LFB | SiSCF_760UMA); 73572b676d7Smrg } else { 73672b676d7Smrg pSiS->BusWidth = 64; 73772b676d7Smrg ramtype = 8; 73872b676d7Smrg alldone = TRUE; 73972b676d7Smrg } 74072b676d7Smrg 74172b676d7Smrg if(pSiS->ChipType >= SIS_761) { 74272b676d7Smrg pSiS->IsAGPCard = FALSE; 74372b676d7Smrg pSiS->IsPCIExpress = TRUE; 74472b676d7Smrg } 74572b676d7Smrg 74672b676d7Smrg } else { /* 661, 741 */ 74772b676d7Smrg 74872b676d7Smrg int dimmnum; 74972b676d7Smrg 75072b676d7Smrg if(pSiS->ChipType == SIS_741) { 75172b676d7Smrg dimmnum = 4; 75272b676d7Smrg } else { 75372b676d7Smrg dimmnum = 3; 75472b676d7Smrg } 75572b676d7Smrg 7561fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x64); 75772b676d7Smrg if(pciconfig & 0x80) { 75872b676d7Smrg pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768; 75972b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 76072b676d7Smrg if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) { 76172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 76272b676d7Smrg "Illegal video RAM size (%dK) detected, using BIOS-provided info\n", 76372b676d7Smrg pScrn->videoRam); 76472b676d7Smrg } else { 76572b676d7Smrg pSiS->BusWidth = 64; 76672b676d7Smrg for(i = 0; i <= (dimmnum - 1); i++) { 76772b676d7Smrg if(pciconfig & (1 << i)) { 7681fd23544Smrg temp = sis_pci_read_host_bridge_u8(0x60 + i); 76972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 77072b676d7Smrg "DIMM%d is %s SDRAM\n", 77172b676d7Smrg i, (temp & 0x40) ? "DDR" : "SDR"); 77272b676d7Smrg } else { 77372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 77472b676d7Smrg "DIMM%d is not installed\n", i); 77572b676d7Smrg } 77672b676d7Smrg } 7771fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x7c); 77872b676d7Smrg ramtype = (pciconfig & 0x02) ? 8 : 4; 77972b676d7Smrg alldone = TRUE; 78072b676d7Smrg } 78172b676d7Smrg } 78272b676d7Smrg 78372b676d7Smrg } 78472b676d7Smrg 78572b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS650) { 78672b676d7Smrg 7871fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x64); 78872b676d7Smrg if(pciconfig & 0x80) { 78972b676d7Smrg pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024; 79072b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 79172b676d7Smrg pSiS->BusWidth = 64; 79272b676d7Smrg for(i=0; i<=3; i++) { 79372b676d7Smrg if(pciconfig & (1 << i)) { 7941fd23544Smrg temp = sis_pci_read_host_bridge_u8(0x60 + i); 79572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 79672b676d7Smrg "DIMM%d is %s SDRAM\n", 79772b676d7Smrg i, (temp & 0x40) ? "DDR" : "SDR"); 79872b676d7Smrg } else { 79972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 80072b676d7Smrg "DIMM%d is not installed\n", i); 80172b676d7Smrg } 80272b676d7Smrg } 8031fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x7c); 80472b676d7Smrg if(pciconfig & 0x02) ramtype = 8; 80572b676d7Smrg else ramtype = 4; 80672b676d7Smrg alldone = TRUE; 80772b676d7Smrg } 80872b676d7Smrg 80972b676d7Smrg } else { 8101fd23544Smrg pciconfig = sis_pci_read_host_bridge_u8(0x63); 81172b676d7Smrg if(pciconfig & 0x80) { 81272b676d7Smrg pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024; 81372b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 81472b676d7Smrg pSiS->BusWidth = 64; 8151fd23544Smrg ramtype = sis_pci_read_host_bridge_u8(0x65); 81672b676d7Smrg ramtype &= 0x01; 81772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 81872b676d7Smrg "Shared Memory Area is on DIMM%d\n", ramtype); 81972b676d7Smrg ramtype = 4; 82072b676d7Smrg alldone = TRUE; 82172b676d7Smrg } 82272b676d7Smrg 82372b676d7Smrg } 82472b676d7Smrg 82572b676d7Smrg /* Fall back to BIOS detection results in case of problems: */ 82672b676d7Smrg 82772b676d7Smrg if(!alldone) { 82872b676d7Smrg 82972b676d7Smrg pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0; 83072b676d7Smrg pSiS->UMAsize = pSiS->LFBsize = 0; 83172b676d7Smrg 83272b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS660) { 83372b676d7Smrg inSISIDXREG(SISCR, 0x79, config); 83472b676d7Smrg pSiS->BusWidth = (config & 0x04) ? 128 : 64; 83572b676d7Smrg ramtype = (config & 0x01) ? 8 : 4; 83672b676d7Smrg if(pSiS->ChipType >= SIS_660) { 83772b676d7Smrg pScrn->videoRam = 0; 83872b676d7Smrg if(config & 0xf0) { 83972b676d7Smrg pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024; 84072b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 84172b676d7Smrg pSiS->ChipFlags |= SiSCF_760UMA; 84272b676d7Smrg pSiS->SiS76xUMASize = pScrn->videoRam * 1024; 84372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 84472b676d7Smrg "%dK shared video RAM (UMA)\n", 84572b676d7Smrg pScrn->videoRam); 84672b676d7Smrg } 84772b676d7Smrg inSISIDXREG(SISCR, 0x78, config); 84872b676d7Smrg config &= 0x30; 84972b676d7Smrg if(config) { 85072b676d7Smrg i = 0; 85172b676d7Smrg if(config == 0x10) i = 32768; 85272b676d7Smrg else if(config == 0x30) i = 65536; 85372b676d7Smrg if(i) { 85472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 85572b676d7Smrg "%dK configured local video RAM (LFB)\n", i); 85672b676d7Smrg pScrn->videoRam += i; 85772b676d7Smrg pSiS->SiS76xLFBSize = i * 1024; 85872b676d7Smrg pSiS->LFBsize = i; 85972b676d7Smrg pSiS->ChipFlags |= SiSCF_760LFB; 86072b676d7Smrg 86172b676d7Smrg } 86272b676d7Smrg } 86372b676d7Smrg } else { 86472b676d7Smrg pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024; 86572b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 86672b676d7Smrg } 86772b676d7Smrg } else { 86872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 86972b676d7Smrg "Shared Memory Area is disabled - awaiting doom\n"); 87072b676d7Smrg inSISIDXREG(SISSR, 0x14, config); 87172b676d7Smrg pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024; 87272b676d7Smrg pSiS->UMAsize = pScrn->videoRam; 87372b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS650) { 87472b676d7Smrg ramtype = (((config & 0x80) >> 7) << 2) + 4; 87572b676d7Smrg pSiS->BusWidth = 64; /* (config & 0x40) ? 128 : 64; */ 87672b676d7Smrg } else { 87772b676d7Smrg ramtype = 4; 87872b676d7Smrg pSiS->BusWidth = 64; 87972b676d7Smrg } 88072b676d7Smrg } 88172b676d7Smrg } 88272b676d7Smrg 88372b676d7Smrg /* These need special attention: Memory controller in CPU, hence 88472b676d7Smrg * - no DDR * 2 for bandwidth calculation, 88572b676d7Smrg * - overlay magic (bandwidth dependent one/two overlay stuff) 88672b676d7Smrg */ 88772b676d7Smrg if((pSiS->ChipType >= SIS_760) && (pSiS->ChipType <= SIS_770)) { 88872b676d7Smrg if(!(pSiS->ChipFlags & SiSCF_760LFB)) { 88972b676d7Smrg ddrtimes2 = FALSE; 89072b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT760OO; 89172b676d7Smrg } 89272b676d7Smrg } 89372b676d7Smrg 89472b676d7Smrg /* DDR -> Mclk * 2 - needed for bandwidth calculation */ 89572b676d7Smrg if(ddrtimes2) { 89672b676d7Smrg if(ramtype == 8) pSiS->MemClock *= 2; 89772b676d7Smrg } 89872b676d7Smrg 89972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 90072b676d7Smrg "DRAM type: %s\n", 90172b676d7Smrg dramTypeStr[ramtype]); 90272b676d7Smrg 90372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 90472b676d7Smrg "Memory clock: %3.3f MHz\n", 90572b676d7Smrg pSiS->MemClock/1000.0); 90672b676d7Smrg 90772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 90872b676d7Smrg "DRAM bus width: %d bit\n", 90972b676d7Smrg pSiS->BusWidth); 91072b676d7Smrg} 91172b676d7Smrg 91272b676d7Smrgvoid 91372b676d7SmrgSiSSetup(ScrnInfoPtr pScrn) 91472b676d7Smrg{ 91572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 91672b676d7Smrg 91772b676d7Smrg pSiS->Flags = 0; 91872b676d7Smrg pSiS->VBFlags = 0; 91972b676d7Smrg pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0; 92072b676d7Smrg pSiS->UMAsize = pSiS->LFBsize = 0; 92172b676d7Smrg 92272b676d7Smrg switch (SISPTR(pScrn)->Chipset) { 92372b676d7Smrg case PCI_CHIP_SIS300: 92472b676d7Smrg case PCI_CHIP_SIS630: /* +730 */ 92572b676d7Smrg case PCI_CHIP_SIS540: 92672b676d7Smrg sis300Setup(pScrn); 92772b676d7Smrg break; 92872b676d7Smrg case PCI_CHIP_SIS315: 92972b676d7Smrg case PCI_CHIP_SIS315H: 93072b676d7Smrg case PCI_CHIP_SIS315PRO: 93172b676d7Smrg case PCI_CHIP_SIS330: 93272b676d7Smrg case PCI_CHIP_SIS340: 93372b676d7Smrg case PCI_CHIP_XGIXG20: 93472b676d7Smrg case PCI_CHIP_XGIXG40: 93572b676d7Smrg sis315Setup(pScrn); 93672b676d7Smrg break; 93772b676d7Smrg case PCI_CHIP_SIS550: 93872b676d7Smrg case PCI_CHIP_SIS650: /* + 740,M650,651 */ 93972b676d7Smrg case PCI_CHIP_SIS660: /* + (M)661,(M)741,(M)760(GX), (M)761(GX), 770? */ 94072b676d7Smrg sis550Setup(pScrn); 94172b676d7Smrg break; 94272b676d7Smrg case PCI_CHIP_SIS5597: 94372b676d7Smrg case PCI_CHIP_SIS6326: 94472b676d7Smrg case PCI_CHIP_SIS530: 94572b676d7Smrg default: 94672b676d7Smrg sisOldSetup(pScrn); 94772b676d7Smrg break; 94872b676d7Smrg } 94972b676d7Smrg} 95072b676d7Smrg 95172b676d7Smrg 952