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