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