/* * Copyright 2011, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Alexander von Gluck IV, kallisti5@unixzen.com */ #include "bios.h" #include #include "accelerant.h" #include "accelerant_protos.h" #undef TRACE #define TRACE_ATOM #ifdef TRACE_ATOM # define TRACE(x...) _sPrintf("radeon_hd: " x) #else # define TRACE(x...) ; #endif atom_context* gAtomContext; void radeon_bios_init_scratch() { radeon_shared_info &info = *gInfo->shared_info; uint32 biosScratch2; uint32 biosScratch6; if (info.chipsetID >= RADEON_R600) { biosScratch2 = Read32(OUT, R600_SCRATCH_REG2); biosScratch6 = Read32(OUT, R600_SCRATCH_REG6); } else { biosScratch2 = Read32(OUT, RADEON_BIOS_2_SCRATCH); biosScratch6 = Read32(OUT, RADEON_BIOS_6_SCRATCH); } biosScratch2 |= ATOM_S2_VRI_BRIGHT_ENABLE; // bios should not control backlight biosScratch6 |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; // bios shouldn't handle mode switching if (info.chipsetID >= RADEON_R600) { Write32(OUT, R600_SCRATCH_REG2, biosScratch2); Write32(OUT, R600_SCRATCH_REG6, biosScratch6); } else { Write32(OUT, RADEON_BIOS_2_SCRATCH, biosScratch2); Write32(OUT, RADEON_BIOS_6_SCRATCH, biosScratch6); } } bool radeon_bios_isposted() { // aka, is primary graphics card that POST loaded radeon_shared_info &info = *gInfo->shared_info; uint32 reg; if (info.chipsetID == RADEON_PALM) { // palms reg = Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); if ((reg & EVERGREEN_CRTC_MASTER_EN) != 0) return true; } else if (info.chipsetID >= RADEON_CEDAR) { // evergreen or higher reg = Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | Read32(OUT, EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); if ((reg & EVERGREEN_CRTC_MASTER_EN) != 0) return true; } else if (info.chipsetID >= RADEON_RS600) { // avivio through r700 reg = Read32(OUT, AVIVO_D1CRTC_CONTROL) | Read32(OUT, AVIVO_D2CRTC_CONTROL); if ((reg & AVIVO_CRTC_EN) != 0) { return true; } } else { // early cards reg = Read32(OUT, RADEON_CRTC_GEN_CNTL) | Read32(OUT, RADEON_CRTC2_GEN_CNTL); if ((reg & RADEON_CRTC_EN) != 0) return true; } // also check memory size incase crt controlers are disabled if (info.chipsetID >= RADEON_R600) reg = Read32(OUT, R600_CONFIG_MEMSIZE); else reg = Read32(OUT, RADEON_CONFIG_MEMSIZE); if (reg) return true; return false; } status_t radeon_init_bios(uint8* bios) { radeon_shared_info &info = *gInfo->shared_info; if (info.has_rom == false) { TRACE("%s: called even though has_rom == false\n", __func__); return B_ERROR; } #ifdef TRACE_ATOM radeon_dump_bios(); #endif struct card_info* atom_card_info = (card_info*)malloc(sizeof(card_info)); if (!atom_card_info) return B_NO_MEMORY; atom_card_info->reg_read = Read32Cail; atom_card_info->reg_write = Write32Cail; // use MMIO instead of PCI I/O BAR atom_card_info->ioreg_read = Read32Cail; atom_card_info->ioreg_write = Write32Cail; atom_card_info->mc_read = _read32; atom_card_info->mc_write = _write32; atom_card_info->pll_read = _read32; atom_card_info->pll_write = _write32; // Point AtomBIOS parser to card bios and malloc gAtomContext gAtomContext = atom_parse(atom_card_info, bios); if (gAtomContext == NULL) { TRACE("%s: couldn't parse system AtomBIOS\n", __func__); return B_ERROR; } if ((gAtomContext->exec_sem = create_sem(1, "AtomBIOS_exec")) < B_NO_ERROR) { TRACE("%s: couldn't create semaphore for AtomBIOS exec thread!\n", __func__); return B_ERROR; } radeon_bios_init_scratch(); atom_allocate_fb_scratch(gAtomContext); // post card atombios if needed if (radeon_bios_isposted() == false) { TRACE("%s: init AtomBIOS for this card as it is not not posted\n", __func__); // radeon_gpu_reset(); // <= r500 only? atom_asic_init(gAtomContext); } else { TRACE("%s: AtomBIOS is already posted\n", __func__); } return B_OK; } status_t radeon_dump_bios() { // For debugging use, dump card AtomBIOS radeon_shared_info &info = *gInfo->shared_info; TRACE("%s: Dumping AtomBIOS as ATOM_DEBUG is set...\n", __func__); FILE* fp; char filename[255]; sprintf(filename, "/boot/system/cache/tmp/radeon_hd_bios_1002_%" B_PRIx32 "_%" B_PRIu32 ".bin", info.pciID, info.deviceIndex); fp = fopen(filename, "wb"); if (fp == NULL) { TRACE("%s: Cannot create AtomBIOS blob at %s\n", __func__, filename); return B_ERROR; } fwrite(gInfo->rom, info.rom_size, 1, fp); fclose(fp); TRACE("%s: AtomBIOS dumped to %s\n", __func__, filename); return B_OK; }