1 /* 2 Copyright (c) 2002, Thomas Kurschel 3 4 5 Part of Radeon kernel driver 6 7 BIOS detection and retrieval of vital data 8 9 Most of this data should be gathered directly, 10 especially monitor detection should be done on 11 demand so not all monitors need to be connected 12 during boot 13 */ 14 15 #include "radeon_driver.h" 16 #include <mmio.h> 17 #include <bios_regs.h> 18 #include <config_regs.h> 19 #include <memcntrl_regs.h> 20 #include <fp_regs.h> 21 #include <crtc_regs.h> 22 #include <radeon_bios.h> 23 //#include "../common/utils.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 28 static const char ati_rom_sig[] = "761295520"; 29 static const char *radeon_sig[] = { 30 "RG6", // r200 31 "RADEON", // r100 32 "M6", // mobile version of r100 33 // probably an M6P; 34 // anyway - this is the card I wrote this driver for! 35 // (perhaps ATI tries to make the card incompatible to standard drivers) 36 "P6", 37 "RV200", // rv200 38 "RV100", // rv100 39 "M7", // m7 40 "RV250", // rv250 R9100 41 "V280", // RV280 R9200 42 "R300", // R300 R9500 / R9700 43 "R350", // R350 R9800 44 "R360", // R360 R9800 XT 45 "V350", // RV350 R9600 46 "V360", // RV350 R9600 XT :guess 47 "M9" // guess: m9 48 }; 49 50 void Radeon_DetectRAM( device_info *di ); 51 52 53 // find address of ROM 54 static char *Radeon_FindRom( rom_info *ri ) 55 { 56 uint32 segstart; 57 char *rom_base; 58 char *rom; 59 int stage; 60 int i,j; 61 62 for( segstart = 0x000c0000; segstart < 0x000f0000; segstart += 0x00001000 ) { 63 stage = 1; 64 65 // find ROM 66 rom_base = ri->bios_ptr + segstart - 0xc0000; 67 68 if( *rom_base == 0x55 && ((*(rom_base + 1)) & 0xff) == 0xaa ) 69 stage = 2; 70 71 if (stage != 2) 72 continue; 73 74 // find signature of ATI 75 rom = rom_base; 76 77 for( i = 0; i < 128 - (int)strlen( ati_rom_sig ) && stage != 3; i++ ) { 78 if( ati_rom_sig[0] == *rom ) { 79 if( strncmp(ati_rom_sig, rom, strlen( ati_rom_sig )) == 0 ) 80 stage = 3; 81 } 82 rom++; 83 } 84 85 if( stage != 3 ) 86 continue; 87 88 // find signature of card 89 rom = rom_base; 90 91 for( i = 0; (i < 512) && (stage != 4); i++ ) { 92 for( j = 0; j < (int)sizeof( radeon_sig ) / (int)sizeof( radeon_sig[0] ); j++ ) { 93 if( radeon_sig[j][0] == *rom ) { 94 if( strncmp( radeon_sig[j], rom, strlen( radeon_sig[j] )) == 0 ) { 95 SHOW_INFO( 2, "Signature: %s", radeon_sig[j] ); 96 stage = 4; 97 break; 98 } 99 } 100 } 101 rom++; 102 } 103 104 if( stage != 4 ) 105 continue; 106 107 SHOW_INFO( 2, "found ROM @0x%lx", segstart ); 108 return rom_base; 109 } 110 111 SHOW_INFO0( 2, "no ROM found" ); 112 return NULL; 113 } 114 115 116 // PLL info is stored in ROM, probably to easily replace it 117 // and thus produce cards with different timings 118 static void Radeon_GetPLLInfo( device_info *di ) 119 { 120 uint8 *bios_header; 121 PLL_BLOCK pll, *pll_info; 122 123 bios_header = di->rom.rom_ptr + *(uint16 *)(di->rom.rom_ptr + 0x48); 124 pll_info = (PLL_BLOCK *)(di->rom.rom_ptr + *(uint16 *)(bios_header + 0x30)); 125 126 memcpy( &pll, pll_info, sizeof( pll )); 127 128 di->pll.xclk = (uint32)pll.XCLK; 129 di->pll.ref_freq = (uint32)pll.PCLK_ref_freq; 130 di->pll.ref_div = (uint32)pll.PCLK_ref_divider; 131 di->pll.min_pll_freq = pll.PCLK_min_freq; 132 di->pll.max_pll_freq = pll.PCLK_max_freq; 133 134 SHOW_INFO( 2, "ref_clk=%ld, ref_div=%ld, xclk=%ld, min_freq=%ld, max_freq=%ld from BIOS", 135 di->pll.ref_freq, di->pll.ref_div, di->pll.xclk, 136 di->pll.min_pll_freq, di->pll.max_pll_freq ); 137 } 138 139 const char *Mon2Str[] = { 140 "N/C", 141 "CRT", 142 "CRT", 143 "Laptop flatpanel", 144 "DVI (flatpanel)", 145 "secondary DVI (flatpanel) - unsupported", 146 "Composite TV - unsupported", 147 "S-Video out - unsupported" 148 }; 149 150 // ask BIOS what kind of monitor is connected to each port 151 static void Radeon_GetMonType( device_info *di ) 152 { 153 unsigned int tmp; 154 155 SHOW_FLOW0( 3, "" ); 156 157 di->disp_type[0] = di->disp_type[1] = dt_none; 158 159 if (di->has_crtc2) { 160 tmp = INREG( di->regs, RADEON_BIOS_4_SCRATCH ); 161 162 // ordering of "if"s is important are multiple 163 // devices can be concurrently connected to one port 164 // (like both a CRT and a TV) 165 166 // primary port 167 if (tmp & 0x08) 168 di->disp_type[0] = dt_dvi_1; 169 else if (tmp & 0x4) 170 di->disp_type[0] = dt_lvds; 171 else if (tmp & 0x200) 172 di->disp_type[0] = dt_crt_1; 173 else if (tmp & 0x10) 174 di->disp_type[0] = dt_ctv; 175 else if (tmp & 0x20) 176 di->disp_type[0] = dt_stv; 177 178 // secondary port 179 if (tmp & 0x2) 180 di->disp_type[1] = dt_crt_2; 181 else if (tmp & 0x800) 182 di->disp_type[1] = dt_dvi_2; 183 else if (tmp & 0x400) 184 // this is unlikely - I only know about one LVDS unit 185 di->disp_type[1] = dt_lvds; 186 else if (tmp & 0x1000) 187 di->disp_type[1] = dt_ctv; 188 else if (tmp & 0x2000) 189 di->disp_type[1] = dt_stv; 190 } else { 191 // regular Radeon 192 di->disp_type[0] = dt_none; 193 194 tmp = INREG( di->regs, RADEON_FP_GEN_CNTL); 195 196 if( tmp & RADEON_FP_EN_TMDS ) 197 di->disp_type[0] = dt_dvi_1; 198 else 199 di->disp_type[0] = dt_crt_1; 200 } 201 202 SHOW_INFO( 1, "BIOS reports %s on primary and %s on secondary port", 203 Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]); 204 205 // remove unsupported devices 206 if( di->disp_type[0] >= dt_dvi_2 ) 207 di->disp_type[0] = dt_none; 208 if( di->disp_type[1] >= dt_dvi_2 ) 209 di->disp_type[1] = dt_none; 210 211 // HACK: overlays can only be shown on first CRTC; 212 // if there's nothing on first port, connect 213 // second port to first CRTC (proper signal routing 214 // is hopefully done by BIOS) 215 if( di->has_crtc2 ) { 216 if( di->disp_type[0] == dt_none && di->disp_type[1] == dt_crt_2 ) { 217 di->disp_type[0] = dt_crt_1; 218 di->disp_type[1] = dt_none; 219 } 220 } 221 222 SHOW_INFO( 1, "Effective routing: %s on primary and %s on secondary port", 223 Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]); 224 } 225 226 227 // get flat panel info (does only make sense for Laptops 228 // with integrated display, but looking for it doesn't hurt, 229 // who knows which strange kind of combination is out there?) 230 static bool Radeon_GetBIOSDFPInfo( device_info *di ) 231 { 232 uint8 *bios_header; 233 uint16 fpi_offset; 234 FPI_BLOCK fpi; 235 char panel_name[30]; 236 int i; 237 238 bios_header = di->rom.rom_ptr + *(uint16 *)(di->rom.rom_ptr + 0x48); 239 240 fpi_offset = *(uint16 *)(bios_header + 0x40); 241 242 if( !fpi_offset ) { 243 di->fp_info.panel_pwr_delay = 200; 244 SHOW_ERROR0( 2, "No Panel Info Table found in BIOS" ); 245 return false; 246 } 247 248 memcpy( &fpi, di->rom.rom_ptr + fpi_offset, sizeof( fpi )); 249 250 memcpy( panel_name, &fpi.name, sizeof( fpi.name ) ); 251 panel_name[sizeof( fpi.name )] = 0; 252 253 SHOW_INFO( 2, "Panel ID string: %s", panel_name ); 254 255 di->fp_info.panel_xres = fpi.panel_xres; 256 di->fp_info.panel_yres = fpi.panel_yres; 257 258 SHOW_INFO( 2, "Panel Size from BIOS: %dx%d", 259 di->fp_info.panel_xres, di->fp_info.panel_yres); 260 261 di->fp_info.panel_pwr_delay = fpi.panel_pwr_delay; 262 if( di->fp_info.panel_pwr_delay > 2000 || di->fp_info.panel_pwr_delay < 0 ) 263 di->fp_info.panel_pwr_delay = 2000; 264 265 // there might be multiple supported resolutions stored; 266 // we are looking for native resolution 267 for( i = 0; i < 20; ++i ) { 268 uint16 fpi_timing_ofs; 269 FPI_TIMING_BLOCK fpi_timing; 270 271 fpi_timing_ofs = fpi.fpi_timing_ofs[i]; 272 273 if( fpi_timing_ofs == 0 ) 274 break; 275 276 memcpy( &fpi_timing, di->rom.rom_ptr + fpi_timing_ofs, sizeof( fpi_timing )); 277 278 if( fpi_timing.panel_xres != di->fp_info.panel_xres || 279 fpi_timing.panel_yres != di->fp_info.panel_yres ) 280 continue; 281 282 di->fp_info.h_blank = (fpi_timing.h_total - fpi_timing.h_display) * 8; 283 // TBD: seems like upper four bits of hsync_start contain garbage 284 di->fp_info.h_over_plus = ((fpi_timing.h_sync_start & 0xfff) - fpi_timing.h_display - 1) * 8; 285 di->fp_info.h_sync_width = fpi_timing.h_sync_width * 8; 286 di->fp_info.v_blank = fpi_timing.v_total - fpi_timing.v_display; 287 di->fp_info.v_over_plus = (fpi_timing.v_sync & 0x7ff) - fpi_timing.v_display; 288 di->fp_info.v_sync_width = (fpi_timing.v_sync & 0xf800) >> 11; 289 di->fp_info.dot_clock = fpi_timing.dot_clock * 10; 290 return true; 291 } 292 293 SHOW_ERROR0( 2, "Radeon: couldn't get Panel Timing from BIOS" ); 294 return false; 295 } 296 297 298 // try to reverse engineer DFP specification from 299 // timing currently set up in graphics cards registers 300 // (effectively, we hope that BIOS has set it up correctly 301 // and noone has messed registers up yet; let's pray) 302 static void Radeon_RevEnvDFPSize( device_info *di ) 303 { 304 vuint8 *regs = di->regs; 305 /* uint32 r; 306 307 // take a look at flat_panel.c of the accelerant how register values 308 // are calculated - this is the inverse function 309 r = INREG( regs, RADEON_FP_VERT_STRETCH ); 310 if( (r & RADEON_VERT_STRETCH_BLEND) == 0 ) { 311 di->fp_info.panel_yres = 312 ((r & RADEON_VERT_PANEL_SIZE) >> RADEON_VERT_PANEL_SHIFT) + 1; 313 } else { 314 uint32 v_total = (INREG( regs, RADEON_FP_CRTC_V_TOTAL_DISP ) 315 >> RADEON_FP_CRTC_V_DISP_SHIFT) + 1; 316 SHOW_INFO( 2, "stretched mode: v_total=%d", v_total ); 317 di->fp_info.panel_yres = 318 (v_total * FIX_SCALE * RADEON_VERT_STRETCH_RATIO_MAX / 319 (r & RADEON_VERT_STRETCH_RATIO_MASK) + FIX_SCALE / 2) >> FIX_SHIFT; 320 // seems to be a BIOS bug - vertical size is 1 point too small 321 // (checked by re-calculating stretch factor) 322 ++di->fp_info.panel_yres; 323 } 324 325 r = INREG( regs, RADEON_FP_HORZ_STRETCH ); 326 if( (r & RADEON_HORZ_STRETCH_BLEND) == 0 ) { 327 di->fp_info.panel_xres = 328 (((r & RADEON_HORZ_PANEL_SIZE) >> RADEON_HORZ_PANEL_SHIFT) + 1) * 8; 329 } else { 330 uint32 h_total = ((INREG( regs, RADEON_FP_CRTC_H_TOTAL_DISP ) 331 >> RADEON_FP_CRTC_H_DISP_SHIFT) + 1) * 8; 332 SHOW_INFO( 2, "stretched mode: h_total=%d", h_total ); 333 di->fp_info.panel_xres = 334 (h_total * FIX_SCALE * RADEON_HORZ_STRETCH_RATIO_MAX / 335 (r & RADEON_HORZ_STRETCH_RATIO_MASK) + FIX_SCALE / 2) >> FIX_SHIFT; 336 }*/ 337 338 di->fp_info.panel_yres = 339 ((INREG( regs, RADEON_FP_VERT_STRETCH ) & RADEON_VERT_PANEL_SIZE) 340 >> RADEON_VERT_PANEL_SHIFT) + 1; 341 342 di->fp_info.panel_xres = 343 (((INREG( regs, RADEON_FP_HORZ_STRETCH ) & RADEON_HORZ_PANEL_SIZE) 344 >> RADEON_HORZ_PANEL_SHIFT) + 1) * 8; 345 346 SHOW_INFO( 2, "detected panel size from registers: %dx%d", 347 di->fp_info.panel_xres, di->fp_info.panel_yres); 348 } 349 350 351 // once more for getting precise timing 352 static void Radeon_RevEnvDFPTiming( device_info *di ) 353 { 354 vuint8 *regs = di->regs; 355 uint32 r; 356 uint16 a, b; 357 358 359 r = INREG( regs, RADEON_FP_CRTC_H_TOTAL_DISP ); 360 // the magic "4" was found by trial and error and probably stems from fudge (see crtc.c) 361 a = (r & RADEON_FP_CRTC_H_TOTAL_MASK)/* + 4*/; 362 b = (r & RADEON_FP_CRTC_H_DISP_MASK) >> RADEON_FP_CRTC_H_DISP_SHIFT; 363 di->fp_info.h_blank = (a - b) * 8; 364 365 SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 ); 366 367 r = INREG( regs, RADEON_FP_H_SYNC_STRT_WID ); 368 di->fp_info.h_over_plus = 369 ((r & RADEON_FP_H_SYNC_STRT_CHAR_MASK) 370 >> RADEON_FP_H_SYNC_STRT_CHAR_SHIFT) - b/* - 1*/; 371 di->fp_info.h_over_plus *= 8; 372 di->fp_info.h_sync_width = 373 ((r & RADEON_FP_H_SYNC_WID_MASK) 374 >> RADEON_FP_H_SYNC_WID_SHIFT); 375 // TBD: this seems to be wrong 376 // (BIOS tells 112, this calculation leads to 24!) 377 di->fp_info.h_sync_width *= 8; 378 379 r = INREG( regs, RADEON_FP_CRTC_V_TOTAL_DISP ); 380 a = (r & RADEON_FP_CRTC_V_TOTAL_MASK)/* + 1*/; 381 b = (r & RADEON_FP_CRTC_V_DISP_MASK) >> RADEON_FP_CRTC_V_DISP_SHIFT; 382 di->fp_info.v_blank = a - b; 383 384 SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b ); 385 386 r = INREG( regs, RADEON_FP_V_SYNC_STRT_WID ); 387 di->fp_info.v_over_plus = (r & RADEON_FP_V_SYNC_STRT_MASK) - b; 388 di->fp_info.v_sync_width = ((r & RADEON_FP_V_SYNC_WID_MASK) 389 >> RADEON_FP_V_SYNC_WID_SHIFT)/* + 1*/; 390 391 // standard CRTC 392 393 r = INREG( regs, RADEON_CRTC_H_TOTAL_DISP ); 394 a = (r & RADEON_CRTC_H_TOTAL); 395 b = (r & RADEON_CRTC_H_DISP) >> RADEON_CRTC_H_DISP_SHIFT; 396 di->fp_info.h_blank = (a - b) * 8; 397 398 SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 ); 399 400 r = INREG( regs, RADEON_CRTC_H_SYNC_STRT_WID ); 401 di->fp_info.h_over_plus = 402 ((r & RADEON_CRTC_H_SYNC_STRT_CHAR) 403 >> RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) - b; 404 di->fp_info.h_over_plus *= 8; 405 di->fp_info.h_sync_width = 406 ((r & RADEON_CRTC_H_SYNC_WID) 407 >> RADEON_CRTC_H_SYNC_WID_SHIFT); 408 di->fp_info.h_sync_width *= 8; 409 410 r = INREG( regs, RADEON_CRTC_V_TOTAL_DISP ); 411 a = (r & RADEON_CRTC_V_TOTAL); 412 b = (r & RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; 413 di->fp_info.v_blank = a - b; 414 415 SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b ); 416 417 r = INREG( regs, RADEON_CRTC_V_SYNC_STRT_WID ); 418 di->fp_info.v_over_plus = (r & RADEON_CRTC_V_SYNC_STRT) - b; 419 di->fp_info.v_sync_width = ((r & RADEON_CRTC_V_SYNC_WID) 420 >> RADEON_CRTC_V_SYNC_WID_SHIFT); 421 } 422 423 424 // get everything in terms of monitors connected to the card 425 static void Radeon_GetBIOSMon( device_info *di ) 426 { 427 Radeon_GetMonType( di ); 428 429 // reset all Flat Panel Info; 430 // it gets filled out step by step, and this way we know what's still missing 431 memset( &di->fp_info, 0, sizeof( di->fp_info )); 432 433 // we assume that the only fp port is combined with standard port 0 434 di->fp_info.disp_type = di->disp_type[0]; 435 436 if( di->disp_type[0] == dt_dvi_1 || di->disp_type[0] == dt_lvds ) 437 { 438 // there is a flat panel - get info about it 439 Radeon_GetBIOSDFPInfo( di ); 440 441 // if BIOS doesn't know, ask the registers 442 if( di->fp_info.panel_xres == 0 || di->fp_info.panel_yres == 0) 443 Radeon_RevEnvDFPSize( di ); 444 445 if( di->fp_info.h_blank == 0 || di->fp_info.v_blank == 0) 446 Radeon_RevEnvDFPTiming( di ); 447 448 SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d", 449 di->fp_info.panel_xres, di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width ); 450 SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d", 451 di->fp_info.panel_yres, di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.v_sync_width ); 452 SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock ); 453 } 454 } 455 456 457 // detect amount of graphics memory 458 void Radeon_DetectRAM( device_info *di ) 459 { 460 vuint8 *regs = di->regs; 461 462 di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK; 463 464 // some production boards of m6 will return 0 if it's 8 MB 465 if( di->local_mem_size == 0 ) 466 di->local_mem_size = 8 * 1024 *1024; 467 468 switch( INREG( regs, RADEON_MEM_SDRAM_MODE_REG ) & RADEON_MEM_CFG_TYPE_MASK ) { 469 case RADEON_MEM_CFG_SDR: 470 // SDR SGRAM (2:1) 471 strcpy(di->ram_type, "SDR SGRAM"); 472 di->ram.ml = 4; 473 di->ram.MB = 4; 474 di->ram.Trcd = 1; 475 di->ram.Trp = 2; 476 di->ram.Twr = 1; 477 di->ram.CL = 2; 478 di->ram.loop_latency = 16; 479 di->ram.Rloop = 16; 480 di->ram.Tr2w = 0; 481 break; 482 483 case RADEON_MEM_CFG_DDR: 484 // DDR SGRAM 485 strcpy(di->ram_type, "DDR SGRAM"); 486 di->ram.ml = 4; 487 di->ram.MB = 4; 488 di->ram.Trcd = 3; 489 di->ram.Trp = 3; 490 di->ram.Twr = 2; 491 di->ram.CL = 3; 492 di->ram.Tr2w = 1; 493 di->ram.loop_latency = 16; 494 di->ram.Rloop = 16; 495 break; 496 497 // only one bit, so there's no default 498 } 499 500 SHOW_INFO( 1, "%ld MB %s found", di->local_mem_size / 1024 / 1024, 501 di->ram_type ); 502 503 if( di->local_mem_size > 64 * 1024 * 1024 ) { 504 di->local_mem_size = 64 * 1024 * 1024; 505 506 SHOW_INFO0( 1, "restricted to 64 MB" ); 507 } 508 } 509 510 511 // map and verify card's BIOS to see whether this really is a Radeon 512 // (as we need BIOS for further info we have to make sure we use the right one) 513 status_t Radeon_MapBIOS( pci_info *pcii, rom_info *ri ) 514 { 515 char buffer[B_OS_NAME_LENGTH]; 516 517 sprintf(buffer, "%04X_%04X_%02X%02X%02X bios", 518 pcii->vendor_id, pcii->device_id, 519 pcii->bus, pcii->device, pcii->function); 520 521 // we only scan BIOS at legacy location in first MB; 522 // using the PCI location would improve detection, especially 523 // if multiple graphics cards are installed 524 // BUT: BeOS uses the first graphics card it finds (sorted by 525 // device name), thus you couldn't choose in BIOS which card 526 // to use; checking the legacy location ensures that the card is 527 // only detected if it's the primary card 528 ri->bios_area = map_physical_memory( buffer, (void *)0xc0000, 529 0x40000, B_ANY_KERNEL_ADDRESS, B_READ_AREA, (void **)&ri->bios_ptr ); 530 if( ri->bios_area < 0 ) 531 return ri->bios_area; 532 533 ri->rom_ptr = Radeon_FindRom( ri ); 534 535 return ri->rom_ptr != NULL ? B_OK : B_ERROR; 536 } 537 538 539 // unmap card's BIOS 540 void Radeon_UnmapBIOS( rom_info *ri ) 541 { 542 delete_area( ri->bios_area ); 543 544 ri->bios_ptr = ri->rom_ptr = NULL; 545 } 546 547 548 // get everything valuable from BIOS (BIOS must be mapped) 549 status_t Radeon_ReadBIOSData( device_info *di ) 550 { 551 shared_info dummy_si; 552 status_t result = B_OK; 553 554 // give Radeon_MapDevice something to play with 555 di->si = &dummy_si; 556 557 // don't map frame buffer - we don't know its proper size yet! 558 result = Radeon_MapDevice( di, true ); 559 if( result < 0 ) 560 goto err1; 561 562 Radeon_GetPLLInfo( di ); 563 Radeon_GetBIOSMon( di ); 564 Radeon_DetectRAM( di ); 565 566 Radeon_UnmapDevice( di ); 567 568 err1: 569 di->si = NULL; 570 571 return result; 572 } 573