1 /* 2 * Copyright 2011, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck IV, kallisti5@unixzen.com 7 */ 8 9 10 #include "bios.h" 11 12 #include <Debug.h> 13 14 #include "accelerant.h" 15 #include "accelerant_protos.h" 16 17 18 #undef TRACE 19 20 #define TRACE_ATOM 21 #ifdef TRACE_ATOM 22 # define TRACE(x...) _sPrintf("radeon_hd: " x) 23 #else 24 # define TRACE(x...) ; 25 #endif 26 27 28 atom_context* gAtomContext; 29 30 31 void 32 radeon_bios_init_scratch() 33 { 34 radeon_shared_info &info = *gInfo->shared_info; 35 36 uint32 biosScratch2; 37 uint32 biosScratch6; 38 39 if (info.chipsetID >= RADEON_R600) { 40 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2); 41 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6); 42 } else { 43 biosScratch2 = Read32(OUT, RADEON_BIOS_2_SCRATCH); 44 biosScratch6 = Read32(OUT, RADEON_BIOS_6_SCRATCH); 45 } 46 47 biosScratch2 |= ATOM_S2_VRI_BRIGHT_ENABLE; 48 // bios should not control backlight 49 biosScratch6 |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; 50 // bios shouldn't handle mode switching 51 52 if (info.chipsetID >= RADEON_R600) { 53 Write32(OUT, R600_SCRATCH_REG2, biosScratch2); 54 Write32(OUT, R600_SCRATCH_REG6, biosScratch6); 55 } else { 56 Write32(OUT, RADEON_BIOS_2_SCRATCH, biosScratch2); 57 Write32(OUT, RADEON_BIOS_6_SCRATCH, biosScratch6); 58 } 59 } 60 61 62 bool 63 radeon_bios_isposted() 64 { 65 // aka, is primary graphics card that POST loaded 66 67 radeon_shared_info &info = *gInfo->shared_info; 68 uint32 reg; 69 70 if (info.chipsetID == RADEON_PALM) { 71 // palms 72 reg = Read32(OUT, EVERGREEN_CRTC_CONTROL 73 + EVERGREEN_CRTC0_REGISTER_OFFSET) 74 | Read32(OUT, EVERGREEN_CRTC_CONTROL 75 + EVERGREEN_CRTC1_REGISTER_OFFSET); 76 if ((reg & EVERGREEN_CRTC_MASTER_EN) != 0) 77 return true; 78 } else if (info.chipsetID >= RADEON_CEDAR) { 79 // evergreen or higher 80 reg = Read32(OUT, EVERGREEN_CRTC_CONTROL 81 + EVERGREEN_CRTC0_REGISTER_OFFSET) 82 | Read32(OUT, EVERGREEN_CRTC_CONTROL 83 + EVERGREEN_CRTC1_REGISTER_OFFSET) 84 | Read32(OUT, EVERGREEN_CRTC_CONTROL 85 + EVERGREEN_CRTC2_REGISTER_OFFSET) 86 | Read32(OUT, EVERGREEN_CRTC_CONTROL 87 + EVERGREEN_CRTC3_REGISTER_OFFSET) 88 | Read32(OUT, EVERGREEN_CRTC_CONTROL 89 + EVERGREEN_CRTC4_REGISTER_OFFSET) 90 | Read32(OUT, EVERGREEN_CRTC_CONTROL 91 + EVERGREEN_CRTC5_REGISTER_OFFSET); 92 if ((reg & EVERGREEN_CRTC_MASTER_EN) != 0) 93 return true; 94 } else if (info.chipsetID >= RADEON_RS600) { 95 // avivio through r700 96 reg = Read32(OUT, AVIVO_D1CRTC_CONTROL) 97 | Read32(OUT, AVIVO_D2CRTC_CONTROL); 98 if ((reg & AVIVO_CRTC_EN) != 0) { 99 return true; 100 } 101 } else { 102 // early cards 103 reg = Read32(OUT, RADEON_CRTC_GEN_CNTL) 104 | Read32(OUT, RADEON_CRTC2_GEN_CNTL); 105 if ((reg & RADEON_CRTC_EN) != 0) 106 return true; 107 } 108 109 // also check memory size incase crt controlers are disabled 110 if (info.chipsetID >= RADEON_R600) 111 reg = Read32(OUT, R600_CONFIG_MEMSIZE); 112 else 113 reg = Read32(OUT, RADEON_CONFIG_MEMSIZE); 114 115 if (reg) 116 return true; 117 118 return false; 119 } 120 121 122 status_t 123 radeon_init_bios(uint8* bios) 124 { 125 radeon_shared_info &info = *gInfo->shared_info; 126 127 if (info.has_rom == false) { 128 TRACE("%s: called even though has_rom == false\n", __func__); 129 return B_ERROR; 130 } 131 132 #ifdef TRACE_ATOM 133 radeon_dump_bios(); 134 #endif 135 136 struct card_info* atom_card_info 137 = (card_info*)malloc(sizeof(card_info)); 138 139 if (!atom_card_info) 140 return B_NO_MEMORY; 141 142 atom_card_info->reg_read = Read32Cail; 143 atom_card_info->reg_write = Write32Cail; 144 145 // use MMIO instead of PCI I/O BAR 146 atom_card_info->ioreg_read = Read32Cail; 147 atom_card_info->ioreg_write = Write32Cail; 148 149 atom_card_info->mc_read = _read32; 150 atom_card_info->mc_write = _write32; 151 atom_card_info->pll_read = _read32; 152 atom_card_info->pll_write = _write32; 153 154 // Point AtomBIOS parser to card bios and malloc gAtomContext 155 gAtomContext = atom_parse(atom_card_info, bios); 156 157 if (gAtomContext == NULL) { 158 TRACE("%s: couldn't parse system AtomBIOS\n", __func__); 159 return B_ERROR; 160 } 161 162 if ((gAtomContext->exec_sem = create_sem(1, "AtomBIOS_exec")) 163 < B_NO_ERROR) { 164 TRACE("%s: couldn't create semaphore for AtomBIOS exec thread!\n", 165 __func__); 166 return B_ERROR; 167 } 168 169 radeon_bios_init_scratch(); 170 atom_allocate_fb_scratch(gAtomContext); 171 172 // post card atombios if needed 173 if (radeon_bios_isposted() == false) { 174 TRACE("%s: init AtomBIOS for this card as it is not not posted\n", 175 __func__); 176 // radeon_gpu_reset(); // <= r500 only? 177 atom_asic_init(gAtomContext); 178 } else { 179 TRACE("%s: AtomBIOS is already posted\n", 180 __func__); 181 } 182 183 return B_OK; 184 } 185 186 187 status_t 188 radeon_dump_bios() 189 { 190 // For debugging use, dump card AtomBIOS 191 radeon_shared_info &info = *gInfo->shared_info; 192 193 TRACE("%s: Dumping AtomBIOS as ATOM_DEBUG is set...\n", 194 __func__); 195 196 FILE* fp; 197 char filename[255]; 198 sprintf(filename, "/boot/system/cache/tmp/radeon_hd_bios_1002_%" B_PRIx32 199 "_%" B_PRIu32 ".bin", info.pciID, info.deviceIndex); 200 201 fp = fopen(filename, "wb"); 202 if (fp == NULL) { 203 TRACE("%s: Cannot create AtomBIOS blob at %s\n", __func__, filename); 204 return B_ERROR; 205 } 206 207 fwrite(gInfo->rom, info.rom_size, 1, fp); 208 209 fclose(fp); 210 211 TRACE("%s: AtomBIOS dumped to %s\n", __func__, filename); 212 213 return B_OK; 214 } 215