xref: /haiku/src/add-ons/accelerants/radeon_hd/bios.cpp (revision 82bfaa954dcfd90582fb2c1a0e918971eea57091)
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