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