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 radeon_gpu_mc_halt(); 45 46 if (radeon_gpu_mc_idlecheck() > 0) { 47 ERROR("%s: Timeout waiting for MC to idle!\n", __func__); 48 } 49 50 if (info.device_chipset < RADEON_R1000) { 51 Write32(OUT, CP_ME_CNTL, CP_ME_HALT); 52 // Disable Command Processor parsing / prefetching 53 54 // Register busy masks for early Radeon HD cards 55 56 // GRBM Command Processor Status 57 uint32 grbm_busy_mask = VC_BUSY; 58 // Vertex Cache Busy 59 grbm_busy_mask |= VGT_BUSY_NO_DMA | VGT_BUSY; 60 // Vertex Grouper Tessellator Busy 61 grbm_busy_mask |= TA03_BUSY; 62 // unknown 63 grbm_busy_mask |= TC_BUSY; 64 // Texture Cache Busy 65 grbm_busy_mask |= SX_BUSY; 66 // Shader Export Busy 67 grbm_busy_mask |= SH_BUSY; 68 // Sequencer Instruction Cache Busy 69 grbm_busy_mask |= SPI_BUSY; 70 // Shader Processor Interpolator Busy 71 grbm_busy_mask |= SMX_BUSY; 72 // Shader Memory Exchange 73 grbm_busy_mask |= SC_BUSY; 74 // Scan Converter Busy 75 grbm_busy_mask |= PA_BUSY; 76 // Primitive Assembler Busy 77 grbm_busy_mask |= DB_BUSY; 78 // Depth Block Busy 79 grbm_busy_mask |= CR_BUSY; 80 // unknown 81 grbm_busy_mask |= CB_BUSY; 82 // Color Block Busy 83 grbm_busy_mask |= GUI_ACTIVE; 84 // unknown (graphics pipeline active?) 85 86 // GRBM Command Processor Detailed Status 87 uint32 grbm2_busy_mask = SPI0_BUSY | SPI1_BUSY | SPI2_BUSY | SPI3_BUSY; 88 // Shader Processor Interpolator 0 - 3 Busy 89 grbm2_busy_mask |= TA0_BUSY | TA1_BUSY | TA2_BUSY | TA3_BUSY; 90 // unknown 0 - 3 Busy 91 grbm2_busy_mask |= DB0_BUSY | DB1_BUSY | DB2_BUSY | DB3_BUSY; 92 // Depth Block 0 - 3 Busy 93 grbm2_busy_mask |= CB0_BUSY | CB1_BUSY | CB2_BUSY | CB3_BUSY; 94 // Color Block 0 - 3 Busy 95 96 uint32 tmp; 97 /* Check if any of the rendering block is busy and reset it */ 98 if ((Read32(OUT, GRBM_STATUS) & grbm_busy_mask) != 0 99 || (Read32(OUT, GRBM_STATUS2) & grbm2_busy_mask) != 0) { 100 tmp = SOFT_RESET_CR 101 | SOFT_RESET_DB 102 | SOFT_RESET_CB 103 | SOFT_RESET_PA 104 | SOFT_RESET_SC 105 | SOFT_RESET_SMX 106 | SOFT_RESET_SPI 107 | SOFT_RESET_SX 108 | SOFT_RESET_SH 109 | SOFT_RESET_TC 110 | SOFT_RESET_TA 111 | SOFT_RESET_VC 112 | SOFT_RESET_VGT; 113 Write32(OUT, GRBM_SOFT_RESET, tmp); 114 Read32(OUT, GRBM_SOFT_RESET); 115 snooze(15000); 116 Write32(OUT, GRBM_SOFT_RESET, 0); 117 } 118 119 // Reset CP 120 tmp = SOFT_RESET_CP; 121 Write32(OUT, GRBM_SOFT_RESET, tmp); 122 Read32(OUT, GRBM_SOFT_RESET); 123 snooze(15000); 124 Write32(OUT, GRBM_SOFT_RESET, 0); 125 126 // Let things settle 127 snooze(1000); 128 } else { 129 // Northern Islands and higher 130 131 Write32(OUT, CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); 132 // Disable Command Processor parsing / prefetching 133 134 // reset the graphics pipeline components 135 uint32 grbm_reset = (SOFT_RESET_CP 136 | SOFT_RESET_CB 137 | SOFT_RESET_DB 138 | SOFT_RESET_GDS 139 | SOFT_RESET_PA 140 | SOFT_RESET_SC 141 | SOFT_RESET_SPI 142 | SOFT_RESET_SH 143 | SOFT_RESET_SX 144 | SOFT_RESET_TC 145 | SOFT_RESET_TA 146 | SOFT_RESET_VGT 147 | SOFT_RESET_IA); 148 149 Write32(OUT, GRBM_SOFT_RESET, grbm_reset); 150 Read32(OUT, GRBM_SOFT_RESET); 151 152 snooze(50); 153 Write32(OUT, GRBM_SOFT_RESET, 0); 154 Read32(OUT, GRBM_SOFT_RESET); 155 snooze(50); 156 } 157 158 // Resume memory controller 159 radeon_gpu_mc_resume(); 160 return B_OK; 161 } 162 163 164 void 165 radeon_gpu_mc_halt() 166 { 167 // Backup current memory controller state 168 gInfo->gpu_info.d1vga_control = Read32(OUT, D1VGA_CONTROL); 169 gInfo->gpu_info.d2vga_control = Read32(OUT, D2VGA_CONTROL); 170 gInfo->gpu_info.vga_render_control = Read32(OUT, VGA_RENDER_CONTROL); 171 gInfo->gpu_info.vga_hdp_control = Read32(OUT, VGA_HDP_CONTROL); 172 gInfo->gpu_info.d1crtc_control = Read32(OUT, D1CRTC_CONTROL); 173 gInfo->gpu_info.d2crtc_control = Read32(OUT, D2CRTC_CONTROL); 174 175 // halt all memory controller actions 176 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 177 Write32(OUT, VGA_RENDER_CONTROL, 0); 178 Write32(OUT, D1CRTC_UPDATE_LOCK, 1); 179 Write32(OUT, D2CRTC_UPDATE_LOCK, 1); 180 Write32(OUT, D1CRTC_CONTROL, 0); 181 Write32(OUT, D2CRTC_CONTROL, 0); 182 Write32(OUT, D1CRTC_UPDATE_LOCK, 0); 183 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 184 Write32(OUT, D1VGA_CONTROL, 0); 185 Write32(OUT, D2VGA_CONTROL, 0); 186 } 187 188 189 void 190 radeon_gpu_mc_resume() 191 { 192 Write32(OUT, D1GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->mc.vramStart); 193 Write32(OUT, D1GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->mc.vramStart); 194 Write32(OUT, D2GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->mc.vramStart); 195 Write32(OUT, D2GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->mc.vramStart); 196 Write32(OUT, VGA_MEMORY_BASE_ADDRESS, gInfo->mc.vramStart); 197 198 // Unlock host access 199 Write32(OUT, VGA_HDP_CONTROL, gInfo->gpu_info.vga_hdp_control); 200 snooze(1); 201 202 // Restore memory controller state 203 Write32(OUT, D1VGA_CONTROL, gInfo->gpu_info.d1vga_control); 204 Write32(OUT, D2VGA_CONTROL, gInfo->gpu_info.d2vga_control); 205 Write32(OUT, D1CRTC_UPDATE_LOCK, 1); 206 Write32(OUT, D2CRTC_UPDATE_LOCK, 1); 207 Write32(OUT, D1CRTC_CONTROL, gInfo->gpu_info.d1crtc_control); 208 Write32(OUT, D2CRTC_CONTROL, gInfo->gpu_info.d2crtc_control); 209 Write32(OUT, D1CRTC_UPDATE_LOCK, 0); 210 Write32(OUT, D2CRTC_UPDATE_LOCK, 0); 211 Write32(OUT, VGA_RENDER_CONTROL, gInfo->gpu_info.vga_render_control); 212 } 213 214 215 uint32 216 radeon_gpu_mc_idlecheck() 217 { 218 uint32 idleStatus; 219 if (!((idleStatus = Read32(MC, SRBM_STATUS)) & 220 (VMC_BUSY | MCB_BUSY | 221 MCDZ_BUSY | MCDY_BUSY | MCDX_BUSY | MCDW_BUSY))) 222 return 0; 223 224 return idleStatus; 225 } 226 227 228 static status_t 229 radeon_gpu_mc_setup_r600() 230 { 231 // HDP initialization 232 uint32 i; 233 uint32 j; 234 for (i = 0, j = 0; i < 32; i++, j += 0x18) { 235 Write32(OUT, (0x2c14 + j), 0x00000000); 236 Write32(OUT, (0x2c18 + j), 0x00000000); 237 Write32(OUT, (0x2c1c + j), 0x00000000); 238 Write32(OUT, (0x2c20 + j), 0x00000000); 239 Write32(OUT, (0x2c24 + j), 0x00000000); 240 } 241 Write32(OUT, HDP_REG_COHERENCY_FLUSH_CNTL, 0); 242 243 // idle the memory controller 244 radeon_gpu_mc_halt(); 245 246 uint32 idleState = radeon_gpu_mc_idlecheck(); 247 if (idleState > 0) { 248 ERROR("%s: Cannot modify non-idle MC! idleState: 0x%" B_PRIX32 "\n", 249 __func__, idleState); 250 //return B_ERROR; 251 } 252 253 // TODO: Memory Controller AGP 254 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, 255 gInfo->mc.vramStart >> 12); 256 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 257 gInfo->mc.vramEnd >> 12); 258 259 Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); 260 uint32 tmp = ((gInfo->mc.vramEnd >> 24) & 0xFFFF) << 16; 261 tmp |= ((gInfo->mc.vramStart >> 24) & 0xFFFF); 262 263 Write32(OUT, R600_MC_VM_FB_LOCATION, tmp); 264 Write32(OUT, HDP_NONSURFACE_BASE, (gInfo->mc.vramStart >> 8)); 265 Write32(OUT, HDP_NONSURFACE_INFO, (2 << 7)); 266 Write32(OUT, HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 267 268 // TODO: AGP gtt start / end / agp base 269 // is AGP? 270 // WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); 271 // WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); 272 // WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); 273 // else? 274 Write32(OUT, R600_MC_VM_AGP_BASE, 0); 275 Write32(OUT, R600_MC_VM_AGP_TOP, 0x0FFFFFFF); 276 Write32(OUT, R600_MC_VM_AGP_BOT, 0x0FFFFFFF); 277 278 idleState = radeon_gpu_mc_idlecheck(); 279 if (idleState > 0) { 280 ERROR("%s: Cannot modify non-idle MC! idleState: 0x%" B_PRIX32 "\n", 281 __func__, idleState); 282 //return B_ERROR; 283 } 284 radeon_gpu_mc_resume(); 285 286 // disable render control 287 Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); 288 289 return B_OK; 290 } 291 292 293 static status_t 294 radeon_gpu_mc_setup_r700() 295 { 296 // HDP initialization 297 uint32 i; 298 uint32 j; 299 for (i = 0, j = 0; i < 32; i++, j += 0x18) { 300 Write32(OUT, (0x2c14 + j), 0x00000000); 301 Write32(OUT, (0x2c18 + j), 0x00000000); 302 Write32(OUT, (0x2c1c + j), 0x00000000); 303 Write32(OUT, (0x2c20 + j), 0x00000000); 304 Write32(OUT, (0x2c24 + j), 0x00000000); 305 } 306 307 // On r7xx read from HDP_DEBUG1 vs write HDP_REG_COHERENCY_FLUSH_CNTL 308 Read32(OUT, HDP_DEBUG1); 309 310 // idle the memory controller 311 radeon_gpu_mc_halt(); 312 313 uint32 idleState = radeon_gpu_mc_idlecheck(); 314 if (idleState > 0) { 315 ERROR("%s: Cannot modify non-idle MC! idleState: 0x%" B_PRIX32 "\n", 316 __func__, idleState); 317 //return B_ERROR; 318 } 319 320 Write32(OUT, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 321 322 // TODO: Memory Controller AGP 323 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, 324 gInfo->mc.vramStart >> 12); 325 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 326 gInfo->mc.vramEnd >> 12); 327 328 Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); 329 uint32 tmp = ((gInfo->mc.vramEnd >> 24) & 0xFFFF) << 16; 330 tmp |= ((gInfo->mc.vramStart >> 24) & 0xFFFF); 331 332 Write32(OUT, R700_MC_VM_FB_LOCATION, tmp); 333 Write32(OUT, HDP_NONSURFACE_BASE, (gInfo->mc.vramStart >> 8)); 334 Write32(OUT, HDP_NONSURFACE_INFO, (2 << 7)); 335 Write32(OUT, HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 336 337 // TODO: AGP gtt start / end / agp base 338 // is AGP? 339 // WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); 340 // WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); 341 // WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); 342 // else? 343 Write32(OUT, R700_MC_VM_AGP_BASE, 0); 344 Write32(OUT, R700_MC_VM_AGP_TOP, 0x0FFFFFFF); 345 Write32(OUT, R700_MC_VM_AGP_BOT, 0x0FFFFFFF); 346 347 idleState = radeon_gpu_mc_idlecheck(); 348 if (idleState > 0) { 349 ERROR("%s: Cannot modify non-idle MC! idleState: 0x%" B_PRIX32 "\n", 350 __func__, idleState); 351 //return B_ERROR; 352 } 353 radeon_gpu_mc_resume(); 354 355 // disable render control 356 Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); 357 358 return B_OK; 359 } 360 361 362 void 363 radeon_gpu_mc_init() 364 { 365 radeon_shared_info &info = *gInfo->shared_info; 366 367 uint32 fbVMLocationReg; 368 if (info.device_chipset >= RADEON_R700) { 369 fbVMLocationReg = R700_MC_VM_FB_LOCATION; 370 } else { 371 fbVMLocationReg = R600_MC_VM_FB_LOCATION; 372 } 373 374 if (gInfo->shared_info->frame_buffer_size > 0) 375 gInfo->mc.valid = true; 376 377 // TODO: 0 should be correct here... but it gets me vertical stripes 378 //uint64 vramBase = 0; 379 uint64 vramBase = gInfo->shared_info->frame_buffer_phys; 380 381 if ((info.chipsetFlags & CHIP_IGP) != 0) { 382 vramBase = Read32(OUT, fbVMLocationReg) & 0xFFFF; 383 vramBase <<= 24; 384 } 385 386 gInfo->mc.vramStart = vramBase; 387 gInfo->mc.vramSize = gInfo->shared_info->frame_buffer_size * 1024; 388 gInfo->mc.vramEnd = (vramBase + gInfo->mc.vramSize) - 1; 389 } 390 391 392 status_t 393 radeon_gpu_mc_setup() 394 { 395 radeon_shared_info &info = *gInfo->shared_info; 396 397 radeon_gpu_mc_init(); 398 // init video ram ranges for memory controler 399 400 if (gInfo->mc.valid != true) { 401 ERROR("%s: Memory Controller init failed.\n", __func__); 402 return B_ERROR; 403 } 404 405 TRACE("%s: vramStart: 0x%" B_PRIX64 ", vramEnd: 0x%" B_PRIX64 "\n", 406 __func__, gInfo->mc.vramStart, gInfo->mc.vramEnd); 407 408 if (info.device_chipset >= RADEON_R700) 409 return radeon_gpu_mc_setup_r700(); 410 else if (info.device_chipset >= RADEON_R600) 411 return radeon_gpu_mc_setup_r600(); 412 413 return B_ERROR; 414 } 415 416 417 status_t 418 radeon_gpu_irq_setup() 419 { 420 // TODO: Stub for IRQ setup 421 422 // allocate rings via r600_ih_ring_alloc 423 424 // disable irq's via r600_disable_interrupts 425 426 // r600_rlc_init 427 428 // setup interrupt control 429 430 return B_ERROR; 431 } 432 433 434 static void 435 lock_i2c(void* cookie, bool lock) 436 { 437 gpio_info *info = (gpio_info*)cookie; 438 radeon_shared_info &sinfo = *gInfo->shared_info; 439 440 uint32 buffer = 0; 441 442 if (lock == true) { 443 // hw_capable and > DCE3 444 if (info->hw_capable == true 445 && sinfo.device_chipset >= (RADEON_R600 | 0x20)) { 446 // Switch GPIO pads to ddc mode 447 buffer = Read32(OUT, info->mask_scl_reg); 448 buffer &= ~(1 << 16); 449 Write32(OUT, info->mask_scl_reg, buffer); 450 } 451 452 // Clear pins 453 buffer = Read32(OUT, info->a_scl_reg) & ~info->a_scl_mask; 454 Write32(OUT, info->a_scl_reg, buffer); 455 buffer = Read32(OUT, info->a_sda_reg) & ~info->a_sda_mask; 456 Write32(OUT, info->a_sda_reg, buffer); 457 } 458 459 // Set pins to input 460 buffer = Read32(OUT, info->en_scl_reg) & ~info->en_scl_mask; 461 Write32(OUT, info->en_scl_reg, buffer); 462 buffer = Read32(OUT, info->en_sda_reg) & ~info->en_sda_mask; 463 Write32(OUT, info->en_sda_reg, buffer); 464 465 // mask GPIO pins for software use 466 buffer = Read32(OUT, info->mask_scl_reg); 467 if (lock == true) { 468 buffer |= info->mask_scl_mask; 469 } else { 470 buffer &= ~info->mask_scl_mask; 471 } 472 Write32(OUT, info->mask_scl_reg, buffer); 473 Read32(OUT, info->mask_scl_reg); 474 475 buffer = Read32(OUT, info->mask_sda_reg); 476 if (lock == true) { 477 buffer |= info->mask_sda_mask; 478 } else { 479 buffer &= ~info->mask_sda_mask; 480 } 481 Write32(OUT, info->mask_sda_reg, buffer); 482 Read32(OUT, info->mask_sda_reg); 483 } 484 485 486 static status_t 487 get_i2c_signals(void* cookie, int* _clock, int* _data) 488 { 489 gpio_info *info = (gpio_info*)cookie; 490 491 uint32 scl = Read32(OUT, info->y_scl_reg) 492 & info->y_scl_mask; 493 uint32 sda = Read32(OUT, info->y_sda_reg) 494 & info->y_sda_mask; 495 496 *_clock = (scl != 0); 497 *_data = (sda != 0); 498 499 return B_OK; 500 } 501 502 503 static status_t 504 set_i2c_signals(void* cookie, int clock, int data) 505 { 506 gpio_info* info = (gpio_info*)cookie; 507 508 uint32 scl = Read32(OUT, info->en_scl_reg) 509 & ~info->en_scl_mask; 510 scl |= clock ? 0 : info->en_scl_mask; 511 Write32(OUT, info->en_scl_reg, scl); 512 Read32(OUT, info->en_scl_reg); 513 514 uint32 sda = Read32(OUT, info->en_sda_reg) 515 & ~info->en_sda_mask; 516 sda |= data ? 0 : info->en_sda_mask; 517 Write32(OUT, info->en_sda_reg, sda); 518 Read32(OUT, info->en_sda_reg); 519 520 return B_OK; 521 } 522 523 524 bool 525 radeon_gpu_read_edid(uint32 connector, edid1_info *edid) 526 { 527 // ensure things are sane 528 uint32 gpioID = gConnector[connector]->gpioID; 529 if (gGPIOInfo[gpioID]->valid == false) 530 return false; 531 532 i2c_bus bus; 533 534 ddc2_init_timing(&bus); 535 bus.cookie = (void*)gGPIOInfo[gpioID]; 536 bus.set_signals = &set_i2c_signals; 537 bus.get_signals = &get_i2c_signals; 538 539 lock_i2c(bus.cookie, true); 540 status_t edid_result = ddc2_read_edid1(&bus, edid, NULL, NULL); 541 lock_i2c(bus.cookie, false); 542 543 if (edid_result != B_OK) 544 return false; 545 546 TRACE("%s: found edid monitor on connector #%" B_PRId32 "\n", 547 __func__, connector); 548 549 return true; 550 } 551 552 553 status_t 554 radeon_gpu_i2c_attach(uint32 id, uint8 hw_line) 555 { 556 gConnector[id]->gpioID = 0; 557 for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 558 if (gGPIOInfo[i]->hw_line != hw_line) 559 continue; 560 gConnector[id]->gpioID = i; 561 return B_OK; 562 } 563 564 TRACE("%s: couldn't find GPIO for connector %" B_PRIu32 "\n", 565 __func__, id); 566 return B_ERROR; 567 } 568 569 570 status_t 571 radeon_gpu_gpio_setup() 572 { 573 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); 574 575 uint8 tableMajor; 576 uint8 tableMinor; 577 uint16 tableOffset; 578 uint16 tableSize; 579 580 if (atom_parse_data_header(gAtomContext, index, &tableSize, 581 &tableMajor, &tableMinor, &tableOffset) != B_OK) { 582 ERROR("%s: could't read GPIO_I2C_Info table from AtomBIOS index %d!\n", 583 __func__, index); 584 return B_ERROR; 585 } 586 587 struct _ATOM_GPIO_I2C_INFO *i2c_info 588 = (struct _ATOM_GPIO_I2C_INFO *)(gAtomContext->bios + tableOffset); 589 590 uint32 numIndices = (tableSize - sizeof(ATOM_COMMON_TABLE_HEADER)) 591 / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 592 593 if (numIndices > ATOM_MAX_SUPPORTED_DEVICE) { 594 ERROR("%s: ERROR: AtomBIOS contains more GPIO_Info items then I" 595 "was prepared for! (seen: %" B_PRIu32 "; max: %" B_PRIu32 ")\n", 596 __func__, numIndices, (uint32)ATOM_MAX_SUPPORTED_DEVICE); 597 return B_ERROR; 598 } 599 600 for (uint32 i = 0; i < numIndices; i++) { 601 ATOM_GPIO_I2C_ASSIGMENT *gpio = &i2c_info->asGPIO_Info[i]; 602 603 // TODO: if DCE 4 and i == 7 ... manual override for evergreen 604 // TODO: if DCE 3 and i == 4 ... manual override 605 606 // populate gpio information 607 gGPIOInfo[i]->hw_line 608 = gpio->sucI2cId.ucAccess; 609 gGPIOInfo[i]->hw_capable 610 = (gpio->sucI2cId.sbfAccess.bfHW_Capable) ? true : false; 611 612 // GPIO mask (Allows software to control the GPIO pad) 613 // 0 = chip access; 1 = only software; 614 gGPIOInfo[i]->mask_scl_reg 615 = B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) * 4; 616 gGPIOInfo[i]->mask_sda_reg 617 = B_LENDIAN_TO_HOST_INT16(gpio->usDataMaskRegisterIndex) * 4; 618 gGPIOInfo[i]->mask_scl_mask 619 = (1 << gpio->ucClkMaskShift); 620 gGPIOInfo[i]->mask_sda_mask 621 = (1 << gpio->ucDataMaskShift); 622 623 // GPIO output / write (A) enable 624 // 0 = GPIO input (Y); 1 = GPIO output (A); 625 gGPIOInfo[i]->en_scl_reg 626 = B_LENDIAN_TO_HOST_INT16(gpio->usClkEnRegisterIndex) * 4; 627 gGPIOInfo[i]->en_sda_reg 628 = B_LENDIAN_TO_HOST_INT16(gpio->usDataEnRegisterIndex) * 4; 629 gGPIOInfo[i]->en_scl_mask 630 = (1 << gpio->ucClkEnShift); 631 gGPIOInfo[i]->en_sda_mask 632 = (1 << gpio->ucDataEnShift); 633 634 // GPIO output / write (A) 635 gGPIOInfo[i]->a_scl_reg 636 = B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4; 637 gGPIOInfo[i]->a_sda_reg 638 = B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4; 639 gGPIOInfo[i]->a_scl_mask 640 = (1 << gpio->ucClkA_Shift); 641 gGPIOInfo[i]->a_sda_mask 642 = (1 << gpio->ucDataA_Shift); 643 644 // GPIO input / read (Y) 645 gGPIOInfo[i]->y_scl_reg 646 = B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4; 647 gGPIOInfo[i]->y_sda_reg 648 = B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4; 649 gGPIOInfo[i]->y_scl_mask 650 = (1 << gpio->ucClkY_Shift); 651 gGPIOInfo[i]->y_sda_mask 652 = (1 << gpio->ucDataY_Shift); 653 654 // ensure data is valid 655 gGPIOInfo[i]->valid = (gGPIOInfo[i]->mask_scl_reg) ? true : false; 656 657 TRACE("%s: GPIO @ %" B_PRIu32 ", valid: %s, hw_line: 0x%" B_PRIX32 "\n", 658 __func__, i, gGPIOInfo[i]->valid ? "true" : "false", 659 gGPIOInfo[i]->hw_line); 660 } 661 662 return B_OK; 663 } 664