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