gfx_init.c revision f29dbc25
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 } else if (pid == 0x5) { 126 if (rev == 0x6) 127 gfx_chip_revision = SC1200_REV_D2_MVE; 128 else if (rev > 0x6) 129 gfx_chip_revision = SC1200_FUTURE_REV; 130 } 131 132 switch ((clk >> 8) & 3) { 133 case 0: 134 default: 135 gfx_pci_speed_khz = 33300; 136 break; 137 case 1: 138 gfx_pci_speed_khz = 48000; 139 break; 140 case 2: 141 gfx_pci_speed_khz = 66600; 142 break; 143 } 144 145 return (gfx_chip_revision); 146} 147 148/*---------------------------------------------------------------------------- 149 * gfx_detect_cpu 150 * 151 * This routine returns the type and revison of the CPU. If a Geode 152 * processor is not present, the routine returns zero. 153 * 154 * The return value is as follows: 155 * bits[24:16] = minor version 156 * bits[15:8] = major version 157 * bits[7:0] = type (1 = GXm, 2 = SC1200, 3 = Redcloud) 158 * 159 * A return value of 0x00020501, for example, indicates GXm version 5.2. 160 *---------------------------------------------------------------------------- 161 */ 162unsigned long 163gfx_detect_cpu(void) 164{ 165 166 unsigned long value = 0; 167 unsigned long version = 0; 168 169 /* initialize core freq. to 0 */ 170 gfx_cpu_frequency = 0; 171 172#if GFX_INIT_GU1 173 174 value = gfx_pci_config_read(0x80000000); 175 176 if (value == PCI_VENDOR_DEVICE_GXM) { 177 unsigned char dir0 = gfx_gxm_config_read(GXM_CONFIG_DIR0) & 0xF0; 178 unsigned char dir1 = gfx_gxm_config_read(GXM_CONFIG_DIR1); 179 180 if (dir0 == 0x40) { 181 /* CHECK FOR GXLV (and GXm) (DIR1 = 0x30 THROUGH 0x82) */ 182 183 if ((dir1 >= 0x30) && (dir1 <= 0x82)) { 184 /* Major version is one less than what appears in DIR1 */ 185 if ((dir1 & 0xF0) < 0x70) { 186 187 version = GFX_CPU_GXLV | (((((unsigned long)dir1 >> 4) - 1) << 8)) | /* major - 1 */ 188 ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ 189 } else { 190 version = GFX_CPU_GXLV | ((((unsigned long)dir1 >> 4)) 191 << 8) | /* major */ 192 ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ 193 } 194 /* Currently always CS5530 for video overlay. */ 195 196#if GFX_VIDEO_DYNAMIC 197 gfx_video_type = GFX_VIDEO_TYPE_CS5530; 198#endif 199 200 /* Currently always CS5530 GPIOs for I2C access. */ 201 202#if GFX_I2C_DYNAMIC 203 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 204#endif 205 206#if GFX_TV_DYNAMIC 207 gfx_tv_type = GFX_TV_TYPE_FS451; 208#endif 209 } 210 } else if (dir0 == 0xB0) { 211 /* CHECK FOR SC1200 */ 212 213 if ((dir1 == 0x70) || (dir1 == 0x81)) { 214 version = GFX_CPU_SC1200 | ((((unsigned long)dir1 >> 4)) 215 << 8) | /* major */ 216 ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ 217 218 /* Detect SC1200 revision */ 219 220 gfx_detect_chip(); 221 222 /* SC1200 for video overlay and VIP. */ 223 224#if GFX_VIDEO_DYNAMIC 225 gfx_video_type = GFX_VIDEO_TYPE_SC1200; 226#endif 227 228#if GFX_VIP_DYNAMIC 229 gfx_vip_type = GFX_VIP_TYPE_SC1200; 230#endif 231 232 /* Currently always SAA7114 decoder. */ 233 234#if GFX_DECODER_DYNAMIC 235 gfx_decoder_type = GFX_DECODER_TYPE_SAA7114; 236#endif 237 238 /* SC1200 for TV encoder */ 239 240#if GFX_TV_DYNAMIC 241 gfx_tv_type = GFX_TV_TYPE_SC1200; 242#endif 243 244 /* Currently always ACCESS.bus for I2C access. */ 245 246#if GFX_I2C_DYNAMIC 247 gfx_i2c_type = GFX_I2C_TYPE_ACCESS; 248#endif 249 } 250 } 251 252 if (version) { 253 /* ALWAYS FIRST GENERATION GRAPHICS UNIT */ 254 255#if GFX_DISPLAY_DYNAMIC 256 gfx_display_type = GFX_DISPLAY_TYPE_GU1; 257#endif 258#if GFX_2DACCEL_DYNAMIC 259 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU1; 260#endif 261#if GFX_INIT_DYNAMIC 262 gfx_init_type = GFX_INIT_TYPE_GU1; 263#endif 264 265 /* READ THE CORE FREQUENCY */ 266 267 gfx_cpu_frequency = gfx_get_core_freq(); 268 } 269 } 270#endif 271 272#if GFX_INIT_GU2 273 274 value = gfx_pci_config_read(0x80000800); 275 276 if (value == PCI_VENDOR_DEVICE_REDCLOUD) { 277 Q_WORD msr_value; 278 int valid, i; 279 280 /* CHECK FOR SOFT VG */ 281 /* If SoftVG is not present, the base addresses for all devices */ 282 /* will not be allocated. Essentially, it is as if no Redcloud */ 283 /* video hardware is present. */ 284 285 value = gfx_pci_config_read(0x80000900); 286 287 if (value == REDCLOUD_VIDEO_PCI_VENDOR_DEVICE) { 288 valid = 1; 289 290 /* BAR0 - BAR3 HOLD THE PERIPHERAL BASE ADDRESSES */ 291 292 for (i = 0; i < 4; i++) { 293 value = gfx_pci_config_read(0x80000910 + (i << 2)); 294 if (value == 0x00000000 || value == 0xFFFFFFFF) { 295 valid = 0; 296 break; 297 } 298 } 299 300 if (valid) { 301 /* REDCLOUD INTEGRATED VIDEO */ 302 303#if GFX_VIDEO_DYNAMIC 304 gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; 305#endif 306 307 /* CURRENTLY, ALWAYS GPIO FOR I2C ACCESS */ 308 309#if GFX_I2C_DYNAMIC 310 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 311#endif 312 313 /* SECOND-GENERATION DISPLAY CONTROLLER */ 314 315#if GFX_DISPLAY_DYNAMIC 316 gfx_display_type = GFX_DISPLAY_TYPE_GU2; 317#endif 318 319 /* SECOND-GENERATION GRAPHICS UNIT */ 320 321#if GFX_2DACCEL_DYNAMIC 322 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; 323#endif 324 325 /* SECOND-GENERATION INITIALIZATION */ 326 327#if GFX_INIT_DYNAMIC 328 gfx_init_type = GFX_INIT_TYPE_GU2; 329#endif 330 331 /* MBUS MSR ACCESSES */ 332 333#if GFX_MSR_DYNAMIC 334 gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; 335#endif 336 337 /* CS5530 GPIO I2C */ 338 339#if GFX_I2C_DYNAMIC 340 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 341#endif 342 343 /* READ VERSION */ 344 345 gfx_msr_init(); 346 347 gfx_msr_read(RC_ID_MCP, MCP_RC_REVID, &msr_value); 348 349 /* SUBTRACT 1 FROM REV ID */ 350 /* REDCLOUD 1.X rev id is 1 less than the reported value */ 351 352 if ((msr_value.low & 0xF0) == 0x10) 353 msr_value.low--; 354 355 version = GFX_CPU_REDCLOUD | ((msr_value.low & 0xF0) << 4) | /* MAJOR */ 356 ((msr_value.low & 0x0F) << 16); /* MINOR */ 357 358 /* READ THE CORE FREQUENCY */ 359 /* I can't find GX implementations that need 360 * this - we're trying to avoid virtual reads 361 * anyway, so bail on it 362 */ 363 364 /* gfx_cpu_frequency = gfx_get_core_freq(); */ 365 366 /* SET THE GP SCRATCH AREA */ 367 /* Color bitmap BLTs use the last 16K of frame buffer space */ 368 369 gfx_gx2_scratch_base = gfx_get_frame_buffer_size() - 0x4000; 370 } 371 } 372 } 373 374#endif 375 376 if (!version) { 377 /* ALWAYS SECOND GENERATION IF SIMULATING */ 378 /* For now, that is. This could change. */ 379 380#if GFX_DISPLAY_DYNAMIC 381 gfx_display_type = GFX_DISPLAY_TYPE_GU2; 382#endif 383#if GFX_2DACCEL_DYNAMIC 384 gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; 385#endif 386#if GFX_INIT_DYNAMIC 387 gfx_init_type = GFX_INIT_TYPE_GU2; 388#endif 389#if GFX_MSR_DYNAMIC 390 gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; 391#endif 392#if GFX_VIDEO_DYNAMIC 393 gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; 394#endif 395#if GFX_I2C_DYNAMIC 396 gfx_i2c_type = GFX_I2C_TYPE_GPIO; 397#endif 398 } 399 gfx_cpu_version = version; 400 401 return (version); 402} 403 404/*---------------------------------------------------------------------------- 405 * gfx_detect_video 406 * 407 * This routine returns the type of the video hardware. 408 * 409 * The return value is as follows: 410 * bits[7:0] = type (1 = CS5530, 2 = SC1200, 3 = Redcloud) 411 * 412 * Currently this routine does not actually detect any hardware, and bases 413 * the video hardware entirely on the detected CPU. 414 *---------------------------------------------------------------------------- 415 */ 416unsigned long 417gfx_detect_video(void) 418{ 419 unsigned long version = 0; 420 421 if ((gfx_cpu_version & 0xFF) == GFX_CPU_GXLV) 422 version = GFX_VID_CS5530; 423 else if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200) 424 version = GFX_VID_SC1200; 425 else if ((gfx_cpu_version & 0xFF) == GFX_CPU_REDCLOUD) 426 version = GFX_VID_REDCLOUD; 427 gfx_vid_version = version; 428 return (version); 429} 430 431/*---------------------------------------------------------------------------- 432 * gfx_pci_config_read 433 * 434 * This routine reads a 32-bit value from the specified location in PCI 435 * configuration space. 436 *---------------------------------------------------------------------------- 437 */ 438unsigned long 439gfx_pci_config_read(unsigned long address) 440{ 441 unsigned long value = 0xFFFFFFFF; 442 443 OUTD(PCI_CONFIG_ADDR, address); 444 value = IND(PCI_CONFIG_DATA); 445 return (value); 446} 447 448/*---------------------------------------------------------------------------- 449 * gfx_pci_config_write 450 * 451 * This routine writes a 32-bit value to the specified location in PCI 452 * configuration space. 453 *---------------------------------------------------------------------------- 454 */ 455void 456gfx_pci_config_write(unsigned long address, unsigned long data) 457{ 458 OUTD(PCI_CONFIG_ADDR, address); 459 OUTD(PCI_CONFIG_DATA, data); 460 return; 461} 462 463/* WRAPPERS IF DYNAMIC SELECTION */ 464/* Extra layer to call either first or second generation routines. */ 465 466#if GFX_INIT_DYNAMIC 467 468/*---------------------------------------------------------------------------- 469 * gfx_get_core_freq 470 *---------------------------------------------------------------------------- 471 */ 472unsigned long 473gfx_get_core_freq(void) 474{ 475 unsigned long freq = 0; 476 477#if GFX_INIT_GU1 478 if (gfx_init_type & GFX_INIT_TYPE_GU1) 479 freq = gu1_get_core_freq(); 480#endif 481#if GFX_INIT_GU2 482 if (gfx_init_type & GFX_INIT_TYPE_GU2) 483 freq = gu2_get_core_freq(); 484#endif 485 486 return freq; 487} 488 489/*---------------------------------------------------------------------------- 490 * gfx_get_cpu_register_base 491 *---------------------------------------------------------------------------- 492 */ 493unsigned long 494gfx_get_cpu_register_base(void) 495{ 496 unsigned long base = 0; 497 498#if GFX_INIT_GU1 499 if (gfx_init_type & GFX_INIT_TYPE_GU1) 500 base = gu1_get_cpu_register_base(); 501#endif 502#if GFX_INIT_GU2 503 if (gfx_init_type & GFX_INIT_TYPE_GU2) 504 base = gu2_get_cpu_register_base(); 505#endif 506 507 return (base); 508} 509 510/*---------------------------------------------------------------------------- 511 * gfx_get_graphics_register_base 512 *---------------------------------------------------------------------------- 513 */ 514unsigned long 515gfx_get_graphics_register_base(void) 516{ 517 unsigned long base = 0; 518 519#if GFX_INIT_GU2 520 if (gfx_init_type & GFX_INIT_TYPE_GU2) 521 base = gu2_get_graphics_register_base(); 522#endif 523 524 return (base); 525} 526 527/*---------------------------------------------------------------------------- 528 * gfx_get_frame_buffer_base 529 *---------------------------------------------------------------------------- 530 */ 531unsigned long 532gfx_get_frame_buffer_base(void) 533{ 534 unsigned long base = 0; 535 536#if GFX_INIT_GU1 537 if (gfx_init_type & GFX_INIT_TYPE_GU1) 538 base = gu1_get_frame_buffer_base(); 539#endif 540#if GFX_INIT_GU2 541 if (gfx_init_type & GFX_INIT_TYPE_GU2) 542 base = gu2_get_frame_buffer_base(); 543#endif 544 545 return (base); 546} 547 548/*---------------------------------------------------------------------------- 549 * gfx_get_frame_buffer_size 550 *---------------------------------------------------------------------------- 551 */ 552unsigned long 553gfx_get_frame_buffer_size(void) 554{ 555 unsigned long size = 0; 556 557#if GFX_INIT_GU1 558 if (gfx_init_type & GFX_INIT_TYPE_GU1) 559 size = gu1_get_frame_buffer_size(); 560#endif 561#if GFX_INIT_GU2 562 if (gfx_init_type & GFX_INIT_TYPE_GU2) 563 size = gu2_get_frame_buffer_size(); 564#endif 565 566 return size; 567} 568 569/*---------------------------------------------------------------------------- 570 * gfx_get_vid_register_base 571 *---------------------------------------------------------------------------- 572 */ 573unsigned long 574gfx_get_vid_register_base(void) 575{ 576 unsigned long base = 0; 577 578#if GFX_INIT_GU1 579 if (gfx_init_type & GFX_INIT_TYPE_GU1) 580 base = gu1_get_vid_register_base(); 581#endif 582#if GFX_INIT_GU2 583 if (gfx_init_type & GFX_INIT_TYPE_GU2) 584 base = gu2_get_vid_register_base(); 585#endif 586 587 return (base); 588} 589 590/*---------------------------------------------------------------------------- 591 * gfx_get_vip_register_base 592 *---------------------------------------------------------------------------- 593 */ 594unsigned long 595gfx_get_vip_register_base(void) 596{ 597 unsigned long base = 0; 598 599#if GFX_INIT_GU1 600 if (gfx_init_type & GFX_INIT_TYPE_GU1) 601 base = gu1_get_vip_register_base(); 602#endif 603 604 return (base); 605} 606 607#endif 608 609/* END OF FILE */ 610