xref: /haiku/src/add-ons/accelerants/radeon_hd/gpu.cpp (revision 9f66f05b58e3a033984f1271ac986a2c99226103)
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