1/* Copyright (c) 2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This file contains routines typically used in driver initialization. 28 * 29 * Routines: 30 * 31 * gfx_pci_config_read 32 * gfx_cpu_config_read 33 * gfx_detect_cpu 34 * gfx_detect_video 35 * gfx_get_cpu_register_base 36 * gfx_get_frame_buffer_base 37 * gfx_get_frame_buffer_size 38 * gfx_get_vid_register_base 39 * gfx_get_vip_register_base 40 * */ 41 42/* CONSTANTS USED BY THE INITIALIZATION CODE */ 43 44#define PCI_CONFIG_ADDR 0x0CF8 45#define PCI_CONFIG_DATA 0x0CFC 46#define PCI_VENDOR_DEVICE_GXM 0x00011078 47#define PCI_VENDOR_DEVICE_REDCLOUD 0x0028100B 48#define REDCLOUD_VIDEO_PCI_VENDOR_DEVICE 0x0030100B 49 50#define GXM_CONFIG_GCR 0xB8 51#define GXM_CONFIG_CCR3 0xC3 52#define GXM_CONFIG_DIR0 0xFE 53#define GXM_CONFIG_DIR1 0xFF 54 55/* STATIC VARIABLES FOR THIS FILE */ 56 57unsigned long gfx_cpu_version = 0; 58unsigned long gfx_cpu_frequency = 0; 59unsigned long gfx_vid_version = 0; 60unsigned long gfx_gx1_scratch_base = 0; 61unsigned long gfx_gx2_scratch_base = 0x7FC000; 62unsigned long gfx_pci_speed_khz = 33300; 63ChipType gfx_chip_revision = CHIP_NOT_DETECTED; 64 65ChipType gfx_detect_chip(void); 66 67/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */ 68 69#if GFX_INIT_GU1 70#include "init_gu1.c" 71#endif 72 73/* INCLUDE SUPPORT FOR SECOND GENERATION, IF SPECIFIED. */ 74 75#if GFX_INIT_GU2 76#include "init_gu2.c" 77#endif 78 79/* THE FOLLOWING ROUTINES ARE NEVER DYNAMIC */ 80/* They are used to set the variables for future dynamic */ 81/* function calls. */ 82 83/*---------------------------------------------------------------------------- 84 * gfx_detect_chip 85 * 86 * This routine returns the name and revision of the chip. This function is 87 * only relevant to the SC1200. 88 *---------------------------------------------------------------------------- 89 */ 90ChipType 91gfx_detect_chip(void) 92{ 93 unsigned char pid = INB(SC1200_CB_BASE_ADDR + SC1200_CB_PID); 94 unsigned char rev = INB(SC1200_CB_BASE_ADDR + SC1200_CB_REV); 95 unsigned short clk = INW(SC1200_CB_BASE_ADDR + SC1200_CB_CCFC); 96 97 gfx_chip_revision = CHIP_NOT_DETECTED; 98 99 if (pid == 0x4) { 100 switch (rev) { 101 case 0: 102 gfx_chip_revision = SC1200_REV_A; 103 break; 104 case 1: 105 gfx_chip_revision = SC1200_REV_B1_B2; 106 break; 107 case 2: 108 gfx_chip_revision = SC1200_REV_B3; 109 break; 110 case 3: 111 gfx_chip_revision = SC1200_REV_C1; 112 break; 113 case 4: 114 gfx_chip_revision = SC1200_REV_D1; 115 break; 116 case 5: 117 gfx_chip_revision = SC1200_REV_D1_1; 118 break; 119 case 6: 120 gfx_chip_revision = SC1200_REV_D2_MVD; 121 break; 122 } 123 if (rev > 0x6) 124 gfx_chip_revision = SC1200_FUTURE_REV; 125 } 126 else if (pid == 0x5) { 127 if (rev == 0x6) 128 gfx_chip_revision = SC1200_REV_D2_MVE; 129 else if (rev > 0x6) 130 gfx_chip_revision = SC1200_FUTURE_REV; 131 } 132 133 switch ((clk >> 8) & 3) { 134 case 0: 135 default: 136 gfx_pci_speed_khz = 33300; 137 break; 138 case 1: 139 gfx_pci_speed_khz = 48000; 140 break; 141 case 2: 142 gfx_pci_speed_khz = 66600; 143 break; 144 } 145 146 return (gfx_chip_revision); 147} 148 149/*---------------------------------------------------------------------------- 150 * gfx_detect_cpu 151 * 152 * This routine returns the type and revision of the CPU. If a Geode 153 * processor is not present, the routine returns zero. 154 * 155 * The return value is as follows: 156 * bits[24:16] = minor version 157 * bits[15:8] = major version 158 * bits[7:0] = type (1 = GXm, 2 = SC1200, 3 = Redcloud) 159 * 160 * A return value of 0x00020501, for example, indicates GXm version 5.2. 161 *---------------------------------------------------------------------------- 162 */ 163unsigned long 164gfx_detect_cpu(void) 165{ 166 167 unsigned long value = 0; 168 unsigned long version = 0; 169 170 /* initialize core freq. to 0 */ 171 gfx_cpu_frequency = 0; 172 173#if GFX_INIT_GU1 174 175 value = gfx_pci_config_read(0x80000000); 176 177 if (value == PCI_VENDOR_DEVICE_GXM) { 178 unsigned char dir0 = gfx_gxm_config_read(GXM_CONFIG_DIR0) & 0xF0; 179 unsigned char dir1 = gfx_gxm_config_read(GXM_CONFIG_DIR1); 180 181 if (dir0 == 0x40) { 182 /* CHECK FOR GXLV (and GXm) (DIR1 = 0x30 THROUGH 0x82) */ 183 184 if ((dir1 >= 0x30) && (dir1 <= 0x82)) { 185 /* Major version is one less than what appears in DIR1 */ 186 if ((dir1 & 0xF0) < 0x70) { 187 188 version = GFX_CPU_GXLV | (((((unsigned long) dir1 >> 4) - 1) << 8)) | /* major - 1 */ 189 ((((unsigned long) dir1 & 0x0F)) << 16); /* minor */ 190 } 191 else { 192 version = GFX_CPU_GXLV | ((((unsigned long) dir1 >> 4)) 193 << 8) | /* major */ 194 ((((unsigned long) dir1 & 0x0F)) << 16); /* minor */ 195 } 196 /* Currently always CS5530 for video overlay. */ 197 198#if GFX_VIDEO_DYNAMIC 199 gfx_video_type = GFX_VIDEO_TYPE_CS5530; 200#endif 201 202 /* Currently always CS5530 GPIOs for I2C access. */ 203 204#if GFX_I2C_DYNAMIC 205 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 206#endif 207 208#if GFX_TV_DYNAMIC 209 gfx_tv_type = GFX_TV_TYPE_FS451; 210#endif 211 } 212 } 213 else if (dir0 == 0xB0) { 214 /* CHECK FOR SC1200 */ 215 216 if ((dir1 == 0x70) || (dir1 == 0x81)) { 217 version = GFX_CPU_SC1200 | ((((unsigned long) dir1 >> 4)) 218 << 8) | /* major */ 219 ((((unsigned long) dir1 & 0x0F)) << 16); /* minor */ 220 221 /* Detect SC1200 revision */ 222 223 gfx_detect_chip(); 224 225 /* SC1200 for video overlay and VIP. */ 226 227#if GFX_VIDEO_DYNAMIC 228 gfx_video_type = GFX_VIDEO_TYPE_SC1200; 229#endif 230 231#if GFX_VIP_DYNAMIC 232 gfx_vip_type = GFX_VIP_TYPE_SC1200; 233#endif 234 235 /* Currently always SAA7114 decoder. */ 236 237#if GFX_DECODER_DYNAMIC 238 gfx_decoder_type = GFX_DECODER_TYPE_SAA7114; 239#endif 240 241 /* SC1200 for TV encoder */ 242 243#if GFX_TV_DYNAMIC 244 gfx_tv_type = GFX_TV_TYPE_SC1200; 245#endif 246 247 /* Currently always ACCESS.bus for I2C access. */ 248 249#if GFX_I2C_DYNAMIC 250 gfx_i2c_type = GFX_I2C_TYPE_ACCESS; 251#endif 252 } 253 } 254 255 if (version) { 256 /* ALWAYS FIRST GENERATION GRAPHICS UNIT */ 257 258#if GFX_DISPLAY_DYNAMIC 259 gfx_display_type = GFX_DISPLAY_TYPE_GU1; 260#endif 261#if GFX_2DACCEL_DYNAMIC 262 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU1; 263#endif 264#if GFX_INIT_DYNAMIC 265 gfx_init_type = GFX_INIT_TYPE_GU1; 266#endif 267 268 /* READ THE CORE FREQUENCY */ 269 270 gfx_cpu_frequency = gfx_get_core_freq(); 271 } 272 } 273#endif 274 275#if GFX_INIT_GU2 276 277 value = gfx_pci_config_read(0x80000800); 278 279 if (value == PCI_VENDOR_DEVICE_REDCLOUD) { 280 Q_WORD msr_value; 281 int valid, i; 282 283 /* CHECK FOR SOFT VG */ 284 /* If SoftVG is not present, the base addresses for all devices */ 285 /* will not be allocated. Essentially, it is as if no Redcloud */ 286 /* video hardware is present. */ 287 288 value = gfx_pci_config_read(0x80000900); 289 290 if (value == REDCLOUD_VIDEO_PCI_VENDOR_DEVICE) { 291 valid = 1; 292 293 /* BAR0 - BAR3 HOLD THE PERIPHERAL BASE ADDRESSES */ 294 295 for (i = 0; i < 4; i++) { 296 value = gfx_pci_config_read(0x80000910 + (i << 2)); 297 if (value == 0x00000000 || value == 0xFFFFFFFF) { 298 valid = 0; 299 break; 300 } 301 } 302 303 if (valid) { 304 /* REDCLOUD INTEGRATED VIDEO */ 305 306#if GFX_VIDEO_DYNAMIC 307 gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; 308#endif 309 310 /* CURRENTLY, ALWAYS GPIO FOR I2C ACCESS */ 311 312#if GFX_I2C_DYNAMIC 313 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 314#endif 315 316 /* SECOND-GENERATION DISPLAY CONTROLLER */ 317 318#if GFX_DISPLAY_DYNAMIC 319 gfx_display_type = GFX_DISPLAY_TYPE_GU2; 320#endif 321 322 /* SECOND-GENERATION GRAPHICS UNIT */ 323 324#if GFX_2DACCEL_DYNAMIC 325 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; 326#endif 327 328 /* SECOND-GENERATION INITIALIZATION */ 329 330#if GFX_INIT_DYNAMIC 331 gfx_init_type = GFX_INIT_TYPE_GU2; 332#endif 333 334 /* MBUS MSR ACCESSES */ 335 336#if GFX_MSR_DYNAMIC 337 gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; 338#endif 339 340 /* CS5530 GPIO I2C */ 341 342#if GFX_I2C_DYNAMIC 343 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 344#endif 345 346 /* READ VERSION */ 347 348 gfx_msr_init(); 349 350 gfx_msr_read(RC_ID_MCP, MCP_RC_REVID, &msr_value); 351 352 /* SUBTRACT 1 FROM REV ID */ 353 /* REDCLOUD 1.X rev id is 1 less than the reported value */ 354 355 if ((msr_value.low & 0xF0) == 0x10) 356 msr_value.low--; 357 358 version = GFX_CPU_REDCLOUD | ((msr_value.low & 0xF0) << 4) | /* MAJOR */ 359 ((msr_value.low & 0x0F) << 16); /* MINOR */ 360 361 /* READ THE CORE FREQUENCY */ 362 /* I can't find GX implementations that need 363 * this - we're trying to avoid virtual reads 364 * anyway, so bail on it 365 */ 366 367 /* gfx_cpu_frequency = gfx_get_core_freq(); */ 368 369 /* SET THE GP SCRATCH AREA */ 370 /* Color bitmap BLTs use the last 16K of frame buffer space */ 371 372 gfx_gx2_scratch_base = gfx_get_frame_buffer_size() - 0x4000; 373 } 374 } 375 } 376 377#endif 378 379 if (!version) { 380 /* ALWAYS SECOND GENERATION IF SIMULATING */ 381 /* For now, that is. This could change. */ 382 383#if GFX_DISPLAY_DYNAMIC 384 gfx_display_type = GFX_DISPLAY_TYPE_GU2; 385#endif 386#if GFX_2DACCEL_DYNAMIC 387 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; 388#endif 389#if GFX_INIT_DYNAMIC 390 gfx_init_type = GFX_INIT_TYPE_GU2; 391#endif 392#if GFX_MSR_DYNAMIC 393 gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; 394#endif 395#if GFX_VIDEO_DYNAMIC 396 gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; 397#endif 398#if GFX_I2C_DYNAMIC 399 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 400#endif 401 } 402 gfx_cpu_version = version; 403 404 return (version); 405} 406 407/*---------------------------------------------------------------------------- 408 * gfx_detect_video 409 * 410 * This routine returns the type of the video hardware. 411 * 412 * The return value is as follows: 413 * bits[7:0] = type (1 = CS5530, 2 = SC1200, 3 = Redcloud) 414 * 415 * Currently this routine does not actually detect any hardware, and bases 416 * the video hardware entirely on the detected CPU. 417 *---------------------------------------------------------------------------- 418 */ 419unsigned long 420gfx_detect_video(void) 421{ 422 unsigned long version = 0; 423 424 if ((gfx_cpu_version & 0xFF) == GFX_CPU_GXLV) 425 version = GFX_VID_CS5530; 426 else if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200) 427 version = GFX_VID_SC1200; 428 else if ((gfx_cpu_version & 0xFF) == GFX_CPU_REDCLOUD) 429 version = GFX_VID_REDCLOUD; 430 gfx_vid_version = version; 431 return (version); 432} 433 434/*---------------------------------------------------------------------------- 435 * gfx_pci_config_read 436 * 437 * This routine reads a 32-bit value from the specified location in PCI 438 * configuration space. 439 *---------------------------------------------------------------------------- 440 */ 441unsigned long 442gfx_pci_config_read(unsigned long address) 443{ 444 unsigned long value = 0xFFFFFFFF; 445 446 OUTD(PCI_CONFIG_ADDR, address); 447 value = IND(PCI_CONFIG_DATA); 448 return (value); 449} 450 451/*---------------------------------------------------------------------------- 452 * gfx_pci_config_write 453 * 454 * This routine writes a 32-bit value to the specified location in PCI 455 * configuration space. 456 *---------------------------------------------------------------------------- 457 */ 458void 459gfx_pci_config_write(unsigned long address, unsigned long data) 460{ 461 OUTD(PCI_CONFIG_ADDR, address); 462 OUTD(PCI_CONFIG_DATA, data); 463 return; 464} 465 466/* WRAPPERS IF DYNAMIC SELECTION */ 467/* Extra layer to call either first or second generation routines. */ 468 469#if GFX_INIT_DYNAMIC 470 471/*---------------------------------------------------------------------------- 472 * gfx_get_core_freq 473 *---------------------------------------------------------------------------- 474 */ 475unsigned long 476gfx_get_core_freq(void) 477{ 478 unsigned long freq = 0; 479 480#if GFX_INIT_GU1 481 if (gfx_init_type & GFX_INIT_TYPE_GU1) 482 freq = gu1_get_core_freq(); 483#endif 484#if GFX_INIT_GU2 485 if (gfx_init_type & GFX_INIT_TYPE_GU2) 486 freq = gu2_get_core_freq(); 487#endif 488 489 return freq; 490} 491 492/*---------------------------------------------------------------------------- 493 * gfx_get_cpu_register_base 494 *---------------------------------------------------------------------------- 495 */ 496unsigned long 497gfx_get_cpu_register_base(void) 498{ 499 unsigned long base = 0; 500 501#if GFX_INIT_GU1 502 if (gfx_init_type & GFX_INIT_TYPE_GU1) 503 base = gu1_get_cpu_register_base(); 504#endif 505#if GFX_INIT_GU2 506 if (gfx_init_type & GFX_INIT_TYPE_GU2) 507 base = gu2_get_cpu_register_base(); 508#endif 509 510 return (base); 511} 512 513/*---------------------------------------------------------------------------- 514 * gfx_get_graphics_register_base 515 *---------------------------------------------------------------------------- 516 */ 517unsigned long 518gfx_get_graphics_register_base(void) 519{ 520 unsigned long base = 0; 521 522#if GFX_INIT_GU2 523 if (gfx_init_type & GFX_INIT_TYPE_GU2) 524 base = gu2_get_graphics_register_base(); 525#endif 526 527 return (base); 528} 529 530/*---------------------------------------------------------------------------- 531 * gfx_get_frame_buffer_base 532 *---------------------------------------------------------------------------- 533 */ 534unsigned long 535gfx_get_frame_buffer_base(void) 536{ 537 unsigned long base = 0; 538 539#if GFX_INIT_GU1 540 if (gfx_init_type & GFX_INIT_TYPE_GU1) 541 base = gu1_get_frame_buffer_base(); 542#endif 543#if GFX_INIT_GU2 544 if (gfx_init_type & GFX_INIT_TYPE_GU2) 545 base = gu2_get_frame_buffer_base(); 546#endif 547 548 return (base); 549} 550 551/*---------------------------------------------------------------------------- 552 * gfx_get_frame_buffer_size 553 *---------------------------------------------------------------------------- 554 */ 555unsigned long 556gfx_get_frame_buffer_size(void) 557{ 558 unsigned long size = 0; 559 560#if GFX_INIT_GU1 561 if (gfx_init_type & GFX_INIT_TYPE_GU1) 562 size = gu1_get_frame_buffer_size(); 563#endif 564#if GFX_INIT_GU2 565 if (gfx_init_type & GFX_INIT_TYPE_GU2) 566 size = gu2_get_frame_buffer_size(); 567#endif 568 569 return size; 570} 571 572/*---------------------------------------------------------------------------- 573 * gfx_get_vid_register_base 574 *---------------------------------------------------------------------------- 575 */ 576unsigned long 577gfx_get_vid_register_base(void) 578{ 579 unsigned long base = 0; 580 581#if GFX_INIT_GU1 582 if (gfx_init_type & GFX_INIT_TYPE_GU1) 583 base = gu1_get_vid_register_base(); 584#endif 585#if GFX_INIT_GU2 586 if (gfx_init_type & GFX_INIT_TYPE_GU2) 587 base = gu2_get_vid_register_base(); 588#endif 589 590 return (base); 591} 592 593/*---------------------------------------------------------------------------- 594 * gfx_get_vip_register_base 595 *---------------------------------------------------------------------------- 596 */ 597unsigned long 598gfx_get_vip_register_base(void) 599{ 600 unsigned long base = 0; 601 602#if GFX_INIT_GU1 603 if (gfx_init_type & GFX_INIT_TYPE_GU1) 604 base = gu1_get_vip_register_base(); 605#endif 606 607 return (base); 608} 609 610#endif 611 612/* END OF FILE */ 613