1 /* 2 * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include "accelerant_protos.h" 12 #include "accelerant.h" 13 #include "bios.h" 14 #include "gpu.h" 15 #include "utility.h" 16 17 #include <Debug.h> 18 19 20 #undef TRACE 21 22 #define TRACE_GPU 23 #ifdef TRACE_GPU 24 # define TRACE(x...) _sPrintf("radeon_hd: " x) 25 #else 26 # define TRACE(x...) ; 27 #endif 28 29 #define ERROR(x...) _sPrintf("radeon_hd: " x) 30 31 32 status_t 33 radeon_gpu_reset() 34 { 35 radeon_shared_info &info = *gInfo->shared_info; 36 37 // Read GRBM Command Processor status 38 if ((Read32(OUT, GRBM_STATUS) & GUI_ACTIVE) == 0) 39 return B_ERROR; 40 41 TRACE("%s: GPU software reset in progress...\n", __func__); 42 43 // Halt memory controller 44 struct gpu_state gpuState; 45 radeon_gpu_mc_halt(&gpuState); 46 47 if (radeon_gpu_mc_idlecheck() > 0) { 48 ERROR("%s: Timeout waiting for MC to idle!\n", __func__); 49 } 50 51 if (info.chipsetID < RADEON_CEDAR) { 52 Write32(OUT, CP_ME_CNTL, CP_ME_HALT); 53 // Disable Command Processor parsing / prefetching 54 55 // Register busy masks for early Radeon HD cards 56 57 // GRBM Command Processor Status 58 uint32 grbmBusyMask = VC_BUSY; 59 // Vertex Cache Busy 60 grbmBusyMask |= VGT_BUSY_NO_DMA | VGT_BUSY; 61 // Vertex Grouper Tessellator Busy 62 grbmBusyMask |= TA03_BUSY; 63 // unknown 64 grbmBusyMask |= TC_BUSY; 65 // Texture Cache Busy 66 grbmBusyMask |= SX_BUSY; 67 // Shader Export Busy 68 grbmBusyMask |= SH_BUSY; 69 // Sequencer Instruction Cache Busy 70 grbmBusyMask |= SPI_BUSY; 71 // Shader Processor Interpolator Busy 72 grbmBusyMask |= SMX_BUSY; 73 // Shader Memory Exchange 74 grbmBusyMask |= SC_BUSY; 75 // Scan Converter Busy 76 grbmBusyMask |= PA_BUSY; 77 // Primitive Assembler Busy 78 grbmBusyMask |= DB_BUSY; 79 // Depth Block Busy 80 grbmBusyMask |= CR_BUSY; 81 // unknown 82 grbmBusyMask |= CB_BUSY; 83 // Color Block Busy 84 grbmBusyMask |= GUI_ACTIVE; 85 // unknown (graphics pipeline active?) 86 87 // GRBM Command Processor Detailed Status 88 uint32 grbm2BusyMask = SPI0_BUSY | SPI1_BUSY | SPI2_BUSY | SPI3_BUSY; 89 // Shader Processor Interpolator 0 - 3 Busy 90 grbm2BusyMask |= TA0_BUSY | TA1_BUSY | TA2_BUSY | TA3_BUSY; 91 // unknown 0 - 3 Busy 92 grbm2BusyMask |= DB0_BUSY | DB1_BUSY | DB2_BUSY | DB3_BUSY; 93 // Depth Block 0 - 3 Busy 94 grbm2BusyMask |= CB0_BUSY | CB1_BUSY | CB2_BUSY | CB3_BUSY; 95 // Color Block 0 - 3 Busy 96 97 uint32 tmp; 98 /* Check if any of the rendering block is busy and reset it */ 99 if ((Read32(OUT, GRBM_STATUS) & grbmBusyMask) != 0 100 || (Read32(OUT, GRBM_STATUS2) & grbm2BusyMask) != 0) { 101 tmp = SOFT_RESET_CR 102 | SOFT_RESET_DB 103 | SOFT_RESET_CB 104 | SOFT_RESET_PA 105 | SOFT_RESET_SC 106 | SOFT_RESET_SMX 107 | SOFT_RESET_SPI 108 | SOFT_RESET_SX 109 | SOFT_RESET_SH 110 | SOFT_RESET_TC 111 | SOFT_RESET_TA 112 | SOFT_RESET_VC 113 | SOFT_RESET_VGT; 114 Write32(OUT, GRBM_SOFT_RESET, tmp); 115 Read32(OUT, GRBM_SOFT_RESET); 116 snooze(15000); 117 Write32(OUT, GRBM_SOFT_RESET, 0); 118 } 119 120 // Reset CP 121 tmp = SOFT_RESET_CP; 122 Write32(OUT, GRBM_SOFT_RESET, tmp); 123 Read32(OUT, GRBM_SOFT_RESET); 124 snooze(15000); 125 Write32(OUT, GRBM_SOFT_RESET, 0); 126 127 // Let things settle 128 snooze(1000); 129 } else { 130 // Evergreen and higher 131 132 Write32(OUT, CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); 133 // Disable Command Processor parsing / prefetching 134 135 // reset the graphics pipeline components 136 uint32 grbmReset = (SOFT_RESET_CP 137 | SOFT_RESET_CB 138 | SOFT_RESET_DB 139 | SOFT_RESET_GDS 140 | SOFT_RESET_PA 141 | SOFT_RESET_SC 142 | SOFT_RESET_SPI 143 | SOFT_RESET_SH 144 | SOFT_RESET_SX 145 | SOFT_RESET_TC 146 | SOFT_RESET_TA 147 | SOFT_RESET_VGT 148 | SOFT_RESET_IA); 149 150 Write32(OUT, GRBM_SOFT_RESET, grbmReset); 151 Read32(OUT, GRBM_SOFT_RESET); 152 153 snooze(50); 154 Write32(OUT, GRBM_SOFT_RESET, 0); 155 Read32(OUT, GRBM_SOFT_RESET); 156 snooze(50); 157 } 158 159 // Resume memory controller 160 radeon_gpu_mc_resume(&gpuState); 161 return B_OK; 162 } 163 164 165 void 166 radeon_gpu_mc_halt(gpu_state *gpuState) 167 { 168 // Backup current memory controller state 169 gpuState->d1vgaControl = Read32(OUT, D1VGA_CONTROL); 170 gpuState->d2vgaControl = Read32(OUT, D2VGA_CONTROL); 171 gpuState->vgaRenderControl = Read32(OUT, VGA_RENDER_CONTROL); 172 gpuState->vgaHdpControl = Read32(OUT, VGA_HDP_CONTROL); 173 gpuState->d1crtcControl = Read32(OUT, D1CRTC_CONTROL); 174 gpuState->d2crtcControl = Read32(OUT, D2CRTC_CONTROL); 175 176 // halt all memory controller actions 177 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 178 Write32(OUT, VGA_RENDER_CONTROL, 0); 179 Write32(OUT, D1CRTC_UPDATE_LOCK, 1); 180 Write32(OUT, D2CRTC_UPDATE_LOCK, 1); 181 Write32(OUT, D1CRTC_CONTROL, 0); 182 Write32(OUT, D2CRTC_CONTROL, 0); 183 Write32(OUT, D1CRTC_UPDATE_LOCK, 0); 184 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 185 Write32(OUT, D1VGA_CONTROL, 0); 186 Write32(OUT, D2VGA_CONTROL, 0); 187 } 188 189 190 void 191 radeon_gpu_mc_resume(gpu_state *gpuState) 192 { 193 Write32(OUT, D1GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->fb.vramStart); 194 Write32(OUT, D1GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); 195 Write32(OUT, D2GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->fb.vramStart); 196 Write32(OUT, D2GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); 197 Write32(OUT, VGA_MEMORY_BASE_ADDRESS, gInfo->fb.vramStart); 198 199 // Unlock host access 200 Write32(OUT, VGA_HDP_CONTROL, gpuState->vgaHdpControl); 201 snooze(1); 202 203 // Restore memory controller state 204 Write32(OUT, D1VGA_CONTROL, gpuState->d1vgaControl); 205 Write32(OUT, D2VGA_CONTROL, gpuState->d2vgaControl); 206 Write32(OUT, D1CRTC_UPDATE_LOCK, 1); 207 Write32(OUT, D2CRTC_UPDATE_LOCK, 1); 208 Write32(OUT, D1CRTC_CONTROL, gpuState->d1crtcControl); 209 Write32(OUT, D2CRTC_CONTROL, gpuState->d2crtcControl); 210 Write32(OUT, D1CRTC_UPDATE_LOCK, 0); 211 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 212 Write32(OUT, VGA_RENDER_CONTROL, gpuState->vgaRenderControl); 213 } 214 215 216 uint32 217 radeon_gpu_mc_idlecheck() 218 { 219 uint32 idleStatus; 220 221 uint32 busyBits 222 = (VMC_BUSY | MCB_BUSY | MCDZ_BUSY | MCDY_BUSY | MCDX_BUSY | MCDW_BUSY); 223 if (!((idleStatus = Read32(MC, SRBM_STATUS)) & busyBits)) 224 return 0; 225 226 bool state; 227 state = (idleStatus & VMC_BUSY) != 0; 228 TRACE("%s: VMC is %s\n", __func__, state ? "busy" : "idle"); 229 state = (idleStatus & MCB_BUSY) != 0; 230 TRACE("%s: MCB is %s\n", __func__, state ? "busy" : "idle"); 231 state = (idleStatus & MCDZ_BUSY) != 0; 232 TRACE("%s: MCDZ is %s\n", __func__, state ? "busy" : "idle"); 233 state = (idleStatus & MCDY_BUSY) != 0; 234 TRACE("%s: MCDY is %s\n", __func__, state ? "busy" : "idle"); 235 state = (idleStatus & MCDX_BUSY) != 0; 236 TRACE("%s: MCDX is %s\n", __func__, state ? "busy" : "idle"); 237 state = (idleStatus & MCDW_BUSY) != 0; 238 TRACE("%s: MCDW is %s\n", __func__, state ? "busy" : "idle"); 239 240 return idleStatus; 241 } 242 243 244 static status_t 245 radeon_gpu_mc_setup_r600() 246 { 247 // HDP initialization 248 uint32 i; 249 uint32 j; 250 for (i = 0, j = 0; i < 32; i++, j += 0x18) { 251 Write32(OUT, (0x2c14 + j), 0x00000000); 252 Write32(OUT, (0x2c18 + j), 0x00000000); 253 Write32(OUT, (0x2c1c + j), 0x00000000); 254 Write32(OUT, (0x2c20 + j), 0x00000000); 255 Write32(OUT, (0x2c24 + j), 0x00000000); 256 } 257 Write32(OUT, HDP_REG_COHERENCY_FLUSH_CNTL, 0); 258 259 // idle the memory controller 260 struct gpu_state gpuState; 261 radeon_gpu_mc_halt(&gpuState); 262 263 uint32 idleState = radeon_gpu_mc_idlecheck(); 264 if (idleState > 0) { 265 ERROR("%s: Modifying non-idle Memory Controller! " 266 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 267 } 268 269 // TODO: Memory Controller AGP 270 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, 271 gInfo->fb.vramStart >> 12); 272 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 273 gInfo->fb.vramEnd >> 12); 274 275 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); 276 uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; 277 tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); 278 279 Write32(OUT, R600_MC_VM_FB_LOCATION, tmp); 280 Write32(OUT, HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); 281 Write32(OUT, HDP_NONSURFACE_INFO, (2 << 7)); 282 Write32(OUT, HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 283 284 // is AGP? 285 // Write32(OUT, R600_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 22); 286 // Write32(OUT, R600_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 22); 287 // Write32(OUT, R600_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); 288 // else? 289 Write32(OUT, R600_MC_VM_AGP_BASE, 0); 290 Write32(OUT, R600_MC_VM_AGP_TOP, 0x0FFFFFFF); 291 Write32(OUT, R600_MC_VM_AGP_BOT, 0x0FFFFFFF); 292 293 idleState = radeon_gpu_mc_idlecheck(); 294 if (idleState > 0) { 295 ERROR("%s: Modifying non-idle Memory Controller! " 296 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 297 } 298 radeon_gpu_mc_resume(&gpuState); 299 300 // disable render control 301 Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); 302 303 return B_OK; 304 } 305 306 307 static status_t 308 radeon_gpu_mc_setup_r700() 309 { 310 // HDP initialization 311 uint32 i; 312 uint32 j; 313 for (i = 0, j = 0; i < 32; i++, j += 0x18) { 314 Write32(OUT, (0x2c14 + j), 0x00000000); 315 Write32(OUT, (0x2c18 + j), 0x00000000); 316 Write32(OUT, (0x2c1c + j), 0x00000000); 317 Write32(OUT, (0x2c20 + j), 0x00000000); 318 Write32(OUT, (0x2c24 + j), 0x00000000); 319 } 320 321 // On r7xx read from HDP_DEBUG1 vs write HDP_REG_COHERENCY_FLUSH_CNTL 322 Read32(OUT, HDP_DEBUG1); 323 324 // idle the memory controller 325 struct gpu_state gpuState; 326 radeon_gpu_mc_halt(&gpuState); 327 328 uint32 idleState = radeon_gpu_mc_idlecheck(); 329 if (idleState > 0) { 330 ERROR("%s: Modifying non-idle Memory Controller! " 331 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 332 } 333 334 Write32(OUT, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 335 336 // TODO: Memory Controller AGP 337 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, 338 gInfo->fb.vramStart >> 12); 339 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 340 gInfo->fb.vramEnd >> 12); 341 342 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); 343 uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; 344 tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); 345 346 Write32(OUT, R700_MC_VM_FB_LOCATION, tmp); 347 Write32(OUT, HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); 348 Write32(OUT, HDP_NONSURFACE_INFO, (2 << 7)); 349 Write32(OUT, HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 350 351 // is AGP? 352 // Write32(OUT, R700_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 22); 353 // Write32(OUT, R700_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 22); 354 // Write32(OUT, R700_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); 355 // else? 356 Write32(OUT, R700_MC_VM_AGP_BASE, 0); 357 Write32(OUT, R700_MC_VM_AGP_TOP, 0x0FFFFFFF); 358 Write32(OUT, R700_MC_VM_AGP_BOT, 0x0FFFFFFF); 359 360 idleState = radeon_gpu_mc_idlecheck(); 361 if (idleState > 0) { 362 ERROR("%s: Modifying non-idle Memory Controller! " 363 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 364 } 365 radeon_gpu_mc_resume(&gpuState); 366 367 // disable render control 368 Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); 369 370 return B_OK; 371 } 372 373 374 static status_t 375 radeon_gpu_mc_setup_evergreen() 376 { 377 // HDP initialization 378 uint32 i; 379 uint32 j; 380 for (i = 0, j = 0; i < 32; i++, j += 0x18) { 381 Write32(OUT, (0x2c14 + j), 0x00000000); 382 Write32(OUT, (0x2c18 + j), 0x00000000); 383 Write32(OUT, (0x2c1c + j), 0x00000000); 384 Write32(OUT, (0x2c20 + j), 0x00000000); 385 Write32(OUT, (0x2c24 + j), 0x00000000); 386 } 387 Write32(OUT, HDP_REG_COHERENCY_FLUSH_CNTL, 0); 388 389 // idle the memory controller 390 struct gpu_state gpuState; 391 radeon_gpu_mc_halt(&gpuState); 392 393 uint32 idleState = radeon_gpu_mc_idlecheck(); 394 if (idleState > 0) { 395 ERROR("%s: Modifying non-idle Memory Controller! " 396 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 397 } 398 399 Write32(OUT, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 400 401 // TODO: Memory Controller AGP 402 Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_LOW_ADDR, 403 gInfo->fb.vramStart >> 12); 404 Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 405 gInfo->fb.vramEnd >> 12); 406 407 Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); 408 409 radeon_shared_info &info = *gInfo->shared_info; 410 if ((info.chipsetFlags & CHIP_IGP) != 0) { 411 // Evergreen IGP Fusion 412 uint32 tmp = Read32(OUT, EVERGREEN_MC_FUS_VM_FB_OFFSET) 413 & 0x000FFFFF; 414 tmp |= ((gInfo->fb.vramEnd >> 20) & 0xF) << 24; 415 tmp |= ((gInfo->fb.vramStart >> 20) & 0xF) << 20; 416 Write32(OUT, EVERGREEN_MC_FUS_VM_FB_OFFSET, tmp); 417 } 418 419 uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; 420 tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); 421 422 Write32(OUT, EVERGREEN_MC_VM_FB_LOCATION, tmp); 423 Write32(OUT, HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); 424 Write32(OUT, HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); 425 Write32(OUT, HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 426 427 // is AGP? 428 // Write32(OUT, EVERGREEN_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 16); 429 // Write32(OUT, EVERGREEN_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 16); 430 // Write32(OUT, EVERGREEN_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); 431 // else? 432 Write32(OUT, EVERGREEN_MC_VM_AGP_BASE, 0); 433 Write32(OUT, EVERGREEN_MC_VM_AGP_TOP, 0x0FFFFFFF); 434 Write32(OUT, EVERGREEN_MC_VM_AGP_BOT, 0x0FFFFFFF); 435 436 idleState = radeon_gpu_mc_idlecheck(); 437 if (idleState > 0) { 438 ERROR("%s: Modifying non-idle Memory Controller! " 439 " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); 440 } 441 radeon_gpu_mc_resume(&gpuState); 442 443 // disable render control 444 Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); 445 446 return B_OK; 447 } 448 449 450 void 451 radeon_gpu_mc_init() 452 { 453 radeon_shared_info &info = *gInfo->shared_info; 454 455 uint32 fbVMLocationReg; 456 if (info.chipsetID >= RADEON_CEDAR) { 457 fbVMLocationReg = EVERGREEN_MC_VM_FB_LOCATION; 458 } else if (info.chipsetID >= RADEON_RV770) { 459 fbVMLocationReg = R700_MC_VM_FB_LOCATION; 460 } else { 461 fbVMLocationReg = R600_MC_VM_FB_LOCATION; 462 } 463 464 if (gInfo->shared_info->frame_buffer_size > 0) 465 gInfo->fb.valid = true; 466 467 // TODO: 0 should be correct here... but it gets me vertical stripes 468 //uint64 vramBase = 0; 469 uint64 vramBase = gInfo->shared_info->frame_buffer_phys; 470 471 if ((info.chipsetFlags & CHIP_IGP) != 0) { 472 vramBase = Read32(OUT, fbVMLocationReg) & 0xFFFF; 473 vramBase <<= 24; 474 } 475 476 gInfo->fb.vramStart = vramBase; 477 gInfo->fb.vramSize = gInfo->shared_info->frame_buffer_size * 1024; 478 gInfo->fb.vramEnd = (vramBase + gInfo->fb.vramSize) - 1; 479 } 480 481 482 status_t 483 radeon_gpu_mc_setup() 484 { 485 radeon_shared_info &info = *gInfo->shared_info; 486 487 radeon_gpu_mc_init(); 488 // init video ram ranges for memory controler 489 490 if (gInfo->fb.valid != true) { 491 ERROR("%s: Memory Controller init failed.\n", __func__); 492 return B_ERROR; 493 } 494 495 TRACE("%s: vramStart: 0x%" B_PRIX64 ", vramEnd: 0x%" B_PRIX64 "\n", 496 __func__, gInfo->fb.vramStart, gInfo->fb.vramEnd); 497 498 if (info.chipsetID >= RADEON_CAYMAN) 499 return radeon_gpu_mc_setup_evergreen(); // also for ni 500 else if (info.chipsetID >= RADEON_CEDAR) 501 return radeon_gpu_mc_setup_evergreen(); 502 else if (info.chipsetID >= RADEON_RV770) 503 return radeon_gpu_mc_setup_r700(); 504 else if (info.chipsetID >= RADEON_R600) 505 return radeon_gpu_mc_setup_r600(); 506 507 return B_ERROR; 508 } 509 510 511 status_t 512 radeon_gpu_irq_setup() 513 { 514 // TODO: Stub for IRQ setup 515 516 // allocate rings via r600_ih_ring_alloc 517 518 // disable irq's via r600_disable_interrupts 519 520 // r600_rlc_init 521 522 // setup interrupt control 523 524 return B_ERROR; 525 } 526 527 528 static void 529 lock_i2c(void* cookie, bool lock) 530 { 531 gpio_info *info = (gpio_info*)cookie; 532 radeon_shared_info &sinfo = *gInfo->shared_info; 533 534 uint32 buffer = 0; 535 536 if (lock == true) { 537 // hw_capable and > DCE3 538 if (info->hw_capable == true 539 && sinfo.dceMajor >= 3) { 540 // Switch GPIO pads to ddc mode 541 buffer = Read32(OUT, info->mask_scl_reg); 542 buffer &= ~(1 << 16); 543 Write32(OUT, info->mask_scl_reg, buffer); 544 } 545 546 // Clear pins 547 buffer = Read32(OUT, info->a_scl_reg) & ~info->a_scl_mask; 548 Write32(OUT, info->a_scl_reg, buffer); 549 buffer = Read32(OUT, info->a_sda_reg) & ~info->a_sda_mask; 550 Write32(OUT, info->a_sda_reg, buffer); 551 } 552 553 // Set pins to input 554 buffer = Read32(OUT, info->en_scl_reg) & ~info->en_scl_mask; 555 Write32(OUT, info->en_scl_reg, buffer); 556 buffer = Read32(OUT, info->en_sda_reg) & ~info->en_sda_mask; 557 Write32(OUT, info->en_sda_reg, buffer); 558 559 // mask GPIO pins for software use 560 buffer = Read32(OUT, info->mask_scl_reg); 561 if (lock == true) { 562 buffer |= info->mask_scl_mask; 563 } else { 564 buffer &= ~info->mask_scl_mask; 565 } 566 Write32(OUT, info->mask_scl_reg, buffer); 567 Read32(OUT, info->mask_scl_reg); 568 569 buffer = Read32(OUT, info->mask_sda_reg); 570 if (lock == true) { 571 buffer |= info->mask_sda_mask; 572 } else { 573 buffer &= ~info->mask_sda_mask; 574 } 575 Write32(OUT, info->mask_sda_reg, buffer); 576 Read32(OUT, info->mask_sda_reg); 577 } 578 579 580 static status_t 581 get_i2c_signals(void* cookie, int* _clock, int* _data) 582 { 583 gpio_info *info = (gpio_info*)cookie; 584 585 uint32 scl = Read32(OUT, info->y_scl_reg) 586 & info->y_scl_mask; 587 uint32 sda = Read32(OUT, info->y_sda_reg) 588 & info->y_sda_mask; 589 590 *_clock = (scl != 0); 591 *_data = (sda != 0); 592 593 return B_OK; 594 } 595 596 597 static status_t 598 set_i2c_signals(void* cookie, int clock, int data) 599 { 600 gpio_info* info = (gpio_info*)cookie; 601 602 uint32 scl = Read32(OUT, info->en_scl_reg) 603 & ~info->en_scl_mask; 604 scl |= clock ? 0 : info->en_scl_mask; 605 Write32(OUT, info->en_scl_reg, scl); 606 Read32(OUT, info->en_scl_reg); 607 608 uint32 sda = Read32(OUT, info->en_sda_reg) 609 & ~info->en_sda_mask; 610 sda |= data ? 0 : info->en_sda_mask; 611 Write32(OUT, info->en_sda_reg, sda); 612 Read32(OUT, info->en_sda_reg); 613 614 return B_OK; 615 } 616 617 618 bool 619 radeon_gpu_read_edid(uint32 connector, edid1_info *edid) 620 { 621 // ensure things are sane 622 uint32 gpioID = gConnector[connector]->gpioID; 623 if (gGPIOInfo[gpioID]->valid == false) 624 return false; 625 626 if (gConnector[connector]->type == VIDEO_CONNECTOR_LVDS) { 627 // we should call radeon_gpu_read_edid_lvds at some point 628 ERROR("%s: LCD panel detected (LVDS), sending VESA EDID!\n", 629 __func__); 630 memcpy(edid, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 631 return true; 632 } 633 634 i2c_bus bus; 635 636 ddc2_init_timing(&bus); 637 bus.cookie = (void*)gGPIOInfo[gpioID]; 638 bus.set_signals = &set_i2c_signals; 639 bus.get_signals = &get_i2c_signals; 640 641 lock_i2c(bus.cookie, true); 642 status_t edid_result = ddc2_read_edid1(&bus, edid, NULL, NULL); 643 lock_i2c(bus.cookie, false); 644 645 if (edid_result != B_OK) 646 return false; 647 648 TRACE("%s: found edid monitor on connector #%" B_PRId32 "\n", 649 __func__, connector); 650 651 return true; 652 } 653 654 655 #if 0 656 bool 657 radeon_gpu_read_edid_lvds(uint32 connector, edid1_info *edid) 658 { 659 uint8 dceMajor; 660 uint8 dceMinor; 661 int index = GetIndexIntoMasterTable(DATA, LVDS_Info); 662 uint16 offset; 663 664 if (atom_parse_data_header(gAtomContexg, index, NULL, 665 &dceMajor, &dceMinor, &offset) == B_OK) { 666 lvdsInfo = (union lvds_info *)(gAtomContext->bios + offset); 667 668 display_timing timing; 669 // Pixel Clock 670 timing.pixel_clock 671 = B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usPixClk) * 10; 672 // Horizontal 673 timing.h_display 674 = B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHActive); 675 timing.h_total = timing.h_display + B_LENDIAN_TO_HOST_INT16( 676 lvdsInfo->info.sLCDTiming.usHBlanking_Time); 677 timing.h_sync_start = timing.h_display 678 + B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncOffset); 679 timing.h_sync_end = timing.h_sync_start 680 + B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncWidth); 681 // Vertical 682 timing.v_display 683 = B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVActive); 684 timing.v_total = timing.v_display + B_LENDIAN_TO_HOST_INT16( 685 lvdsInfo->info.sLCDTiming.usVBlanking_Time); 686 timing.v_sync_start = timing.v_display 687 + B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncOffset); 688 timing.v_sync_end = timing.v_sync_start 689 + B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncWidth); 690 691 #if 0 692 // Who cares. 693 uint32 powerDelay 694 = B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.usOffDelayInMs); 695 uint32 lcdMisc = lvdsInfo->info.ucLVDS_Misc; 696 #endif 697 698 uint16 flags = B_LENDIAN_TO_HOST_INT16( 699 lvdsInfo->info.sLCDTiming.susModeMiscInfo.usAccess); 700 701 if ((flags & ATOM_VSYNC_POLARITY) == 0) 702 timing.flags |= B_POSITIVE_VSYNC; 703 if ((flags & ATOM_HSYNC_POLARITY) == 0) 704 timing.flags |= B_POSITIVE_HSYNC; 705 706 // Extra flags 707 if ((flags & ATOM_INTERLACE) != 0) 708 timing.flags |= B_TIMING_INTERLACED; 709 710 #if 0 711 // We don't use these timing flags at the moment 712 if ((flags & ATOM_COMPOSITESYNC) != 0) 713 timing.flags |= MODE_FLAG_CSYNC; 714 if ((flags & ATOM_DOUBLE_CLOCK_MODE) != 0) 715 timing.flags |= MODE_FLAG_DBLSCAN; 716 #endif 717 718 // TODO: generate a fake EDID with information above 719 } 720 } 721 #endif 722 723 724 status_t 725 radeon_gpu_i2c_attach(uint32 id, uint8 hw_line) 726 { 727 gConnector[id]->gpioID = 0; 728 for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 729 if (gGPIOInfo[i]->hw_line != hw_line) 730 continue; 731 gConnector[id]->gpioID = i; 732 return B_OK; 733 } 734 735 TRACE("%s: couldn't find GPIO for connector %" B_PRIu32 "\n", 736 __func__, id); 737 return B_ERROR; 738 } 739 740 741 status_t 742 radeon_gpu_gpio_setup() 743 { 744 radeon_shared_info &info = *gInfo->shared_info; 745 746 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); 747 748 uint8 tableMajor; 749 uint8 tableMinor; 750 uint16 tableOffset; 751 uint16 tableSize; 752 753 if (atom_parse_data_header(gAtomContext, index, &tableSize, 754 &tableMajor, &tableMinor, &tableOffset) != B_OK) { 755 ERROR("%s: could't read GPIO_I2C_Info table from AtomBIOS index %d!\n", 756 __func__, index); 757 return B_ERROR; 758 } 759 760 struct _ATOM_GPIO_I2C_INFO *i2c_info 761 = (struct _ATOM_GPIO_I2C_INFO *)(gAtomContext->bios + tableOffset); 762 763 uint32 numIndices = (tableSize - sizeof(ATOM_COMMON_TABLE_HEADER)) 764 / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 765 766 if (numIndices > ATOM_MAX_SUPPORTED_DEVICE) { 767 ERROR("%s: ERROR: AtomBIOS contains more GPIO_Info items then I" 768 "was prepared for! (seen: %" B_PRIu32 "; max: %" B_PRIu32 ")\n", 769 __func__, numIndices, (uint32)ATOM_MAX_SUPPORTED_DEVICE); 770 return B_ERROR; 771 } 772 773 for (uint32 i = 0; i < numIndices; i++) { 774 ATOM_GPIO_I2C_ASSIGMENT *gpio = &i2c_info->asGPIO_Info[i]; 775 776 if (info.dceMajor >= 3) { 777 if (i == 4 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) 778 == 0x1fda && gpio->sucI2cId.ucAccess == 0x94) { 779 gpio->sucI2cId.ucAccess = 0x14; 780 TRACE("%s: BUG: GPIO override for DCE 3 occured\n", __func__); 781 } 782 } 783 784 if (info.dceMajor >= 4) { 785 if (i == 7 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) 786 == 0x1936 && gpio->sucI2cId.ucAccess == 0) { 787 gpio->sucI2cId.ucAccess = 0x97; 788 gpio->ucDataMaskShift = 8; 789 gpio->ucDataEnShift = 8; 790 gpio->ucDataY_Shift = 8; 791 gpio->ucDataA_Shift = 8; 792 TRACE("%s: BUG: GPIO override for DCE 4 occured\n", __func__); 793 } 794 } 795 796 // populate gpio information 797 gGPIOInfo[i]->hw_line 798 = gpio->sucI2cId.ucAccess; 799 gGPIOInfo[i]->hw_capable 800 = (gpio->sucI2cId.sbfAccess.bfHW_Capable) ? true : false; 801 802 // GPIO mask (Allows software to control the GPIO pad) 803 // 0 = chip access; 1 = only software; 804 gGPIOInfo[i]->mask_scl_reg 805 = B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) * 4; 806 gGPIOInfo[i]->mask_sda_reg 807 = B_LENDIAN_TO_HOST_INT16(gpio->usDataMaskRegisterIndex) * 4; 808 gGPIOInfo[i]->mask_scl_mask 809 = (1 << gpio->ucClkMaskShift); 810 gGPIOInfo[i]->mask_sda_mask 811 = (1 << gpio->ucDataMaskShift); 812 813 // GPIO output / write (A) enable 814 // 0 = GPIO input (Y); 1 = GPIO output (A); 815 gGPIOInfo[i]->en_scl_reg 816 = B_LENDIAN_TO_HOST_INT16(gpio->usClkEnRegisterIndex) * 4; 817 gGPIOInfo[i]->en_sda_reg 818 = B_LENDIAN_TO_HOST_INT16(gpio->usDataEnRegisterIndex) * 4; 819 gGPIOInfo[i]->en_scl_mask 820 = (1 << gpio->ucClkEnShift); 821 gGPIOInfo[i]->en_sda_mask 822 = (1 << gpio->ucDataEnShift); 823 824 // GPIO output / write (A) 825 gGPIOInfo[i]->a_scl_reg 826 = B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4; 827 gGPIOInfo[i]->a_sda_reg 828 = B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4; 829 gGPIOInfo[i]->a_scl_mask 830 = (1 << gpio->ucClkA_Shift); 831 gGPIOInfo[i]->a_sda_mask 832 = (1 << gpio->ucDataA_Shift); 833 834 // GPIO input / read (Y) 835 gGPIOInfo[i]->y_scl_reg 836 = B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4; 837 gGPIOInfo[i]->y_sda_reg 838 = B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4; 839 gGPIOInfo[i]->y_scl_mask 840 = (1 << gpio->ucClkY_Shift); 841 gGPIOInfo[i]->y_sda_mask 842 = (1 << gpio->ucDataY_Shift); 843 844 // ensure data is valid 845 gGPIOInfo[i]->valid = (gGPIOInfo[i]->mask_scl_reg) ? true : false; 846 847 TRACE("%s: GPIO @ %" B_PRIu32 ", valid: %s, hw_line: 0x%" B_PRIX32 "\n", 848 __func__, i, gGPIOInfo[i]->valid ? "true" : "false", 849 gGPIOInfo[i]->hw_line); 850 } 851 852 return B_OK; 853 } 854