xref: /haiku/src/add-ons/media/media-add-ons/radeon/Radeon.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /******************************************************************************
2 /
3 /	File:			Radeon.cpp
4 /
5 /	Description:	ATI Radeon Graphics Chip interface.
6 /
7 /	Copyright 2001, Carlos Hasan
8 /
9 *******************************************************************************/
10 
11 #include <unistd.h>
12 #include <dirent.h>
13 #include <Debug.h>
14 #include <string.h>
15 //#include "Driver.h"
16 #include "Radeon.h"
17 
18 static const char * const C_RADEON_REGISTER_AREA_NAME = "RadeonRegisters";
19 static const char * const C_RADEON_MEMORY_AREA_NAME = "RadeonMemory";
20 static const char * const C_RADEON_ROM_AREA_NAME = "RadeonROM";
21 
22 // CRadeonRect
23 CRadeonRect::CRadeonRect()
24 	:	fLeft(0),
25 		fTop(0),
26 		fRight(0),
27 		fBottom(0)
28 {
29 }
30 
31 CRadeonRect::CRadeonRect(int left, int top, int right, int bottom)
32 	:	fLeft(left),
33 		fTop(top),
34 		fRight(right),
35 		fBottom(bottom)
36 {
37 }
38 
39 int CRadeonRect::Left() const
40 {
41 	return fLeft;
42 }
43 
44 int CRadeonRect::Top() const
45 {
46 	return fTop;
47 }
48 
49 int CRadeonRect::Right() const
50 {
51 	return fRight;
52 }
53 
54 int CRadeonRect::Bottom() const
55 {
56 	return fBottom;
57 }
58 
59 int CRadeonRect::Width() const
60 {
61 	return fRight - fLeft + 1;
62 }
63 
64 int CRadeonRect::Height() const
65 {
66 	return fBottom - fTop + 1;
67 }
68 
69 void CRadeonRect::SetLeft(int value)
70 {
71 	fLeft = value;
72 }
73 
74 void CRadeonRect::SetTop(int value)
75 {
76 	fTop = value;
77 }
78 
79 void CRadeonRect::SetRight(int value)
80 {
81 	fRight = value;
82 }
83 
84 void CRadeonRect::SetBottom(int value)
85 {
86 	fBottom = value;
87 }
88 
89 void CRadeonRect::SetTo(int left, int top, int right, int bottom)
90 {
91 	fLeft = left;
92 	fTop = top;
93 	fRight = right;
94 	fBottom = bottom;
95 }
96 
97 void CRadeonRect::MoveTo(int left, int top)
98 {
99 	fRight += left - fLeft;
100 	fBottom += top - fTop;
101 	fLeft += left - fLeft;
102 	fTop += top - fTop;
103 }
104 
105 void CRadeonRect::ResizeTo(int width, int height)
106 {
107 	fRight = fLeft + width - 1;
108 	fBottom = fTop + height - 1;
109 }
110 
111 
112 // CRadeon
113 CRadeon::CRadeon( const char *dev_name )
114 	:	fHandle(0),
115 		fRegister(NULL),
116 		fROM(NULL),
117 		fVirtualCard(NULL),
118 		fSharedInfo(NULL),
119 		fRegisterArea(0),
120 		fROMArea(0),
121 		fVirtualCardArea(0),
122 		fSharedInfoArea(0)
123 {
124 	PRINT(("CRadeon::CRadeon()\n"));
125 
126 	if ((fHandle = open(dev_name, O_RDWR | O_CLOEXEC)) < 0) {
127 		PRINT(("CRadeon::CRadeon() - Can't open kernel driver\n"));
128 		return;
129 	}
130 
131 	radeon_get_private_data gpd;
132 
133 	if (GetDeviceInformation(gpd) < B_OK) {
134 		PRINT(("CRadeon::CRadeon() - Can't get device information\n"));
135 		return;
136 	}
137 
138 	CloneArea(
139 		"Radeon virtual card", gpd.virtual_card_area,
140 		&fVirtualCardArea, (void **)&fVirtualCard );
141 	CloneArea(
142 		"Radeon shared info", gpd.shared_info_area,
143 		&fSharedInfoArea, (void **)&fSharedInfo );
144 
145 	if( fSharedInfo != NULL )  {
146 		CloneArea(
147 			"Radeon regs", fSharedInfo->regs_area,
148 			&fRegisterArea, (void **)&fRegister );
149 		CloneArea(
150 			"Radeon ROM", fSharedInfo->ROM_area,
151 			&fROMArea, (void **)&fROM );
152 	}
153 
154 	if (fVirtualCard == NULL || fSharedInfo == NULL ||
155 		fROM == NULL || fRegister == NULL)
156 	{
157 		PRINT(("CRadeon::CRadeon() - Can't map memory apertures\n"));
158 		return;
159 	}
160 
161 	PRINT(("CRadeon::CRadeon() - ATI Radeon found\n"));
162 }
163 
164 CRadeon::~CRadeon()
165 {
166 	PRINT(("CRadeon::~CRadeon()\n"));
167 
168 	if( fVirtualCard != NULL )
169 		delete_area( fVirtualCardArea );
170 
171 	if( fSharedInfo != NULL )
172 		delete_area( fSharedInfoArea );
173 
174 	if (fRegister != NULL)
175 		delete_area( fRegisterArea );
176 
177 	if (fROM != NULL)
178 		delete_area( fROMArea );
179 
180 	if (fHandle >= 0)
181 		close(fHandle);
182 }
183 
184 status_t CRadeon::InitCheck() const
185 {
186 	return
187 		(fHandle >= 0 &&
188 		fRegister != NULL && fROM != NULL &&
189 		fVirtualCard != NULL && fSharedInfo != NULL) ? B_OK : B_ERROR;
190 }
191 
192 uint32 CRadeon::VirtualMemoryBase() const
193 {
194 	return fSharedInfo->memory[mt_local].virtual_addr_start;
195 }
196 
197 int CRadeon::Register(radeon_register index) const
198 {
199 	return fRegister[index >> 2];
200 }
201 
202 void CRadeon::SetRegister(radeon_register index, int value)
203 {
204 	fRegister[index >> 2] = value;
205 }
206 
207 int CRadeon::Register(radeon_register index, int mask) const
208 {
209 	return fRegister[index >> 2] & mask;
210 }
211 
212 void CRadeon::SetRegister(radeon_register index, int mask, int value)
213 {
214 #ifdef DEBUG
215 	if ((value & ~mask) != 0)
216 		PRINT(("CRadeon::SetRegister(0x%04x, 0x%08x, 0x%08x)\n", index, mask, value));
217 #endif
218 
219 	fRegister[index >> 2] = (fRegister[index >> 2] & ~mask) | (value & mask);
220 }
221 
222 int CRadeon::VIPRegister(int device, int address)
223 {
224 	radeon_vip_read vr;
225 	status_t res;
226 
227 	vr.magic = RADEON_PRIVATE_DATA_MAGIC;
228 	vr.channel = device;
229 	vr.address = address;
230 
231 	res = ioctl( fHandle, RADEON_VIPREAD, &vr, sizeof( vr ));
232 
233 	if( res == B_OK )
234 		return vr.data;
235 	else
236 		return -1;
237 }
238 
239 void CRadeon::SetVIPRegister(int device, int address, int value)
240 {
241 	radeon_vip_write vw;
242 
243 	vw.magic = RADEON_PRIVATE_DATA_MAGIC;
244 	vw.channel = device;
245 	vw.address = address;
246 	vw.data = value;
247 
248 	ioctl( fHandle, RADEON_VIPWRITE, &vw, sizeof( vw ));
249 }
250 
251 int CRadeon::FindVIPDevice( uint32 device_id )
252 {
253 	radeon_find_vip_device fvd;
254 	status_t res;
255 
256 	fvd.magic = RADEON_PRIVATE_DATA_MAGIC;
257 	fvd.device_id = device_id;
258 
259 	res = ioctl( fHandle, RADEON_FINDVIPDEVICE, &fvd, sizeof( fvd ));
260 
261 	if( res == B_OK )
262 		return fvd.channel;
263 	else
264 		return -1;
265 }
266 
267 void CRadeon::GetPLLParameters(int & refFreq, int & refDiv, int & minFreq, int & maxFreq, int & xclock)
268 {
269 	refFreq = fSharedInfo->pll.ref_freq;
270 	refDiv = fSharedInfo->pll.ref_div;
271 	minFreq = fSharedInfo->pll.min_pll_freq;
272 	maxFreq = fSharedInfo->pll.max_pll_freq;
273 	xclock = fSharedInfo->pll.xclk;
274 }
275 
276 void CRadeon::GetMMParameters(radeon_video_tuner & tuner,
277 							  radeon_video_decoder & video,
278 							  radeon_video_clock & clock,
279 							  int & tunerPort,
280 							  int & compositePort,
281 							  int & svideoPort)
282 {
283 	unsigned char *fVideoBIOS = fROM + fROM[0x48] + (fROM[0x49] << 8);
284 	unsigned char * fMMTable = fROM + fVideoBIOS[0x38] + (fVideoBIOS[0x39] << 8);
285 
286 	switch (fMMTable[0] & 0x1f) {
287 	case 0x00:
288 		tuner = C_RADEON_NO_TUNER;
289 		break;
290 	case 0x01:
291 		tuner = C_RADEON_FI1236_MK1_NTSC;
292 		break;
293 	case 0x02:
294 		tuner = C_RADEON_FI1236_MK2_NTSC_JAPAN;
295 		break;
296 	case 0x03:
297 		tuner = C_RADEON_FI1216_MK2_PAL_BG;
298 		break;
299 	case 0x04:
300 		tuner = C_RADEON_FI1246_MK2_PAL_I;
301 		break;
302 	case 0x05:
303 		tuner = C_RADEON_FI1216_MF_MK2_PAL_BG_SECAM_L;
304 		break;
305 	case 0x06:
306 		tuner = C_RADEON_FI1236_MK2_NTSC;
307 		break;
308 	case 0x07:
309 		tuner = C_RADEON_FI1256_MK2_SECAM_DK;
310 		break;
311 	case 0x08:
312 		tuner = C_RADEON_FI1236_MK2_NTSC;
313 		break;
314 	case 0x09:
315 		tuner = C_RADEON_FI1216_MK2_PAL_BG;
316 		break;
317 	case 0x0a:
318 		tuner = C_RADEON_FI1246_MK2_PAL_I;
319 		break;
320 	case 0x0b:
321 		tuner = C_RADEON_FI1216_MK2_PAL_BG_SECAM_L;
322 		break;
323 	case 0x0c:
324 		tuner = C_RADEON_FI1236_MK2_NTSC;
325 		break;
326 	case 0x0d:
327 		tuner = C_RADEON_TEMIC_FN5AL_PAL_IBGDK_SECAM_DK;
328 		break;
329 	default:
330 		tuner = C_RADEON_NO_TUNER;
331 		break;
332 	}
333 
334 	switch (fMMTable[5] & 0x0f) {
335 	case 0x00:
336 		video = C_RADEON_NO_VIDEO;
337 		break;
338 	case 0x01:
339 		video = C_RADEON_BT819;
340 		break;
341 	case 0x02:
342 		video = C_RADEON_BT829;
343 		break;
344 	case 0x03:
345 		video = C_RADEON_BT829A;
346 		break;
347 	case 0x04:
348 		video = C_RADEON_SA7111;
349 		break;
350 	case 0x05:
351 		video = C_RADEON_SA7112;
352 		break;
353 	case 0x06:
354 		video = C_RADEON_RAGE_THEATER;
355 		break;
356 	default:
357 		video = C_RADEON_NO_VIDEO;
358 		break;
359 	}
360 
361 	switch (fMMTable[5] & 0xf0) {
362 	case 0x00:
363 	case 0x10:
364 	case 0x20:
365 	case 0x30:
366 		clock = C_RADEON_NO_VIDEO_CLOCK;
367 		break;
368 	case 0x40:
369 		clock = C_RADEON_VIDEO_CLOCK_28_63636_MHZ;
370 		break;
371 	case 0x50:
372 		clock = C_RADEON_VIDEO_CLOCK_29_49892_MHZ;
373 		break;
374 	case 0x60:
375 		clock = C_RADEON_VIDEO_CLOCK_27_00000_MHZ;
376 		break;
377 	case 0x70:
378 		clock = C_RADEON_VIDEO_CLOCK_14_31818_MHZ;
379 		break;
380 	default:
381 		clock = C_RADEON_NO_VIDEO_CLOCK;
382 		break;
383 	}
384 
385 	for (int port = 0; port < 4; port++) {
386 		switch (fMMTable[7 + port] & 0x03) {
387 		case 0x00:
388 			// Unused or Invalid
389 			break;
390 		case 0x01:
391 			// Tuner Input
392 			tunerPort = 0;
393 			break;
394 		case 0x02:
395 			// Front/Rear Composite Input
396 			compositePort = (fMMTable[7 + port] & 0x04 ? 2 : 1);
397 			break;
398 		case 0x03:
399 			// Front/Rear SVideo Input
400 			svideoPort = (fMMTable[7 + port] & 0x04 ? 6 : 5);
401 			break;
402 		}
403 	}
404 }
405 
406 status_t CRadeon::AllocateGraphicsMemory(
407 	memory_type_e memory_type, int32 size,
408 	int32 *offset, int32 *handle )
409 {
410 	radeon_alloc_mem am;
411 	status_t res;
412 
413 	am.magic = RADEON_PRIVATE_DATA_MAGIC;
414 	am.size = size;
415 	am.memory_type = mt_local;
416 	am.global = false;
417 
418 	res = ioctl( fHandle, RADEON_ALLOC_MEM, &am );
419 
420 	if( res != B_OK )
421 		return res;
422 
423 	*handle = am.handle;
424 	*offset = am.offset;
425 	return B_OK;
426 }
427 
428 void CRadeon::FreeGraphicsMemory(
429 	memory_type_e memory_type, int32 handle )
430 {
431 	radeon_free_mem fm;
432 
433 	fm.magic = RADEON_PRIVATE_DATA_MAGIC;
434 	fm.memory_type = memory_type;
435 	fm.global = false;
436 	fm.handle = handle;
437 
438 	ioctl( fHandle, RADEON_FREE_MEM, &fm );
439 }
440 
441 status_t CRadeon::DMACopy(
442 	uint32 src, void *target, size_t size, bool lock_mem, bool contiguous )
443 {
444 	radeon_dma_copy dc;
445 
446 	dc.magic = RADEON_PRIVATE_DATA_MAGIC;
447 	dc.src = src;
448 	dc.target = target;
449 	dc.size = size;
450 	dc.lock_mem = lock_mem;
451 	dc.contiguous = contiguous;
452 
453 	return ioctl( fHandle, RADEON_DMACOPY, &dc );
454 }
455 
456 status_t CRadeon::GetDeviceInformation(radeon_get_private_data & info)
457 {
458 	info.magic = RADEON_PRIVATE_DATA_MAGIC;
459 
460 	return ioctl( fHandle, RADEON_GET_PRIVATE_DATA, &info, sizeof( info ));
461 }
462 
463 status_t CRadeon::CloneArea(const char * name, area_id src_area,
464 	area_id *cloned_area, void ** map)
465 {
466 	int res = clone_area( name, map, B_ANY_ADDRESS,
467 		B_READ_AREA | B_WRITE_AREA, src_area );
468 
469 	if( res < 0 ) {
470 		return res;
471 	} else {
472 		*cloned_area = res;
473 		return B_OK;
474 	}
475 }
476 
477 status_t CRadeon::WaitInterrupt(int * mask, int * sequence, bigtime_t * time, bigtime_t timeout)
478 {
479 	radeon_wait_for_cap_irq wvc;
480 	status_t status;
481 
482 	wvc.magic = RADEON_PRIVATE_DATA_MAGIC;
483 	wvc.timeout = timeout;
484 
485 	status = ioctl( fHandle, RADEON_WAIT_FOR_CAP_IRQ, &wvc );
486 
487 	if( status == B_OK ) {
488 		*mask = wvc.int_status;
489 		*sequence = wvc.counter;
490 		*time = wvc.timestamp;
491 	}
492 
493 	return status;
494 }
495 
496 #if 0
497 void CRadeon::PrintToStream()
498 {
499 	// ATI ROM Signature
500 	if (ROM(0) == 0x55 && ROM(1) == 0xAA) {
501 		for (int offset = 0; offset < 128 - 9; offset++) {
502 			if (ROM(offset + 0) == '7' &&
503 				ROM(offset + 1) == '6' &&
504 				ROM(offset + 2) == '1' &&
505 				ROM(offset + 3) == '2' &&
506 				ROM(offset + 4) == '9' &&
507 				ROM(offset + 5) == '5' &&
508 				ROM(offset + 6) == '5' &&
509 				ROM(offset + 7) == '2' &&
510 				ROM(offset + 8) == '0')
511 				break;
512 		}
513 	}
514 
515 	// Video BIOS
516 	unsigned char *fVideoBIOS = fROM + fROM[0x48] + (fROM[0x49] << 8);
517 
518 	PRINT((
519 		"----------------------------------------------------------------------\n"
520         "ATI RADEON VIDEO BIOS\n"
521         "\n"
522         "BIOS Revision: %03d.%03d.%03d%03d.%s\n"
523         "PCI Bus/Device/Function Code: 0x%04x\n"
524         "BIOS Runtime Segment Address: 0x%04x\n"
525         "I/O Base Address: 0x%04x\n"
526         "Subsystem Vendor ID: 0x%04x\n"
527         "Subsystem ID: 0x%04x\n"
528         "Post Vendor ID: 0x%04x\n"
529         "\n",
530 
531         // OEM Revision (ID1.ID2.REVISION.CONFIG_FILE)
532         fVideoBIOS[2], fVideoBIOS[3],
533         fVideoBIOS[4], fVideoBIOS[5],
534         fROM + fVideoBIOS[0x10] + (fVideoBIOS[0x11] << 8),
535 
536         // PCI bus, device, function code
537         fVideoBIOS[0x16] + (fVideoBIOS[0x17] << 8),
538 
539         // ROM BIOS segment
540         fVideoBIOS[0x18] + (fVideoBIOS[0x19] << 8),
541 
542         // I/O base address
543         fVideoBIOS[0x1a] + (fVideoBIOS[0x1b] << 8),
544 
545         // Subsystem Vendor ID, Subsystem ID, Post Vendor ID
546         fVideoBIOS[0x1c] + (fVideoBIOS[0x1d] << 8),
547         fVideoBIOS[0x1e] + (fVideoBIOS[0x1f] << 8),
548         fVideoBIOS[0x20] + (fVideoBIOS[0x21] << 8)
549     ));
550 
551 
552 	// PLL Information
553 	unsigned char *fPLL = fROM + fVideoBIOS[0x30] + (fVideoBIOS[0x31] << 8);
554 
555 	PRINT((
556 		"----------------------------------------------------------------------\n"
557         "ATI RADEON PLL INFORMATION TABLE\n"
558         "\n"
559         "External Clock: %g MHz\n"
560         "Reference Frequency: %g MHz\n"
561         "Reference Divisor: %d\n"
562         "Min PLL Frequency: %g MHz\n"
563         "Max PLL Frequency: %g MHz\n"
564         "\n",
565 		(fPLL[0x08] + (fPLL[0x09] << 8)) / 1000.0,
566 		(fPLL[0x0e] + (fPLL[0x0f] << 8)) / 100.0,
567 		fPLL[0x10] + (fPLL[0x11] << 8),
568 		(fPLL[0x12] + (fPLL[0x13] << 8) + (fPLL[0x14] << 16) + (fPLL[0x15] << 24)) / 1000.0,
569 		(fPLL[0x12] + (fPLL[0x16] << 8) + (fPLL[0x17] << 16) + (fPLL[0x18] << 24)) / 1000.0));
570 
571 
572 	// TV Table
573 	unsigned char * fTVTable = fROM + fVideoBIOS[0x32] + (fVideoBIOS[0x33] << 8);
574 
575 	PRINT((
576 		"----------------------------------------------------------------------\n"
577         "ATI RADEON TV INFORMATION TABLE\n"
578         "\n"
579         "Table Signature: %c%c%c\n"
580         "Table Version: %d\n"
581         "Table Size: %d bytes\n"
582         "\n"
583         "TVOut Support: %s\n"
584         "BIOS built-in TV standard: %s\n"
585         "TVOut information: %s, %s MHz\n"
586         "\n"
587         "Run time supported TV standard:%s%s%s%s%s%s\n"
588         "Initialization time supported TV standard:%s%s%s%s%s%s\n"
589         "\n",
590 
591         // Table signature, version and size
592         fTVTable[0x00],fTVTable[0x01], fTVTable[0x02],
593         fTVTable[0x03],
594         fTVTable[0x04] + ((int) fTVTable[0x05] << 8),
595 
596         // TVOut support
597         fTVTable[0x06] == 'N' ? "TVOut chip not found" : "TVOut chip on board",
598 
599         // BIOS built-in initialization TV standard
600         (fTVTable[0x07] & 0x0f) == 0x01 ? "NTSC" :
601         (fTVTable[0x07] & 0x0f) == 0x02 ? "PAL" :
602         (fTVTable[0x07] & 0x0f) == 0x03 ? "PAL-M" :
603         (fTVTable[0x07] & 0x0f) == 0x04 ? "PAL-60" :
604         (fTVTable[0x07] & 0x0f) == 0x05 ? "NTSC-J" :
605         (fTVTable[0x07] & 0x0f) == 0x06 ? "SCART-PAL" : "Reserved",
606 
607         // TV Out information
608         (fTVTable[0x09] & 0x03) == 0x00 ? "Invalid" :
609         (fTVTable[0x09] & 0x03) == 0x01 ? "TV off, CRT on" :
610         (fTVTable[0x09] & 0x03) == 0x02 ? "TV on, CRT off" : "TV on, CRT on",
611 
612         (fTVTable[0x09] & 0x0c) == 0x00 ? "29.498928713" :
613         (fTVTable[0x09] & 0x0c) == 0x04 ? "28.63636" :
614         (fTVTable[0x09] & 0x0c) == 0x08 ? "14.31818" : "27.0",
615 
616         // Runtime supported TV standard
617         (fTVTable[0x0a] & 0x01) != 0 ? " NTSC" : "",
618         (fTVTable[0x0a] & 0x02) != 0 ? " PAL" : "",
619         (fTVTable[0x0a] & 0x04) != 0 ? " PAL-M" : "",
620         (fTVTable[0x0a] & 0x08) != 0 ? " PAL-60" : "",
621         (fTVTable[0x0a] & 0x10) != 0 ? " NTSC-J" : "",
622         (fTVTable[0x0a] & 0x20) != 0 ? " SCART-PAL" : "",
623 
624         // Initialization time supported TV standard
625         (fTVTable[0x0b] & 0x01) != 0 ? " NTSC" : "",
626         (fTVTable[0x0b] & 0x02) != 0 ? " PAL" : "",
627         (fTVTable[0x0b] & 0x04) != 0 ? " PAL-M" : "",
628         (fTVTable[0x0b] & 0x08) != 0 ? " PAL-60" : "",
629         (fTVTable[0x0b] & 0x10) != 0 ? " NTSC-J" : "",
630         (fTVTable[0x0b] & 0x20) != 0 ? " SCART-PAL" : ""
631     ));
632 
633     // Hardware Configuration Table
634     unsigned char * fHWTable = fROM + fVideoBIOS[0x36] + (fVideoBIOS[0x37] << 8);
635 
636 	PRINT((
637 		"----------------------------------------------------------------------\n"
638         "ATI RADEON HARDWARE CONFIGURATION TABLE\n"
639         "\n"
640         "Table Signature: %c%c%c%c\n"
641         "Table Revision: %d\n"
642         "Table Size: %d\n"
643         "\n"
644         "I2C Type: %s\n"
645         "TVOut Support: %s\n"
646         "Video Out Crystal: %s\n"
647         "ImpactTV Data Port: %s\n"
648         "\n"
649         "Video Port Capability:\n"
650         "   AMC/DVS0 Video Port: %s\n"
651         "   Zoom Video Port: %s\n"
652         "   AMC/DVS1 Video Port: %s\n"
653         "   VIP 16-bit Video Port: %s\n"
654         "\n"
655         "Host Port Configuration: %s\n"
656         "\n",
657 
658         // Table Signature, Revision, Size
659         fHWTable[0x00], fHWTable[0x01], fHWTable[0x02], fHWTable[0x03],
660         fHWTable[0x04], fHWTable[0x05],
661 
662         // I2C type
663         (fHWTable[0x06] & 0x0f) == 0x00 ? "Normal GP I/O (data=GP_IO2, clock=GP_IO1)" :
664         (fHWTable[0x06] & 0x0f) == 0x01 ? "ImpacTV GP I/O" :
665         (fHWTable[0x06] & 0x0f) == 0x02 ? "Dedicated I2C Pin" :
666         (fHWTable[0x06] & 0x0f) == 0x03 ? "GP I/O (data=GP_IO12, clock=GP_IO13)" :
667         (fHWTable[0x06] & 0x0f) == 0x04 ? "GP I/O (data=GPIO12, clock=GPIO10)" :
668         (fHWTable[0x06] & 0x0f) == 0x05 ? "RAGE THEATER I2C Master" :
669         (fHWTable[0x06] & 0x0f) == 0x06 ? "Rage128 MPP2 Pin" :
670         (fHWTable[0x06] & 0x0f) == 0x0f ? "No I2C Configuration" : "Reserved",
671 
672         // TVOut support
673         (fHWTable[0x07] & 0x0f) == 0x00 ? "No TVOut supported" :
674         (fHWTable[0x07] & 0x0f) == 0x01 ? "ImpactTV1 supported" :
675         (fHWTable[0x07] & 0x0f) == 0x02 ? "ImpactTV2 supported" :
676         (fHWTable[0x07] & 0x0f) == 0x03 ? "Improved ImpactTV2 supported" :
677         (fHWTable[0x07] & 0x0f) == 0x04 ? "RAGE THEATER supported" : "Reserved",
678 
679         // Video Out Crystal
680         (fHWTable[0x07] & 0x70) == 0x00 ? "TVOut not installed" :
681         (fHWTable[0x07] & 0x70) == 0x10 ? "28.63636 MHz" :
682         (fHWTable[0x07] & 0x70) == 0x20 ? "29.49892713 MHz" :
683         (fHWTable[0x07] & 0x70) == 0x30 ? "27.0 MHz" :
684         (fHWTable[0x07] & 0x70) == 0x40 ? "14.31818 MHz" : "Reserved",
685 
686         // ImpactTV data port
687         (fHWTable[0x07] & 0x80) == 0x00 ? "MPP1" : "MPP2",
688 
689         // Video Port Capability
690         (fHWTable[0x08] & 0x01) == 0x00 ? "Not Supported" : "Supported",
691         (fHWTable[0x08] & 0x02) == 0x00 ? "Not Supported" : "Supported",
692         (fHWTable[0x08] & 0x04) == 0x00 ? "Not Supported" : "Supported",
693         (fHWTable[0x08] & 0x08) == 0x00 ? "Not Supported" : "Supported",
694 
695         // Host Port Configuration
696         (fHWTable[0x09] & 0x0f) == 0x00 ? "No Host Port" :
697         (fHWTable[0x09] & 0x0f) == 0x01 ? "MPP Host Port" :
698         (fHWTable[0x09] & 0x0f) == 0x02 ? "2 bit VIP Host Port" :
699         (fHWTable[0x09] & 0x0f) == 0x03 ? "4 bit VIP Host Port" :
700         (fHWTable[0x09] & 0x0f) == 0x04 ? "8 bit VIP Host Port" : "Reserved"
701     ));
702 
703 	// Multimedia Table
704 	unsigned char * fMMTable = fROM + fVideoBIOS[0x38] + (fVideoBIOS[0x39] << 8);
705 
706     PRINT((
707     	"----------------------------------------------------------------------\n"
708         "ATI RADEON MULTIMEDIA TABLE\n"
709         "\n"
710         "Table Revision: %d\n"
711         "Table Size: %d bytes\n"
712         "\n"
713         "Tuner Chip: %s\n"
714         "Tuner Input: %s\n"
715         "Tuner Voltage Regulator: %s\n"
716         "\n"
717         "Audio Chip: %s\n"
718         "FM Audio Decoder: %s\n"
719         "Audio Scrambling: %s\n"
720         "\n"
721         "Product Type: %s, Revision %d\n"
722         "Product ID: %s\n"
723         "\n"
724         "I2S Input Configuration: %s\n"
725         "I2S Output Configuration: %s\n"
726         "I2S Audio Chip: %s\n"
727         "S/PDIF Output Configuration: %s\n"
728         "\n"
729         "Video Decoder: %s\n"
730         "Video Standard/Crystal: %s\n"
731         "Video Decoder Host Config: %s\n"
732         "Hardware Teletext: %s\n"
733         "\n"
734         "Video Input:\n"
735         "    0: %s, %s (ID %d)\n"
736         "    1: %s, %s (ID %d)\n"
737         "    2: %s, %s (ID %d)\n"
738         "    3: %s, %s (ID %d)\n"
739         "    4: %s, %s (ID %d)\n"
740         "\n",
741 
742         /* Hardware Table */
743         fMMTable[-2], fMMTable[-1],
744 
745         /* Tuner Type */
746         (fMMTable[0] & 0x1f) == 0x00 ? "No Tuner" :
747         (fMMTable[0] & 0x1f) == 0x01 ? "Philips FI1236 MK1 NTSC M/N North America" :
748         (fMMTable[0] & 0x1f) == 0x02 ? "Philips FI1236 MK2 NTSC M/N Japan" :
749 
750         (fMMTable[0] & 0x1f) == 0x03 ? "Philips FI1216 MK2 PAL B/G" :
751         (fMMTable[0] & 0x1f) == 0x04 ? "Philips FI1246 MK2 PAL I" :
752         (fMMTable[0] & 0x1f) == 0x05 ? "Philips FI1216 MF MK2 PAL B/G, SECAM L/L'" :
753         (fMMTable[0] & 0x1f) == 0x06 ? "Philips FI1236 MK2 NTSC M/N North America" :
754         (fMMTable[0] & 0x1f) == 0x07 ? "Philips FI1256 MK2 SECAM D/K" :
755         (fMMTable[0] & 0x1f) == 0x08 ? "Philips FM1236 MK2 NTSC M/N North America" :
756 
757         (fMMTable[0] & 0x1f) == 0x09 ? "Philips FI1216 MK2 PAL B/G - External Tuner POD" :
758         (fMMTable[0] & 0x1f) == 0x0a ? "Philips FI1246 MK2 PAL I - External Tuner POD" :
759         (fMMTable[0] & 0x1f) == 0x0b ? "Philips FI1216 MF MK2 PAL B/G, SECAM L/L' - External Tuner POD" :
760         (fMMTable[0] & 0x1f) == 0x0c ? "Philips FI1236 MK2 NTSC M/N North America - External Tuner POD" :
761 
762         (fMMTable[0] & 0x1f) == 0x0d ? "Temic FN5AL RF3X7595 PAL I/B/G/DK & SECAM DK" :
763         (fMMTable[0] & 0x1f) == 0x10 ? "Alps TSBH5 NTSC M/N North America" :
764         (fMMTable[0] & 0x1f) == 0x11 ? "Alps TSC?? NTSC M/N North America" :
765         (fMMTable[0] & 0x1f) == 0x12 ? "Alps TSCH5 NTSC M/N North America" :
766 
767         (fMMTable[0] & 0x1f) == 0x1f ? "Unknown Tuner Type" : "Reserved",
768 
769         /* Video Input for Tuner */
770         (fMMTable[0] & 0xe0) == 0x00 ? "Video Input 0" :
771         (fMMTable[0] & 0xe0) == 0x20 ? "Video Input 1" :
772         (fMMTable[0] & 0xe0) == 0x40 ? "Video Input 2" :
773         (fMMTable[0] & 0xe0) == 0x60 ? "Video Input 3" :
774         (fMMTable[0] & 0xe0) == 0x80 ? "Video Input 4" : "Reserved",
775 
776         /* Tuner Voltage */
777         (fMMTable[3] & 0x03) == 0x00 ? "No Tuner Power down feature" :
778         (fMMTable[3] & 0x03) == 0x01 ? "Tuner Power down feature" : "Reserved",
779 
780         /* Audio Chip Type */
781         (fMMTable[1] & 0x0f) == 0x00 ? "Philips TEA5582 NTSC Stereo, no dbx, no volume" :
782         (fMMTable[1] & 0x0f) == 0x01 ? "Mono with audio mux" :
783         (fMMTable[1] & 0x0f) == 0x02 ? "Philips TDA9850 NTSC N.A. Stereo, dbx, mux, no volume" :
784         (fMMTable[1] & 0x0f) == 0x03 ? "Sony CXA2020S Japan NTSC Stereo, mux, no volume" :
785         (fMMTable[1] & 0x0f) == 0x04 ? "ITT MSP3410D Europe Stereo, volume, internal mux" :
786         (fMMTable[1] & 0x0f) == 0x05 ? "Crystal CS4236B" :
787         (fMMTable[1] & 0x0f) == 0x06 ? "Philips TDA9851 NTSC Stereo, volume, no dbx, no mux" :
788         (fMMTable[1] & 0x0f) == 0x07 ? "ITT MSP3415 (Europe)" :
789         (fMMTable[1] & 0x0f) == 0x08 ? "ITT MSP3430 (N.A.)" :
790         (fMMTable[1] & 0x0f) == 0x0f ? "No Audio Chip Installed" : "Reserved",
791 
792         /* FM Audio Decoder */
793         (fMMTable[3] & 0x30) == 0x00 ? "No FM Audio Decoder" :
794         (fMMTable[3] & 0x30) == 0x10 ? "FM Audio Decoder (Rohm BA1332F)" : "Reserved",
795 
796         /* Audio Scrambling */
797         (fMMTable[3] & 0x80) == 0x00 ? "Not Supported" : "Supported",
798 
799         /* Product Type */
800         (fMMTable[1] & 0x10) == 0x00 ? "OEM Product" : "ATI Product",
801 
802         /* OEM Revision */
803         (fMMTable[1] & 0xe0) >> 5,
804 
805         /* Product ID */
806         (fMMTable[1] & 0x10) == 0x00 ? "<OEM ID>" :
807         (
808             fMMTable[2] == 0x00 ? "ATI Prototype Board" :
809             fMMTable[2] == 0x01 ? "ATI All in Wonder" :
810             fMMTable[2] == 0x02 ? "ATI All in Wonder Pro, no MPEG/DVD decoder" :
811             fMMTable[2] == 0x03 ? "ATI All in Wonder Pro, CD11 or similar MPEG/DVD decoder on MPP" :
812             fMMTable[2] == 0x04 ? "ATI All in Wonder Plus" :
813             fMMTable[2] == 0x05 ? "ATI Kitchener Board" :
814             fMMTable[2] == 0x06 ? "ATI Toronto Board (analog audio)" :
815             fMMTable[2] == 0x07 ? "ATI TV-Wonder" :
816             fMMTable[2] == 0x08 ? "ATI Victoria Board (Rage XL plus RAGE THEATER)" : "Reserved"
817         ),
818 
819         /* I2S Input/Output Configuration */
820         (fMMTable[4] & 0x01) == 0x00 ? "Not Supported" : "Supported",
821         (fMMTable[4] & 0x02) == 0x00 ? "Not Supported" : "Supported",
822 
823         /* I2S Audio Chip */
824         (fMMTable[4] & 0x1c) == 0x00 ? "TDA1309_32Strap" :
825         (fMMTable[4] & 0x1c) == 0x04 ? "TDA1309_64Strap" :
826         (fMMTable[4] & 0x1c) == 0x08 ? "ITT MSP3430" :
827         (fMMTable[4] & 0x1c) == 0x0c ? "ITT MSP3415" : "Reserved",
828 
829         /* S/PDIF Output Config */
830         (fMMTable[4] & 0x20) == 0x00 ? "Not Supported" : "Supported",
831 
832         /* Video Decoder Type */
833         (fMMTable[5] & 0x0f) == 0x00 ? "No Video Decoder" :
834         (fMMTable[5] & 0x0f) == 0x01 ? "Bt819" :
835         (fMMTable[5] & 0x0f) == 0x02 ? "Bt829" :
836         (fMMTable[5] & 0x0f) == 0x03 ? "Bt829A" :
837         (fMMTable[5] & 0x0f) == 0x04 ? "Philips SA7111" :
838         (fMMTable[5] & 0x0f) == 0x05 ? "Philips SA7112 or SA7112A" :
839         (fMMTable[5] & 0x0f) == 0x06 ? "RAGE THEATER" : "Reserved",
840 
841         /* Video-In Standard/Crystal */
842         (fMMTable[5] & 0xf0) == 0x00 ? "NTSC and PAL Crystals installed" :
843         (fMMTable[5] & 0xf0) == 0x10 ? "NTSC Crystal only" :
844         (fMMTable[5] & 0xf0) == 0x20 ? "PAL Crystal only" :
845         (fMMTable[5] & 0xf0) == 0x30 ? "NTSC, PAL, SECAM Ssingle crystal for Bt829 and Bt879" :
846         (fMMTable[5] & 0xf0) == 0x40 ? "28.63636 MHz Crystal" :
847         (fMMTable[5] & 0xf0) == 0x50 ? "29.49892713 MHz Crystal" :
848         (fMMTable[5] & 0xf0) == 0x60 ? "27.0 MHz Crystal" :
849         (fMMTable[5] & 0xf0) == 0x70 ? "14.31818 MHz Crystal" : "Reserved",
850 
851         /* Video Decoder Host Config */
852         (fMMTable[6] & 0x07) == 0x00 ? "I2C Device" :
853         (fMMTable[6] & 0x07) == 0x01 ? "MPP Device" :
854         (fMMTable[6] & 0x07) == 0x02 ? "2 bits VIP Device" :
855         (fMMTable[6] & 0x07) == 0x03 ? "4 bits VIP Device" :
856         (fMMTable[6] & 0x07) == 0x04 ? "8 bits VIP Device" :
857         (fMMTable[6] & 0x07) == 0x07 ? "PCI Device" : "Reserved",
858 
859         /* Hardware Teletext */
860         (fMMTable[3] & 0x0c) == 0x00 ? "No Hardware Teletext" :
861         (fMMTable[3] & 0x0c) == 0x04 ? "Philips SAA5281" : "Reserved",
862 
863         /* Video Input 0 */
864         (fMMTable[7] & 0x03) == 0x00 ? "Unused/Invalid" :
865         (fMMTable[7] & 0x03) == 0x01 ? "Tuner Input" :
866         (fMMTable[7] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
867         (fMMTable[7] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
868         (fMMTable[7] & 0x38) >> 3,
869 
870         /* Video Input 1 */
871         (fMMTable[8] & 0x03) == 0x00 ? "Unused/Invalid" :
872         (fMMTable[8] & 0x03) == 0x01 ? "Tuner Input" :
873         (fMMTable[8] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
874         (fMMTable[8] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
875         (fMMTable[8] & 0x38) >> 3,
876 
877         /* Video Input 2 */
878         (fMMTable[9] & 0x03) == 0x00 ? "Unused/Invalid" :
879         (fMMTable[9] & 0x03) == 0x01 ? "Tuner Input" :
880         (fMMTable[9] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
881         (fMMTable[9] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
882         (fMMTable[9] & 0x38) >> 3,
883 
884         /* Video Input 3 */
885         (fMMTable[10] & 0x03) == 0x00 ? "Unused/Invalid" :
886         (fMMTable[10] & 0x03) == 0x01 ? "Tuner Input" :
887         (fMMTable[10] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
888         (fMMTable[10] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
889         (fMMTable[10] & 0x38) >> 3,
890 
891         /* Video Input 4 */
892         (fMMTable[11] & 0x03) == 0x00 ? "Unused/Invalid" :
893         (fMMTable[11] & 0x03) == 0x01 ? "Tuner Input" :
894         (fMMTable[11] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
895         (fMMTable[11] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
896         (fMMTable[11] & 0x38) >> 3
897     ));
898 }
899 #endif
900