sis_setup.c revision 1fd23544
1/*
2 * Basic hardware and memory detection
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1) Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2) Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3) The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author:  	Thomas Winischhofer <thomas@winischhofer.net>
29 *
30 * Ideas and methods for old series based on code by Can-Ru Yeou, SiS Inc.
31 *
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include "sis.h"
39#define SIS_NEED_inSISREGW
40#define SIS_NEED_inSISREGL
41#define SIS_NEED_outSISREGW
42#define SIS_NEED_outSISREGL
43#define SIS_NEED_inSISIDXREG
44#define SIS_NEED_outSISIDXREG
45#include "sis_regs.h"
46
47extern int SiSMclk(SISPtr pSiS);
48
49static const char *dramTypeStr[] = {
50	"Fast Page DRAM",
51	"2 cycle EDO RAM",
52	"1 cycle EDO RAM",
53	"SDRAM/SGRAM",
54	"SDR SDRAM",
55	"SGRAM",
56	"ESDRAM",
57	"DDR SDRAM",  /* for 550/650/etc */
58	"DDR SDRAM",  /* for 550/650/etc */
59	"VCM",	      /* for 630 */
60	"DDR2 SDRAM", /* for 340 */
61	""
62};
63
64/* MCLK tables for SiS6326 */
65static const int SiS6326MCLKIndex[4][8] = {
66	{ 10, 12, 14, 16, 17, 18, 19,  7 },  /* SGRAM */
67	{  4,  6,  8, 10, 11, 12, 13,  3 },  /* Fast Page */
68	{  9, 11, 12, 13, 15, 16,  5,  7 },  /* 2 cycle EDO */
69	{ 10, 12, 14, 16, 17, 18, 19,  7 }   /* ? (Not 1 cycle EDO) */
70};
71
72static const struct _sis6326mclk {
73    CARD16 mclk;
74    UChar  sr13;
75    UChar  sr28;
76    UChar  sr29;
77} SiS6326MCLK[] = {
78	{  0, 0,    0,    0 },
79	{  0, 0,    0,    0 },
80	{  0, 0,    0,    0 },
81	{ 45, 0, 0x2b, 0x26 },
82	{ 53, 0, 0x49, 0xe4 },
83	{ 55, 0, 0x7c, 0xe7 },
84	{ 56, 0, 0x7c, 0xe7 },
85	{ 60, 0, 0x42, 0xe3 },
86	{ 61, 0, 0x21, 0xe1 },
87	{ 65, 0, 0x5a, 0xe4 },
88	{ 66, 0, 0x5a, 0xe4 },
89	{ 70, 0, 0x61, 0xe4 },
90	{ 75, 0, 0x3e, 0xe2 },
91	{ 80, 0, 0x42, 0xe2 },
92	{ 83, 0, 0xb3, 0xc5 },
93	{ 85, 0, 0x5e, 0xe3 },
94	{ 90, 0, 0xae, 0xc4 },
95	{100, 0, 0x37, 0xe1 },
96	{115, 0, 0x78, 0x0e },
97	{134, 0, 0x4a, 0xa3 }
98};
99
100#ifdef XSERVER_LIBPCIACCESS
101struct pci_device *
102sis_get_device (int device)
103{
104    struct pci_slot_match bridge_match = {
105	0, 0, device, PCI_MATCH_ANY, 0
106    };
107    struct pci_device_iterator	*slot_iterator;
108    struct pci_device		*bridge;
109
110    slot_iterator = pci_slot_match_iterator_create (&bridge_match);
111    bridge = pci_device_next (slot_iterator);
112    pci_iterator_destroy (slot_iterator);
113    return bridge;
114}
115
116unsigned int
117sis_pci_read_device_u32(int device, int offset)
118{
119    struct pci_device *host_bridge = sis_get_device(device);
120    unsigned int result;
121
122    pci_device_cfg_read_u32(host_bridge, &result, offset);
123    return result;
124}
125
126unsigned char
127sis_pci_read_device_u8(int device, int offset)
128{
129    struct pci_device *host_bridge = sis_get_device(device);
130    unsigned char result;
131
132    pci_device_cfg_read_u8(host_bridge, &result, offset);
133    return result;
134}
135
136void
137sis_pci_write_host_bridge_u32(int offset, unsigned int value)
138{
139    struct pci_device *host_bridge = sis_get_device(0);
140    pci_device_cfg_write_u32(host_bridge, value, offset);
141}
142
143void
144sis_pci_write_host_bridge_u8(int offset, unsigned char value)
145{
146    struct pci_device *host_bridge = sis_get_device(0);
147    pci_device_cfg_write_u8(host_bridge, value, offset);
148}
149
150#else
151unsigned int
152sis_pci_read_device_u32(int device, int offset)
153{
154    PCITAG tag = pciTag(0, device, 0);
155    return pciReadLong(tag, offset);
156}
157
158unsigned char
159sis_pci_read_device_u8(int device, int offset)
160{
161    PCITAG tag = pciTag(0, device, 0);
162    return pciReadByte(tag, offset);
163}
164
165void
166sis_pci_write_host_bridge_u32(int offset, unsigned int value)
167{
168    pciWriteLong(0x00000000, offset, value);
169}
170
171void
172sis_pci_write_host_bridge_u8(int offset, unsigned char value)
173{
174    pciWriteByte(0x00000000, offset, value);
175}
176
177
178#endif
179
180unsigned int
181sis_pci_read_host_bridge_u32(int offset)
182{
183    return sis_pci_read_device_u32(0, offset);
184}
185
186unsigned char
187sis_pci_read_host_bridge_u8(int offset)
188{
189    return sis_pci_read_device_u8(0, offset);
190}
191
192static int sisESSPresent(ScrnInfoPtr pScrn)
193{
194  int flags = 0;
195#ifndef XSERVER_LIBPCIACCESS
196  int i;
197  pciConfigPtr pdptr, *systemPCIdevices = NULL;
198
199  if((systemPCIdevices = xf86GetPciConfigInfo())) {
200      i = 0;
201      while((pdptr = systemPCIdevices[i])) {
202	  if((pdptr->pci_vendor == 0x1274) &&
203	     ((pdptr->pci_device == 0x5000) ||
204	      ((pdptr->pci_device & 0xFFF0) == 0x1370))) {
205	      flags |= ESS137xPRESENT;
206	      break;
207	  }
208	  i++;
209      }
210  }
211  return flags;
212#else
213  struct pci_id_match id_match = { 0x1274, PCI_MATCH_ANY,
214				   PCI_MATCH_ANY, PCI_MATCH_ANY,
215				   PCI_MATCH_ANY, PCI_MATCH_ANY,
216				   0 };
217  struct pci_device_iterator *id_iterator;
218  struct pci_device *ess137x;
219
220  id_iterator = pci_id_match_iterator_create(&id_match);
221
222  ess137x = pci_device_next(id_iterator);
223  while (ess137x) {
224      if ((ess137x->device_id == 0x5000) ||
225	  ((ess137x->device_id & 0xfff0) == 0x1370)) {
226	  flags |= ESS137xPRESENT;
227      }
228      ess137x = pci_device_next(id_iterator);
229  }
230  return flags;
231#endif
232}
233
234/* For old chipsets, 5597, 6326, 530/620 */
235static void
236sisOldSetup(ScrnInfoPtr pScrn)
237{
238    SISPtr pSiS = SISPTR(pScrn);
239    int    ramsize[8]  = { 1,  2,  4, 0, 0,  2,  4,  8};
240    int    buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 };
241    int    clockTable[4] = { 66, 75, 83, 100 };
242    int    ramtype[4]  = { 5, 0, 1, 3 };
243    int    config, temp, i;
244    UChar  sr23, sr33, sr37;
245#if 0
246    UChar  newsr13, newsr28, newsr29;
247#endif
248
249
250    if(pSiS->oldChipset <= OC_SIS6225) {
251	inSISIDXREG(SISSR, 0x0F, temp);
252	pScrn->videoRam = (1 << (temp & 0x03)) * 1024;
253	if(pScrn->videoRam > 4096) pScrn->videoRam = 4096;
254	pSiS->BusWidth = 32;
255    } else if(pSiS->Chipset == PCI_CHIP_SIS5597) {
256	inSISIDXREG(SISSR, 0x2F, temp);
257	pScrn->videoRam = ((temp & 0x07) + 1) * 256;
258	inSISIDXREG(SISSR, 0x0C, temp);
259	if(temp & 0x06) {
260		pScrn->videoRam *= 2;
261		pSiS->BusWidth = 64;
262	} else  pSiS->BusWidth = 32;
263    } else {
264	inSISIDXREG(SISSR, 0x0C, temp);
265	config = ((temp & 0x10) >> 2 ) | ((temp & 0x06) >> 1);
266	pScrn->videoRam = ramsize[config] * 1024;
267	pSiS->BusWidth = buswidth[config];
268    }
269
270    if(pSiS->Chipset == PCI_CHIP_SIS530)  {
271
272	inSISIDXREG(SISSR, 0x0D, temp);
273	pSiS->Flags &= ~(UMA);
274	if(temp & 0x01) {
275		pSiS->Flags |= UMA;  		/* Shared fb mode */
276		inSISIDXREG(SISSR, 0x10, temp);
277		pSiS->MemClock = clockTable[temp & 0x03] * 1000;
278	} else  {
279		pSiS->MemClock = SiSMclk(pSiS); /* Local fb mode */
280	}
281
282    } else if(pSiS->Chipset == PCI_CHIP_SIS6326) {
283
284	inSISIDXREG(SISSR,0x0e,temp);
285
286	i = temp & 0x03;
287
288	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
289	    "DRAM type: %s\n",
290	    dramTypeStr[ramtype[i]]);
291
292	temp = (temp >> 5) & 0x07;
293	i = SiS6326MCLKIndex[i][temp];
294	pSiS->MemClock = SiS6326MCLK[i].mclk;
295#if 0
296	/* Correct invalid MCLK settings by old BIOSes */
297	newsr13 = SiS6326MCLK[i].sr13;
298	newsr28 = SiS6326MCLK[i].sr28;
299	newsr29 = SiS6326MCLK[i].sr29;
300	if((pSiS->ChipRev == 0x92) ||
301	   (pSiS->ChipRev == 0xd1) ||
302	   (pSiS->ChipRev == 0xd2)) {
303	   if(pSiS->MemClock == 60) {
304	      newsr28 = 0xae;
305	      newsr29 = 0xc4;
306	   }
307	}
308#endif
309	pSiS->MemClock *= 1000;
310#if 0
311	inSISIDXREG(SISSR, 0x13, temp);
312	temp &= 0x80;
313	temp |= (newsr13 & 0x80);
314	outSISIDXREG(SISSR,0x13,temp);
315	outSISIDXREG(SISSR,0x28,newsr28);
316	outSISIDXREG(SISSR,0x29,newsr29);
317#endif
318
319    } else {
320
321	pSiS->MemClock = SiSMclk(pSiS);
322
323    }
324
325    pSiS->Flags &= ~(SYNCDRAM | RAMFLAG);
326    if(pSiS->oldChipset >= OC_SIS82204) {
327       inSISIDXREG(SISSR, 0x23, sr23);
328       inSISIDXREG(SISSR, 0x33, sr33);
329       if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08;
330       if(sr33 & 0x09) {				/* 5597: Sync DRAM timing | One cycle EDO ram;   */
331		pSiS->Flags |= (sr33 & SYNCDRAM);	/* 6326: Enable SGRam timing | One cycle EDO ram */
332		pSiS->Flags |= RAMFLAG;			/* 530:  Enable SGRAM timing | reserved (0)      */
333       } else if((pSiS->oldChipset < OC_SIS530A) && (sr23 & 0x20)) {
334		pSiS->Flags |= SYNCDRAM;		/* 5597, 6326: EDO DRAM enabled */
335       }						/* 530/620:    reserved (0)     */
336    }
337
338    pSiS->Flags &= ~(ESS137xPRESENT);
339    if(pSiS->Chipset == PCI_CHIP_SIS530) {
340       if(pSiS->oldChipset == OC_SIS530A) {
341	   pSiS->Flags |= sisESSPresent(pScrn);
342       }
343       if(pSiS->Flags & ESS137xPRESENT) {
344	   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
345		      "SiS530/620: Found ESS device\n");
346       }
347    }
348
349    pSiS->Flags &= ~(SECRETFLAG);
350    if(pSiS->oldChipset >= OC_SIS5597) {
351	inSISIDXREG(SISSR, 0x37, sr37);
352	if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG;
353    }
354
355    pSiS->Flags &= ~(A6326REVAB);
356    if(pSiS->Chipset == PCI_CHIP_SIS6326) {
357       if(((pSiS->ChipRev & 0x0f) == 0x0a) ||
358	  ((pSiS->ChipRev & 0x0f) == 0x0b)) {
359	    pSiS->Flags |= A6326REVAB;
360       }
361    }
362
363    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
364	       "Memory clock: %3.3f MHz\n",
365	       pSiS->MemClock/1000.0);
366
367    if(pSiS->oldChipset > OC_SIS6225) {
368       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
369	       "DRAM bus width: %d bit\n",
370	       pSiS->BusWidth);
371    }
372
373#ifdef TWDEBUG
374    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
375		"oldChipset = %d, Flags %x\n", pSiS->oldChipset, pSiS->Flags);
376#endif
377}
378
379static void
380sis300Setup(ScrnInfoPtr pScrn)
381{
382    SISPtr    pSiS = SISPTR(pScrn);
383    const int bus[4] = {32, 64, 128, 32};
384    const int adaptermclk[8]    = {  66,  83, 100, 133,
385                                    100, 100, 100, 100};
386    const int adaptermclk300[8] = { 125, 125, 125, 100,
387                                    100, 100, 100, 100};
388    unsigned int config, pciconfig, sr3a, ramtype;
389    UChar        temp;
390    int		 cpubuswidth;
391    MessageType	 from = X_PROBED;
392
393    pSiS->MemClock = SiSMclk(pSiS);
394
395    inSISIDXREG(SISSR, 0x14, config);
396    cpubuswidth = bus[config >> 6];
397
398    inSISIDXREG(SISSR, 0x3A, sr3a);
399    ramtype = (sr3a & 0x03) + 4;
400
401    pSiS->IsPCIExpress = FALSE;
402
403    switch(pSiS->Chipset) {
404    case PCI_CHIP_SIS300:
405	pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
406	pSiS->LFBsize = pScrn->videoRam;
407	pSiS->BusWidth = cpubuswidth;
408	pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
409	break;
410    case PCI_CHIP_SIS540:
411    case PCI_CHIP_SIS630:
412	pSiS->IsAGPCard = TRUE;
413	pciconfig = sis_pci_read_host_bridge_u8(0x63);
414	if(pciconfig & 0x80) {
415	   pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
416	   pSiS->BusWidth = 64;
417	   pciconfig = sis_pci_read_host_bridge_u8(0x64);
418	   if((pciconfig & 0x30) == 0x30) {
419	      pSiS->BusWidth = 128;
420	      pScrn->videoRam <<= 1;
421	   }
422	   ramtype = sis_pci_read_host_bridge_u8(0x65);
423	   ramtype &= 0x03;
424	   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
425		"Shared Memory Area is on DIMM%d\n", ramtype);
426	   ramtype = sis_pci_read_host_bridge_u8(0x60 + ramtype);
427	   if(ramtype & 0x80) ramtype = 9;
428	   else               ramtype = 4;
429	   pSiS->UMAsize = pScrn->videoRam;
430	} else {
431	   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
432		"Shared Memory Area is disabled - awaiting doom\n");
433	   pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
434	   pSiS->UMAsize = pScrn->videoRam;
435	   pSiS->BusWidth = 64;
436	   ramtype = 4;
437	   from = X_INFO;
438	}
439	break;
440    default:
441	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
442		"Internal error: sis300setup() called with invalid chipset!\n");
443	pSiS->BusWidth = 64;
444	from = X_INFO;
445    }
446
447    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
448	    "DRAM type: %s\n",
449	    dramTypeStr[ramtype]);
450
451    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
452	    "Memory clock: %3.3f MHz\n",
453	    pSiS->MemClock/1000.0);
454
455    if(pSiS->Chipset == PCI_CHIP_SIS300) {
456       if(pSiS->ChipRev > 0x13) {
457	  inSISIDXREG(SISSR, 0x3A, temp);
458	  xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
459	     "(Adapter assumes MCLK being %d Mhz)\n",
460	     adaptermclk300[(temp & 0x07)]);
461       }
462    } else {
463       inSISIDXREG(SISSR, 0x1A, temp);
464       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
465	    "(Adapter assumes MCLK being %d Mhz)\n",
466	    adaptermclk[(temp & 0x07)]);
467    }
468
469    xf86DrvMsg(pScrn->scrnIndex, from,
470	    "DRAM bus width: %d bit\n",
471	    pSiS->BusWidth);
472}
473
474/* For 315, 315H, 315PRO/E, 330, 340 */
475static void
476sis315Setup(ScrnInfoPtr pScrn)
477{
478    SISPtr  pSiS = SISPTR(pScrn);
479    int     busSDR[4]  = {64, 64, 128, 128};
480    int     busDDR[4]  = {32, 32,  64,  64};
481    int     busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
482    unsigned int config, config1, config2, sr3a, cr5f;
483    char    *dramTypeStr315[] = {
484	"Single channel 1 rank SDR SDRAM",
485	"Single channel 1 rank SDR SGRAM",
486	"Single channel 1 rank DDR SDRAM",
487	"Single channel 1 rank DDR SGRAM",
488	"Single channel 2 rank SDR SDRAM",
489	"Single channel 2 rank SDR SGRAM",
490	"Single channel 2 rank DDR SDRAM",
491	"Single channel 2 rank DDR SGRAM",
492	"Asymmetric SDR SDRAM",
493	"Asymmetric SDR SGRAM",
494	"Asymmetric DDR SDRAM",
495	"Asymmetric DDR SGRAM",
496	"Dual channel SDR SDRAM",
497	"Dual channel SDR SGRAM",
498	"Dual channel DDR SDRAM",
499	"Dual channel DDR SGRAM"
500    };
501    char    *dramTypeStr330[] = {
502	"Single Channel SDR SDRAM",
503	"",
504	"Single Channel DDR SDRAM",
505	"",
506	"--unknown--",
507	"",
508	"--unknown--",
509	"",
510	"Asymetric Dual Channel SDR SDRAM",
511	"",
512	"Asymetric Dual Channel DDR SDRAM",
513	"",
514	"Dual channel SDR SDRAM",
515	"",
516	"Dual channel DDR SDRAM",
517	""
518    };
519    char    *dramTypeStr340[] = {
520	"Single channel DDR SDRAM",
521	"Single channel DDR2 SDRAM",
522	"Single channel DDR2x SDRAM",
523	"",
524	"Dual channel DDR SDRAM",
525	"Dual channel DDR2 SDRAM",
526	"Dual channel DDR2x SDRAM",
527	"",
528	"Dual channel DDR SDRAM",
529	"Dual channel DDR2 SDRAM",
530	"Dual channel DDR2x SDRAM",
531	"",
532	"Quad channel DDR SDRAM",
533	"Quad channel DDR2 SDRAM",
534	"Quad channel DDR2x SDRAM",
535	""
536    };
537
538    inSISIDXREG(SISSR, 0x14, config);
539    config1 = (config & 0x0C) >> 2;
540
541    inSISIDXREG(SISSR, 0x3a, sr3a);
542    config2 = sr3a & 0x03;
543
544    inSISIDXREG(SISCR,0x5f,cr5f);
545
546    pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
547
548    pSiS->IsPCIExpress = FALSE;
549
550    switch(pSiS->Chipset) {
551
552    case PCI_CHIP_SIS340:
553    case PCI_CHIP_XGIXG20:
554    case PCI_CHIP_XGIXG40:
555
556       if(pSiS->ChipType != XGI_20) {	/* SIS340, XGI_40 */
557
558          pSiS->IsAGPCard = TRUE;
559
560          if(pSiS->ChipRev == 2) {
561	     if(config1 & 0x01) config1 = 0x02;
562	     else               config1 = 0x00;
563          }
564          if(config1 == 0x02)      pScrn->videoRam <<= 1; /* dual rank */
565          else if(config1 == 0x03) pScrn->videoRam <<= 2; /* quad rank */
566
567	  inSISIDXREG(SISSR, 0x39, config2);
568	  config2 &= 0x02;
569	  if(!config2) {
570	     inSISIDXREG(SISSR, 0x3a, config2);
571	     config2 = (config2 & 0x02) >> 1;
572          }
573
574	  pSiS->BusWidth = (config & 0x02) ? 64 : 32;
575
576       } else {				/* XGI_20 (Z7) */
577
578	  config1 = 0x00;
579	  inSISIDXREG(SISCR, 0x97, config2);
580	  config2 &= 0x01;
581	  config2 <<= 1;	/* 0 or 2 */
582
583	  pSiS->BusWidth = (config & 0x02) ? 32 :
584				((config & 0x01) ? 16 : 8);
585
586       }
587
588       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
589	    "DRAM type: %s\n", dramTypeStr340[(config1 * 4) + (config2 & 0x03)]);
590
591       pSiS->MemClock = SiSMclk(pSiS);
592
593       pSiS->MemClock *= 2; /* at least DDR */
594
595       break;
596
597    case PCI_CHIP_SIS330:
598
599       pSiS->IsAGPCard = TRUE;
600
601       if(config1) pScrn->videoRam <<= 1;
602
603       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
604	   "DRAM type: %s\n", dramTypeStr330[(config1 * 4) + (config2 & 0x02)]);
605
606       pSiS->MemClock = SiSMclk(pSiS);
607
608       if(config2 & 0x02) {
609	  pSiS->MemClock *= 2;
610	  if(config1 == 0x02) {
611	     pSiS->BusWidth = busDDRA[0];
612	  } else {
613	     pSiS->BusWidth = busDDR[(config & 0x02)];
614	  }
615       } else {
616	  if(config1 == 0x02) {
617	     pSiS->BusWidth = busDDRA[2];
618	  } else {
619	     pSiS->BusWidth = busSDR[(config & 0x02)];
620	  }
621       }
622
623       break;
624
625    default: /* 315 */
626
627       pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
628
629       if(cr5f & 0x10) pSiS->ChipFlags |= SiSCF_Is315E;
630
631       /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */
632       if((config1 == 0x01) || (config1 == 0x03)) pScrn->videoRam <<= 1;
633
634       /* If DDR asymetric -> mem * 1,5 */
635       if(config1 == 0x02) pScrn->videoRam += pScrn->videoRam/2;
636
637       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
638	    "DRAM type: %s\n", dramTypeStr315[(config1 * 4) + config2]);
639
640       pSiS->MemClock = SiSMclk(pSiS);
641
642       /* If DDR -> memclock * 2 */
643       if(config2 & 0x02) pSiS->MemClock *= 2;
644
645       if(config1 == 0x02)
646	  pSiS->BusWidth = busDDRA[(config & 0x03)];
647       else if(config2 & 0x02)
648	  pSiS->BusWidth = busDDR[(config & 0x03)];
649       else
650	  pSiS->BusWidth = busSDR[(config & 0x03)];
651
652       if(pSiS->ChipFlags & SiSCF_Is315E) {
653	  inSISIDXREG(SISSR,0x15,config);
654	  if(config & 0x10) pSiS->BusWidth = 32;
655       }
656
657    }
658
659    pSiS->LFBsize = pScrn->videoRam;
660
661    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
662		"Memory clock: %3.3f MHz\n",
663		pSiS->MemClock/1000.0);
664
665    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
666		"DRAM bus width: %d bit\n",
667		pSiS->BusWidth);
668}
669
670/* For 550, 65x, 740, 661, 741, 660, 760, 761 */
671static void
672sis550Setup(ScrnInfoPtr pScrn)
673{
674    SISPtr       pSiS = SISPTR(pScrn);
675    unsigned int config, ramtype=0, i;
676    CARD8	 pciconfig, temp;
677    Bool	 alldone = FALSE;
678    Bool	 ddrtimes2 = TRUE;
679
680    pSiS->IsAGPCard = TRUE;
681    pSiS->IsPCIExpress = FALSE;
682    pSiS->ChipFlags &= ~(SiSCF_760UMA | SiSCF_760LFB);
683
684    pSiS->MemClock = SiSMclk(pSiS);
685
686    if(pSiS->Chipset == PCI_CHIP_SIS660) {
687
688       if(pSiS->ChipType >= SIS_660) {
689
690	  /* UMA - shared fb */
691	  pScrn->videoRam = 0;
692	  pciconfig = sis_pci_read_host_bridge_u8(0x4c);
693	  if(pciconfig & 0xe0) {
694	     pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768;
695	     pSiS->ChipFlags |= SiSCF_760UMA;
696	     pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
697	     pSiS->UMAsize = pScrn->videoRam;
698	     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
699		"%dK shared video RAM (UMA)\n",
700		pScrn->videoRam);
701	  }
702
703	  /* LFB - local framebuffer: PCI reg hold total RAM (but configurable in BIOS) */
704	  /* TODO */
705	  pciconfig = sis_pci_read_device_u8(1, 0xcd);
706	  pciconfig = (pciconfig >> 1) & 0x03;
707	  i = 0;
708	  if(pciconfig == 0x01)      i = 32768;
709	  else if(pciconfig == 0x03) i = 65536;
710	  if(i) {
711	     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK total local video RAM (LFB)\n", i);
712	  }
713
714	  /* LFB: CR78 holds amount of LFB memory configured in the BIOS setup */
715	  inSISIDXREG(SISCR, 0x78, config);
716	  config &= 0x30;
717	  if(config) {
718	     i = 0;
719	     if(config == 0x10)      i = 32768;
720	     else if(config == 0x30) i = 65536;
721	     if(i) {
722		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK configured local video RAM (LFB)\n", i);
723		pScrn->videoRam += i;
724		pSiS->ChipFlags |= SiSCF_760LFB;
725		pSiS->SiS76xLFBSize = i * 1024;
726		pSiS->LFBsize = i;
727	     }
728	  }
729
730	  if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) {
731	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
732		 "Illegal video RAM size (%dK) detected, using BIOS provided setting\n",
733		 pScrn->videoRam);
734	     pSiS->ChipFlags &= ~(SiSCF_760LFB | SiSCF_760UMA);
735	  } else {
736	     pSiS->BusWidth = 64;
737	     ramtype = 8;
738	     alldone = TRUE;
739	  }
740
741	  if(pSiS->ChipType >= SIS_761) {
742	     pSiS->IsAGPCard = FALSE;
743	     pSiS->IsPCIExpress = TRUE;
744	  }
745
746       } else {  /* 661, 741 */
747
748	  int dimmnum;
749
750	  if(pSiS->ChipType == SIS_741) {
751	     dimmnum = 4;
752	  } else {
753	     dimmnum = 3;
754	  }
755
756	  pciconfig = sis_pci_read_host_bridge_u8(0x64);
757	  if(pciconfig & 0x80) {
758	     pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768;
759	     pSiS->UMAsize = pScrn->videoRam;
760	     if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) {
761		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
762			"Illegal video RAM size (%dK) detected, using BIOS-provided info\n",
763			pScrn->videoRam);
764	     } else {
765		pSiS->BusWidth = 64;
766		for(i = 0; i <= (dimmnum - 1); i++) {
767		   if(pciconfig & (1 << i)) {
768		      temp = sis_pci_read_host_bridge_u8(0x60 + i);
769		      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
770			  "DIMM%d is %s SDRAM\n",
771			  i, (temp & 0x40) ? "DDR" : "SDR");
772		   } else {
773		      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
774			  "DIMM%d is not installed\n", i);
775		   }
776		}
777		pciconfig = sis_pci_read_host_bridge_u8(0x7c);
778		ramtype = (pciconfig & 0x02) ? 8 : 4;
779		alldone = TRUE;
780	     }
781          }
782
783       }
784
785    } else if(pSiS->Chipset == PCI_CHIP_SIS650) {
786
787       pciconfig = sis_pci_read_host_bridge_u8(0x64);
788       if(pciconfig & 0x80) {
789          pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024;
790	  pSiS->UMAsize = pScrn->videoRam;
791	  pSiS->BusWidth = 64;
792	  for(i=0; i<=3; i++) {
793	     if(pciconfig & (1 << i)) {
794		temp = sis_pci_read_host_bridge_u8(0x60 + i);
795		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
796		   "DIMM%d is %s SDRAM\n",
797		   i, (temp & 0x40) ? "DDR" : "SDR");
798	     } else {
799		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
800		   "DIMM%d is not installed\n", i);
801	     }
802	  }
803	  pciconfig = sis_pci_read_host_bridge_u8(0x7c);
804	  if(pciconfig & 0x02) ramtype = 8;
805	  else                 ramtype = 4;
806	  alldone = TRUE;
807       }
808
809    } else {
810       pciconfig = sis_pci_read_host_bridge_u8(0x63);
811       if(pciconfig & 0x80) {
812	  pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
813	  pSiS->UMAsize = pScrn->videoRam;
814	  pSiS->BusWidth = 64;
815          ramtype = sis_pci_read_host_bridge_u8(0x65);
816	  ramtype &= 0x01;
817	  xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
818	   	"Shared Memory Area is on DIMM%d\n", ramtype);
819	  ramtype = 4;
820	  alldone = TRUE;
821       }
822
823    }
824
825    /* Fall back to BIOS detection results in case of problems: */
826
827    if(!alldone) {
828
829       pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
830       pSiS->UMAsize = pSiS->LFBsize = 0;
831
832       if(pSiS->Chipset == PCI_CHIP_SIS660) {
833	  inSISIDXREG(SISCR, 0x79, config);
834	  pSiS->BusWidth = (config & 0x04) ? 128 : 64;
835	  ramtype = (config & 0x01) ? 8 : 4;
836	  if(pSiS->ChipType >= SIS_660) {
837	     pScrn->videoRam = 0;
838	     if(config & 0xf0) {
839		pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
840		pSiS->UMAsize = pScrn->videoRam;
841		pSiS->ChipFlags |= SiSCF_760UMA;
842		pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
843		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
844				"%dK shared video RAM (UMA)\n",
845				pScrn->videoRam);
846	     }
847	     inSISIDXREG(SISCR, 0x78, config);
848	     config &= 0x30;
849	     if(config) {
850	        i = 0;
851		if(config == 0x10)      i = 32768;
852		else if(config == 0x30) i = 65536;
853		if(i) {
854		   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
855				"%dK configured local video RAM (LFB)\n", i);
856		   pScrn->videoRam += i;
857		   pSiS->SiS76xLFBSize = i * 1024;
858		   pSiS->LFBsize = i;
859		   pSiS->ChipFlags |= SiSCF_760LFB;
860
861		}
862	     }
863	  } else {
864	     pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
865	     pSiS->UMAsize = pScrn->videoRam;
866	  }
867       } else {
868	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
869	      "Shared Memory Area is disabled - awaiting doom\n");
870	  inSISIDXREG(SISSR, 0x14, config);
871	  pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
872	  pSiS->UMAsize = pScrn->videoRam;
873	  if(pSiS->Chipset == PCI_CHIP_SIS650) {
874	     ramtype = (((config & 0x80) >> 7) << 2) + 4;
875	     pSiS->BusWidth = 64;   /* (config & 0x40) ? 128 : 64; */
876	  } else {
877	     ramtype = 4;
878	     pSiS->BusWidth = 64;
879	  }
880       }
881    }
882
883    /* These need special attention: Memory controller in CPU, hence
884     * - no DDR * 2 for bandwidth calculation,
885     * - overlay magic (bandwidth dependent one/two overlay stuff)
886     */
887    if((pSiS->ChipType >= SIS_760) && (pSiS->ChipType <= SIS_770)) {
888       if(!(pSiS->ChipFlags & SiSCF_760LFB)) {
889	  ddrtimes2 = FALSE;
890	  pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT760OO;
891       }
892    }
893
894    /* DDR -> Mclk * 2 - needed for bandwidth calculation */
895    if(ddrtimes2) {
896       if(ramtype == 8) pSiS->MemClock *= 2;
897    }
898
899    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
900		"DRAM type: %s\n",
901		dramTypeStr[ramtype]);
902
903    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
904		"Memory clock: %3.3f MHz\n",
905		pSiS->MemClock/1000.0);
906
907    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
908		"DRAM bus width: %d bit\n",
909		pSiS->BusWidth);
910}
911
912void
913SiSSetup(ScrnInfoPtr pScrn)
914{
915    SISPtr pSiS = SISPTR(pScrn);
916
917    pSiS->Flags = 0;
918    pSiS->VBFlags = 0;
919    pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
920    pSiS->UMAsize = pSiS->LFBsize = 0;
921
922    switch (SISPTR(pScrn)->Chipset) {
923    case PCI_CHIP_SIS300:
924    case PCI_CHIP_SIS630:  /* +730 */
925    case PCI_CHIP_SIS540:
926        sis300Setup(pScrn);
927        break;
928    case PCI_CHIP_SIS315:
929    case PCI_CHIP_SIS315H:
930    case PCI_CHIP_SIS315PRO:
931    case PCI_CHIP_SIS330:
932    case PCI_CHIP_SIS340:
933    case PCI_CHIP_XGIXG20:
934    case PCI_CHIP_XGIXG40:
935    	sis315Setup(pScrn);
936	break;
937    case PCI_CHIP_SIS550:
938    case PCI_CHIP_SIS650: /* + 740,M650,651 */
939    case PCI_CHIP_SIS660: /* + (M)661,(M)741,(M)760(GX), (M)761(GX), 770? */
940        sis550Setup(pScrn);
941	break;
942    case PCI_CHIP_SIS5597:
943    case PCI_CHIP_SIS6326:
944    case PCI_CHIP_SIS530:
945    default:
946        sisOldSetup(pScrn);
947        break;
948    }
949}
950
951
952