1/*
2	Copyright (c) 2002, Thomas Kurschel
3
4
5	Part of Radeon kernel driver
6
7	BIOS detection and retrieval of vital data
8
9	Most of this data should be gathered directly,
10	especially monitor detection should be done on
11	demand so not all monitors need to be connected
12	during boot
13*/
14
15#include "radeon_driver.h"
16#include "mmio.h"
17#include "bios_regs.h"
18#include "config_regs.h"
19#include "memcntrl_regs.h"
20#include "buscntrl_regs.h"
21#include "fp_regs.h"
22#include "crtc_regs.h"
23#include "ddc_regs.h"
24#include "radeon_bios.h"
25#include "utils.h"
26
27#include <stdio.h>
28#include <string.h>
29
30#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
31
32#define RADEON_BIOS8(v) 	 (di->rom.rom_ptr[v])
33#define RADEON_BIOS16(v) 	((di->rom.rom_ptr[v]) | \
34				(di->rom.rom_ptr[(v) + 1] << 8))
35#define RADEON_BIOS32(v) 	((di->rom.rom_ptr[v]) | \
36				(di->rom.rom_ptr[(v) + 1] << 8) | \
37				(di->rom.rom_ptr[(v) + 2] << 16) | \
38				(di->rom.rom_ptr[(v) + 3] << 24))
39
40static const char ati_rom_sig[] = "761295520";
41
42static const tmds_pll_info default_tmds_pll[14][4] =
43{
44    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},			// r100
45    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},			// rv100
46    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},						// rs100
47    {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},			// rv200
48    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},			// rs200
49    {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},			// r200
50    {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}},			// rv250
51    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},						// rs300
52    {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, 	// rv280
53    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},				// r300
54    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},				// r350
55    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},			// rv350
56    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},			// rv380
57    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},				// r420
58};
59
60
61// find address of ROM;
62// this code is really nasty as maintaining the radeon signatures
63// is almost impossible (the signatures provided by ATI are always out-dated);
64// further, if there is more then one card built into the computer, we
65// may detect the wrong BIOS!
66// we have two possible solutions:
67// 1. use the PCI location as stored in BIOS
68// 2. verify the IO-base address as stored in BIOS
69// I have no clue how these values are _written_ into the BIOS, and
70// unfortunately, every BIOS does the detection in a different way,
71// so I'm not sure which is the _right_ way of doing it
72static char *Radeon_FindRom( rom_info *ri )
73{
74	uint32 segstart;
75	uint8 *rom_base;
76	char *rom;
77	int i;
78
79	for( segstart = 0x000c0000; segstart < 0x000f0000; segstart += 0x00001000 ) {
80		bool found = false;
81
82		// find ROM
83		rom_base = ri->bios_ptr + segstart - 0xc0000;
84
85		if( rom_base[0] != 0x55 || rom_base[1] != 0xaa )
86			continue;
87
88		// find signature of ATI
89		rom = rom_base;
90
91		found = false;
92
93		for( i = 0; i < 128 - strlen( ati_rom_sig ); i++ ) {
94			if( ati_rom_sig[0] == rom_base[i] ) {
95				if( strncmp(ati_rom_sig, rom_base + i, strlen( ati_rom_sig )) == 0 ) {
96					found = true;
97					break;
98				}
99			}
100		}
101
102		if( !found )
103			continue;
104
105		// EK don't bother looking for signiture now, due to lack of consistancy.
106
107		SHOW_INFO( 2, "found ROM @0x%lx", segstart );
108		return rom_base;
109	}
110
111	SHOW_INFO0( 2, "no ROM found" );
112	return NULL;
113}
114
115
116// PLL info is stored in ROM, probably it's too easy to replace it
117// and thus they produce cards with different timings
118static void Radeon_GetPLLInfo( device_info *di )
119{
120	uint8 *bios_header;
121	uint8 *tmp;
122	PLL_BLOCK pll, *pll_info;
123
124	bios_header = di->rom.rom_ptr + *(uint16 *)(di->rom.rom_ptr + 0x48);
125	pll_info = (PLL_BLOCK *)(di->rom.rom_ptr + *(uint16 *)(bios_header + 0x30));
126
127	// determine type of ROM
128
129	tmp = bios_header + 4;
130
131    if ((	*tmp 	== 'A'
132   		&& *(tmp+1) == 'T'
133   		&& *(tmp+2) == 'O'
134   		&& *(tmp+3) == 'M'
135   		)
136   		||
137   		(	*tmp	== 'M'
138   		&& *(tmp+1) == 'O'
139   		&& *(tmp+2) == 'T'
140   		&& *(tmp+3) == 'A'
141   		))
142	{
143		int bios_header, master_data_start, pll_start;
144		di->is_atombios = true;
145
146		bios_header 	  	 = RADEON_BIOS16(0x48);
147		master_data_start 	 = RADEON_BIOS16(bios_header + 32);
148		pll_start 		  	 = RADEON_BIOS16(master_data_start + 12);
149
150		di->pll.ref_div 	 = 0;
151		di->pll.max_pll_freq = RADEON_BIOS16(pll_start + 32);
152		di->pll.xclk 		 = RADEON_BIOS16(pll_start + 72);
153		di->pll.min_pll_freq = RADEON_BIOS16(pll_start + 78);
154		di->pll.ref_freq 	 = RADEON_BIOS16(pll_start + 82);
155
156		SHOW_INFO( 2, "TESTING ref_clk=%ld, ref_div=%ld, xclk=%ld, min_freq=%ld, max_freq=%ld from ATOM Bios",
157		di->pll.ref_freq, di->pll.ref_div, di->pll.xclk,
158		di->pll.min_pll_freq, di->pll.max_pll_freq );
159
160		// Unused by beos driver so it appears...
161		// info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
162		// info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
163		// if (info->sclk == 0) info->sclk = 200;
164		// if (info->mclk == 0) info->mclk = 200;
165
166	}
167    else
168	{
169		di->is_atombios = false;
170
171		memcpy( &pll, pll_info, sizeof( pll ));
172
173		di->pll.xclk 		 = (uint32)pll.XCLK;
174		di->pll.ref_freq 	 = (uint32)pll.PCLK_ref_freq;
175		di->pll.ref_div 	 = (uint32)pll.PCLK_ref_divider;
176		di->pll.min_pll_freq = pll.PCLK_min_freq;
177		di->pll.max_pll_freq = pll.PCLK_max_freq;
178
179		SHOW_INFO( 2, "ref_clk=%ld, ref_div=%ld, xclk=%ld, min_freq=%ld, max_freq=%ld from Legacy BIOS",
180		di->pll.ref_freq, di->pll.ref_div, di->pll.xclk,
181		di->pll.min_pll_freq, di->pll.max_pll_freq );
182
183	}
184
185}
186
187/*
188const char *Mon2Str[] = {
189	"N/C",
190	"CRT",
191	"CRT",
192	"Laptop flatpanel",
193	"DVI (flatpanel)",
194	"secondary DVI (flatpanel) - unsupported",
195	"Composite TV",
196	"S-Video out"
197};*/
198
199/*
200// ask BIOS what kind of monitor is connected to each port
201static void Radeon_GetMonType( device_info *di )
202{
203	unsigned int tmp;
204
205	SHOW_FLOW0( 3, "" );
206
207	di->disp_type[0] = di->disp_type[1] = dt_none;
208
209	if (di->has_crtc2) {
210		tmp = INREG( di->regs, RADEON_BIOS_4_SCRATCH );
211
212		// ordering of "if"s is important as multiple
213		// devices can be concurrently connected to one port
214		// (like both a CRT and a TV)
215
216		// primary port
217		// having flat-panel support is most important
218		if (tmp & 0x08)
219			di->disp_type[0] = dt_dvi;
220		else if (tmp & 0x4)
221			di->disp_type[0] = dt_lvds;
222		else if (tmp & 0x200)
223			di->disp_type[0] = dt_tv_crt;
224		else if (tmp & 0x10)
225			di->disp_type[0] = dt_ctv;
226		else if (tmp & 0x20)
227			di->disp_type[0] = dt_stv;
228
229		// secondary port
230		// having TV-Out support is more important then CRT support
231		// (CRT gets signal anyway)
232		if (tmp & 0x1000)
233			di->disp_type[1] = dt_ctv;
234		else if (tmp & 0x2000)
235			di->disp_type[1] = dt_stv;
236		else if (tmp & 0x2)
237			di->disp_type[1] = dt_crt;
238		else if (tmp & 0x800)
239			di->disp_type[1] = dt_dvi_ext;
240		else if (tmp & 0x400)
241			// this is unlikely - I only know about one LVDS unit
242			di->disp_type[1] = dt_lvds;
243	} else {
244		// regular Radeon
245		// TBD: no TV-Out detection
246		di->disp_type[0] = dt_none;
247
248		tmp = INREG( di->regs, RADEON_FP_GEN_CNTL);
249
250		if( tmp & RADEON_FP_EN_TMDS )
251			di->disp_type[0] = dt_dvi;
252		else
253			di->disp_type[0] = dt_crt;
254	}
255
256	SHOW_INFO( 1, "BIOS reports %s on primary and %s on secondary port",
257		Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]);
258
259	// remove unsupported devices
260	if( di->disp_type[0] >= dt_dvi_ext )
261		di->disp_type[0] = dt_none;
262	if( di->disp_type[1] >= dt_dvi_ext )
263		di->disp_type[1] = dt_none;
264
265	// HACK: overlays can only be shown on first CRTC;
266	// if there's nothing on first port, connect
267	// second port to first CRTC (proper signal routing
268	// is hopefully done by BIOS)
269	if( di->has_crtc2 ) {
270		if( di->disp_type[0] == dt_none && di->disp_type[1] == dt_crt ) {
271			di->disp_type[0] = dt_crt;
272			di->disp_type[1] = dt_none;
273		}
274	}
275
276	SHOW_INFO( 1, "Effective routing: %s on primary and %s on secondary port",
277		Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]);
278}
279*/
280
281
282static bool Radeon_GetConnectorInfoFromBIOS ( device_info* di )
283{
284
285	ptr_disp_entity ptr_entity = &di->routing;
286	int i = 0, j, tmp, tmp0=0, tmp1=0;
287
288	int bios_header, master_data_start;
289
290	bios_header = RADEON_BIOS16(0x48);
291
292	if (di->is_atombios)
293	{
294		master_data_start = RADEON_BIOS16( bios_header + 32 );
295		tmp = RADEON_BIOS16( master_data_start + 22);
296		if (tmp) {
297			int crtc = 0, id[2];
298			tmp1 = RADEON_BIOS16( tmp + 4 );
299			for (i=0; i<8; i++) {
300				if(tmp1 & (1<<i)) {
301					uint16 portinfo = RADEON_BIOS16( tmp + 6 + i * 2 );
302					if (crtc < 2) {
303						if ((i == 2) || (i == 6)) continue; /* ignore TV here */
304
305						if ( crtc == 1 ) {
306							/* sharing same port with id[0] */
307							if ((( portinfo >> 8) & 0xf) == id[0] ) {
308								if (i == 3)
309									ptr_entity->port_info[0].tmds_type = tmds_int;
310								else if (i == 7)
311									ptr_entity->port_info[0].tmds_type = tmds_ext;
312
313								if (ptr_entity->port_info[0].dac_type == dac_unknown)
314									ptr_entity->port_info[0].dac_type = (portinfo & 0xf) - 1;
315								continue;
316							}
317						}
318
319						id[crtc] = (portinfo>>8) & 0xf;
320						ptr_entity->port_info[crtc].dac_type = (portinfo & 0xf) - 1;
321						ptr_entity->port_info[crtc].connector_type = (portinfo>>4) & 0xf;
322						if (i == 3)
323							ptr_entity->port_info[crtc].tmds_type = tmds_int;
324						else if (i == 7)
325							ptr_entity->port_info[crtc].tmds_type = tmds_ext;
326
327						tmp0 = RADEON_BIOS16( master_data_start + 24);
328						if( tmp0 && id[crtc] ) {
329							switch (RADEON_BIOS16(tmp0 + 4 + 27 * id[crtc]) * 4)
330							{
331								case RADEON_GPIO_MONID:
332									ptr_entity->port_info[crtc].ddc_type = ddc_monid;
333									break;
334								case RADEON_GPIO_DVI_DDC:
335									ptr_entity->port_info[crtc].ddc_type = ddc_dvi;
336									break;
337								case RADEON_GPIO_VGA_DDC:
338									ptr_entity->port_info[crtc].ddc_type = ddc_vga;
339									break;
340								case RADEON_GPIO_CRT2_DDC:
341									ptr_entity->port_info[crtc].ddc_type = ddc_crt2;
342									break;
343								default:
344									ptr_entity->port_info[crtc].ddc_type = ddc_none_detected;
345									break;
346							}
347
348						} else {
349							ptr_entity->port_info[crtc].ddc_type = ddc_none_detected;
350						}
351						crtc++;
352					} else {
353						/* we have already had two CRTCs assigned. the rest may share the same
354						* port with the existing connector, fill in them accordingly.
355						*/
356						for ( j = 0; j < 2; j++ ) {
357							if ((( portinfo >> 8 ) & 0xf ) == id[j] ) {
358								if ( i == 3 )
359								ptr_entity->port_info[j].tmds_type = tmds_int;
360								else if (i == 7)
361								ptr_entity->port_info[j].tmds_type = tmds_ext;
362
363								if ( ptr_entity->port_info[j].dac_type == dac_unknown )
364									ptr_entity->port_info[j].dac_type = ( portinfo & 0xf ) - 1;
365							}
366						}
367					}
368				}
369			}
370
371			for (i=0; i<2; i++) {
372				SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
373					i, ptr_entity->port_info[i].ddc_type, ptr_entity->port_info[i].dac_type,
374					ptr_entity->port_info[i].tmds_type, ptr_entity->port_info[i].connector_type);
375		    }
376		} else {
377			SHOW_INFO0( 4 , "No Device Info Table found!");
378			return FALSE;
379		}
380	} else {
381		/* Some laptops only have one connector (VGA) listed in the connector table,
382		* we need to add LVDS in as a non-DDC display.
383		* Note, we can't assume the listed VGA will be filled in PortInfo[0],
384		* when walking through connector table. connector_found has following meaning:
385		* 0 -- nothing found,
386		* 1 -- only PortInfo[0] filled,
387		* 2 -- only PortInfo[1] filled,
388		* 3 -- both are filled.
389		*/
390		int connector_found = 0;
391
392		if ((tmp = RADEON_BIOS16( bios_header + 0x50 ))) {
393			for ( i = 1; i < 4; i++ ) {
394
395				if (!(RADEON_BIOS16( tmp + i * 2 )))
396					break; /* end of table */
397
398				tmp0 = RADEON_BIOS16( tmp + i * 2 );
399				if ((( tmp0 >> 12 ) & 0x0f ) == 0 )
400					continue;     /* no connector */
401				if (connector_found > 0) {
402					if (ptr_entity->port_info[tmp1].ddc_type == (( tmp0 >> 8 ) & 0x0f ))
403						continue;	/* same connector */
404				}
405
406				/* internal ddc_dvi port will get assigned to portinfo[0], or if there is no ddc_dvi (like in some igps). */
407				tmp1 = (((( tmp0 >> 8 ) & 0xf ) == ddc_dvi ) || ( tmp1 == 1 )) ? 0 : 1; /* determine port info index */
408
409				ptr_entity->port_info[tmp1].ddc_type = (tmp0 >> 8) & 0x0f;
410				if (ptr_entity->port_info[tmp1].ddc_type > ddc_crt2)
411					ptr_entity->port_info[tmp1].ddc_type = ddc_none_detected;
412				ptr_entity->port_info[tmp1].dac_type = (tmp0 & 0x01) ? dac_tvdac : dac_primary;
413				ptr_entity->port_info[tmp1].connector_type = (tmp0 >> 12) & 0x0f;
414				if (ptr_entity->port_info[tmp1].connector_type > connector_unsupported)
415					ptr_entity->port_info[tmp1].connector_type = connector_unsupported;
416				ptr_entity->port_info[tmp1].tmds_type = ((tmp0 >> 4) & 0x01) ? tmds_ext : tmds_int;
417
418				/* some sanity checks */
419				if (((ptr_entity->port_info[tmp1].connector_type != connector_dvi_d) &&
420				(ptr_entity->port_info[tmp1].connector_type != connector_dvi_i)) &&
421				ptr_entity->port_info[tmp1].tmds_type == tmds_int)
422				ptr_entity->port_info[tmp1].tmds_type = tmds_unknown;
423
424				connector_found += (tmp1 + 1);
425			}
426		} else {
427			SHOW_INFO0(4, "No Connector Info Table found!");
428			return FALSE;
429		}
430
431		if (di->is_mobility)
432		{
433			/* For the cases where only one VGA connector is found,
434			we assume LVDS is not listed in the connector table,
435			add it in here as the first port.
436			*/
437			if ((connector_found < 3) && (ptr_entity->port_info[tmp1].connector_type == connector_crt)) {
438				if (connector_found == 1) {
439					memcpy (&ptr_entity->port_info[1],
440						&ptr_entity->port_info[0],
441							sizeof (ptr_entity->port_info[0]));
442				}
443				ptr_entity->port_info[0].dac_type = dac_tvdac;
444				ptr_entity->port_info[0].tmds_type = tmds_unknown;
445				ptr_entity->port_info[0].ddc_type = ddc_none_detected;
446				ptr_entity->port_info[0].connector_type = connector_proprietary;
447
448				SHOW_INFO0( 4 , "lvds port is not in connector table, added in.");
449				if (connector_found == 0)
450					connector_found = 1;
451				else
452					connector_found = 3;
453			}
454
455			if ((tmp = RADEON_BIOS16( bios_header + 0x42 ))) {
456				if ((tmp0 = RADEON_BIOS16( tmp + 0x15 ))) {
457					if ((tmp1 = RADEON_BIOS16( tmp0 + 2 ) & 0x07)) {
458						ptr_entity->port_info[0].ddc_type	= tmp1;
459						if (ptr_entity->port_info[0].ddc_type > ddc_crt2) {
460							SHOW_INFO( 4, "unknown ddctype %d found",
461								ptr_entity->port_info[0].ddc_type);
462							ptr_entity->port_info[0].ddc_type = ddc_none_detected;
463						}
464						SHOW_INFO0( 4, "lcd ddc info table found!");
465					}
466				}
467			}
468		} else if (connector_found == 2) {
469			memcpy (&ptr_entity->port_info[0],
470				&ptr_entity->port_info[1],
471					sizeof (ptr_entity->port_info[0]));
472			ptr_entity->port_info[1].dac_type = dac_unknown;
473			ptr_entity->port_info[1].tmds_type = tmds_unknown;
474			ptr_entity->port_info[1].ddc_type = ddc_none_detected;
475			ptr_entity->port_info[1].connector_type = connector_none;
476			connector_found = 1;
477		}
478
479		if (connector_found == 0) {
480			SHOW_INFO0( 4, "no connector found in connector info table.");
481		} else {
482			SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
483				0, ptr_entity->port_info[0].ddc_type, ptr_entity->port_info[0].dac_type,
484				ptr_entity->port_info[0].tmds_type, ptr_entity->port_info[0].connector_type);
485
486		}
487		if (connector_found == 3) {
488			SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
489				1, ptr_entity->port_info[1].ddc_type, ptr_entity->port_info[1].dac_type,
490				ptr_entity->port_info[1].tmds_type, ptr_entity->port_info[1].connector_type);
491		}
492
493	}
494	return TRUE;
495}
496
497
498// get flat panel info (does only make sense for Laptops
499// with integrated display, but looking for it doesn't hurt,
500// who knows which strange kind of combination is out there?)
501static bool Radeon_GetBIOSDFPInfo( device_info *di )
502{
503	uint16 bios_header;
504	uint16 fpi_offset;
505	FPI_BLOCK fpi;
506	char panel_name[30];
507	int i;
508
509	uint16 tmp;
510
511	bios_header = RADEON_BIOS16( 0x48 );
512
513	if (di->is_atombios)
514	{
515		int master_data_start;
516		master_data_start = RADEON_BIOS16( bios_header + 32 );
517
518		tmp = RADEON_BIOS16( master_data_start + 16 );
519		if( tmp )
520		{
521
522		    di->fp_info.panel_xres		= RADEON_BIOS16( tmp +  6 );
523		    di->fp_info.panel_yres		= RADEON_BIOS16( tmp + 10 );
524		    di->fp_info.dot_clock		= RADEON_BIOS16( tmp +  4 ) * 10;
525		    di->fp_info.h_blank			= RADEON_BIOS16( tmp +  8 );
526		    di->fp_info.h_over_plus		= RADEON_BIOS16( tmp + 14 );
527		    di->fp_info.h_sync_width	= RADEON_BIOS16( tmp + 16 );
528		    di->fp_info.v_blank      	= RADEON_BIOS16( tmp + 12 );
529			di->fp_info.v_over_plus		= RADEON_BIOS16( tmp + 18 );
530		    di->fp_info.h_sync_width	= RADEON_BIOS16( tmp + 20 );
531		    di->fp_info.panel_pwr_delay	= RADEON_BIOS16( tmp + 40 );
532
533		    SHOW_INFO( 2, "Panel Info from ATOMBIOS:\n"
534					"XRes: %d, YRes: %d, DotClock: %d\n"
535					"HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n"
536					"VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n"
537					"PanelPowerDelay: %d\n",
538					di->fp_info.panel_xres,	di->fp_info.panel_yres,	di->fp_info.dot_clock,
539					di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width,
540					di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.h_sync_width,
541					di->fp_info.panel_pwr_delay	);
542
543		}
544		else
545		{
546		    di->fp_info.panel_pwr_delay = 200;
547			SHOW_ERROR0( 2, "No Panel Info Table found in BIOS" );
548			return false;
549		}
550	} // is_atombios
551	else
552	{
553
554		fpi_offset = RADEON_BIOS16(bios_header + 0x40);
555
556		if( !fpi_offset ) {
557			di->fp_info.panel_pwr_delay = 200;
558			SHOW_ERROR0( 2, "No Panel Info Table found in BIOS" );
559			return false;
560		}
561
562		memcpy( &fpi, di->rom.rom_ptr + fpi_offset, sizeof( fpi ));
563
564		memcpy( panel_name, &fpi.name, sizeof( fpi.name ) );
565		panel_name[sizeof( fpi.name )] = 0;
566
567		SHOW_INFO( 2, "Panel ID string: %s", panel_name );
568
569		di->fp_info.panel_xres = fpi.panel_xres;
570		di->fp_info.panel_yres = fpi.panel_yres;
571
572		SHOW_INFO( 2, "Panel Size from BIOS: %dx%d",
573			di->fp_info.panel_xres, di->fp_info.panel_yres);
574
575		di->fp_info.panel_pwr_delay = fpi.panel_pwr_delay;
576		if( di->fp_info.panel_pwr_delay > 2000 || di->fp_info.panel_pwr_delay < 0 )
577			di->fp_info.panel_pwr_delay = 2000;
578
579		di->fp_info.ref_div = fpi.ref_div;
580		di->fp_info.post_div = fpi.post_div;
581		di->fp_info.feedback_div = fpi.feedback_div;
582
583		di->fp_info.fixed_dividers =
584			di->fp_info.ref_div != 0 && di->fp_info.feedback_div > 3;
585
586
587		// there might be multiple supported resolutions stored;
588		// we are looking for native resolution
589		for( i = 0; i < 20; ++i ) {
590			uint16 fpi_timing_ofs;
591			FPI_TIMING_BLOCK fpi_timing;
592
593			fpi_timing_ofs = fpi.fpi_timing_ofs[i];
594
595			if( fpi_timing_ofs == 0 )
596				break;
597
598			memcpy( &fpi_timing, di->rom.rom_ptr + fpi_timing_ofs, sizeof( fpi_timing ));
599
600			if( fpi_timing.panel_xres != di->fp_info.panel_xres ||
601				fpi_timing.panel_yres != di->fp_info.panel_yres )
602				continue;
603
604			di->fp_info.h_blank			= (fpi_timing.h_total - fpi_timing.h_display) * 8;
605			// TBD: seems like upper four bits of hsync_start contain garbage
606			di->fp_info.h_over_plus 	= ((fpi_timing.h_sync_start & 0xfff) - fpi_timing.h_display - 1) * 8;
607			di->fp_info.h_sync_width 	= fpi_timing.h_sync_width * 8;
608			di->fp_info.v_blank			= fpi_timing.v_total - fpi_timing.v_display;
609			di->fp_info.v_over_plus 	= (fpi_timing.v_sync & 0x7ff) - fpi_timing.v_display;
610			di->fp_info.v_sync_width 	= (fpi_timing.v_sync & 0xf800) >> 11;
611			di->fp_info.dot_clock 		= fpi_timing.dot_clock * 10;
612			return true;
613		}
614	} // not is_atombios
615
616	SHOW_ERROR0( 2, "Radeon: couldn't get Panel Timing from BIOS" );
617	return false;
618}
619
620
621// try to reverse engineer DFP specification from
622// timing currently set up in graphics cards registers
623// (effectively, we hope that BIOS has set it up correctly
624//  and noone has messed registers up yet; let's pray)
625static void Radeon_RevEnvDFPSize( device_info *di )
626{
627	vuint8 *regs = di->regs;
628
629	di->fp_info.panel_yres =
630		((INREG( regs, RADEON_FP_VERT_STRETCH ) & RADEON_VERT_PANEL_SIZE)
631		>> RADEON_VERT_PANEL_SIZE_SHIFT) + 1;
632
633	di->fp_info.panel_xres =
634		(((INREG( regs, RADEON_FP_HORZ_STRETCH ) & RADEON_HORZ_PANEL_SIZE)
635		>> RADEON_HORZ_PANEL_SIZE_SHIFT) + 1) * 8;
636
637	SHOW_INFO( 2, "detected panel size from registers: %dx%d",
638		di->fp_info.panel_xres, di->fp_info.panel_yres);
639}
640
641
642// once more for getting precise timing
643static void Radeon_RevEnvDFPTiming( device_info *di )
644{
645	vuint8 *regs = di->regs;
646	uint32 r;
647	uint16 a, b;
648
649
650	r = INREG( regs, RADEON_FP_CRTC_H_TOTAL_DISP );
651	// the magic "4" was found by trial and error and probably stems from fudge (see crtc.c)
652	a = (r & RADEON_FP_CRTC_H_TOTAL_MASK)/* + 4*/;
653	b = (r & RADEON_FP_CRTC_H_DISP_MASK) >> RADEON_FP_CRTC_H_DISP_SHIFT;
654	di->fp_info.h_blank = (a - b) * 8;
655
656	SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 );
657
658	r = INREG( regs, RADEON_FP_H_SYNC_STRT_WID );
659	di->fp_info.h_over_plus =
660		((r & RADEON_FP_H_SYNC_STRT_CHAR_MASK)
661			  	>> RADEON_FP_H_SYNC_STRT_CHAR_SHIFT) - b/* - 1*/;
662	di->fp_info.h_over_plus *= 8;
663	di->fp_info.h_sync_width =
664		((r & RADEON_FP_H_SYNC_WID_MASK)
665				>> RADEON_FP_H_SYNC_WID_SHIFT);
666	// TBD: this seems to be wrong
667	// (my BIOS tells 112, this calculation leads to 24!)
668	di->fp_info.h_sync_width *= 8;
669
670	r = INREG( regs, RADEON_FP_CRTC_V_TOTAL_DISP );
671	a = (r & RADEON_FP_CRTC_V_TOTAL_MASK)/* + 1*/;
672	b = (r & RADEON_FP_CRTC_V_DISP_MASK) >> RADEON_FP_CRTC_V_DISP_SHIFT;
673	di->fp_info.v_blank = a - b;
674
675	SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b );
676
677	r = INREG( regs, RADEON_FP_V_SYNC_STRT_WID );
678	di->fp_info.v_over_plus = (r & RADEON_FP_V_SYNC_STRT_MASK) - b;
679	di->fp_info.v_sync_width = ((r & RADEON_FP_V_SYNC_WID_MASK)
680		>> RADEON_FP_V_SYNC_WID_SHIFT)/* + 1*/;
681
682	// standard CRTC
683	r = INREG( regs, RADEON_CRTC_H_TOTAL_DISP );
684	a = (r & RADEON_CRTC_H_TOTAL);
685	b = (r & RADEON_CRTC_H_DISP) >> RADEON_CRTC_H_DISP_SHIFT;
686	di->fp_info.h_blank = (a - b) * 8;
687
688	SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 );
689
690	r = INREG( regs, RADEON_CRTC_H_SYNC_STRT_WID );
691	di->fp_info.h_over_plus =
692		((r & RADEON_CRTC_H_SYNC_STRT_CHAR)
693			  	>> RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) - b;
694	di->fp_info.h_over_plus *= 8;
695	di->fp_info.h_sync_width =
696		((r & RADEON_CRTC_H_SYNC_WID)
697				>> RADEON_CRTC_H_SYNC_WID_SHIFT);
698	di->fp_info.h_sync_width *= 8;
699
700	r = INREG( regs, RADEON_CRTC_V_TOTAL_DISP );
701	a = (r & RADEON_CRTC_V_TOTAL);
702	b = (r & RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT;
703	di->fp_info.v_blank = a - b;
704
705	SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b );
706
707	r = INREG( regs, RADEON_CRTC_V_SYNC_STRT_WID );
708	di->fp_info.v_over_plus = (r & RADEON_CRTC_V_SYNC_STRT) - b;
709	di->fp_info.v_sync_width = ((r & RADEON_CRTC_V_SYNC_WID)
710		>> RADEON_CRTC_V_SYNC_WID_SHIFT);
711}
712
713//snaffled from X.org hope it works...
714static void Radeon_GetTMDSInfoFromBios( device_info *di )
715{
716    uint32 tmp, maxfreq;
717    uint32 found = FALSE;
718    int i, n;
719    uint16 bios_header;
720
721    bios_header = RADEON_BIOS16( 0x48 );
722
723	for (i = 0; i < 4; i++) {
724        di->tmds_pll[i].value = 0;
725        di->tmds_pll[i].freq = 0;
726    }
727
728	if (di->is_atombios)
729	{
730		int master_data_start;
731		master_data_start = RADEON_BIOS16( bios_header + 32 );
732
733		if((tmp = RADEON_BIOS16 (master_data_start + 18))) {
734
735		    maxfreq = RADEON_BIOS16(tmp + 4);
736
737		    for (i = 0; i < 4; i++) {
738				di->tmds_pll[i].freq = RADEON_BIOS16(tmp + i * 6 + 6);
739				// This assumes each field in TMDS_PLL has 6 bit as in R300/R420
740				di->tmds_pll[i].value = ((RADEON_BIOS8(tmp + i * 6 + 8) & 0x3f) |
741				   ((RADEON_BIOS8(tmp + i * 6 + 10) & 0x3f) << 6) |
742				   ((RADEON_BIOS8(tmp + i * 6 +  9) & 0xf) << 12) |
743				   ((RADEON_BIOS8(tmp + i * 6 + 11) & 0xf) << 16));
744				SHOW_ERROR( 2, "TMDS PLL from BIOS: %ld %lx",
745				   di->tmds_pll[i].freq, di->tmds_pll[i].value);
746
747				if (maxfreq == di->tmds_pll[i].freq) {
748				    di->tmds_pll[i].freq = 0xffffffff;
749				    break;
750				}
751		    }
752		    found = TRUE;
753		}
754    } else {
755
756		tmp = RADEON_BIOS16(bios_header + 0x34);
757		if (tmp) {
758		    SHOW_ERROR( 2, "DFP table revision: %d", RADEON_BIOS8(tmp));
759		    if (RADEON_BIOS8(tmp) == 3) {
760				n = RADEON_BIOS8(tmp + 5) + 1;
761				if (n > 4)
762					n = 4;
763				for (i = 0; i < n; i++) {
764					di->tmds_pll[i].value = RADEON_BIOS32(tmp + i * 10 + 0x08);
765					di->tmds_pll[i].freq = RADEON_BIOS16(tmp + i * 10 + 0x10);
766				}
767				found = TRUE;
768		    } else if (RADEON_BIOS8(tmp) == 4) {
769		        int stride = 0;
770				n = RADEON_BIOS8(tmp + 5) + 1;
771				if (n > 4)
772					n = 4;
773				for (i = 0; i < n; i++) {
774				    di->tmds_pll[i].value = RADEON_BIOS32(tmp + stride + 0x08);
775				    di->tmds_pll[i].freq = RADEON_BIOS16(tmp + stride + 0x10);
776				    if (i == 0)
777				    	stride += 10;
778				    else
779				    	stride += 6;
780				}
781				found = TRUE;
782		    }
783
784		    // revision 4 has some problem as it appears in RV280,
785		    // comment it off for now, use default instead
786			/*
787				else if (RADEON_BIOS8(tmp) == 4) {
788				int stride = 0;
789				n = RADEON_BIOS8(tmp + 5) + 1;
790				if (n > 4) n = 4;
791				for (i = 0; i < n; i++) {
792					di->tmds_pll[i].value = RADEON_BIOS32(tmp + stride + 0x08);
793					di->tmds_pll[i].freq = RADEON_BIOS16(tmp + stride + 0x10);
794					if (i == 0)
795						stride += 10;
796					else
797						stride += 6;
798				}
799				found = TRUE;
800			}
801			*/
802
803		}
804    }
805
806    if (found == FALSE) {
807    	for (i = 0; i < 4; i++) {
808	        di->tmds_pll[i].value = default_tmds_pll[di->asic][i].value;
809	        di->tmds_pll[i].freq = default_tmds_pll[di->asic][i].freq;
810	        SHOW_ERROR( 2, "TMDS PLL from DEFAULTS: %ld %lx",
811				di->tmds_pll[i].freq, di->tmds_pll[i].value);
812    	}
813    }
814}
815
816/*
817// get everything in terms of monitors connected to the card
818static void Radeon_GetBIOSMon( device_info *di )
819{
820	Radeon_GetMonType( di );
821
822    // reset all Flat Panel Info;
823    // it gets filled out step by step, and this way we know what's still missing
824    memset( &di->fp_info, 0, sizeof( di->fp_info ));
825
826    // we assume that the only fp port is combined with standard port 0
827	di->fp_info.disp_type = di->disp_type[0];
828
829	if( di->is_mobility ) {
830		// there is a flat panel - get info about it
831		Radeon_GetBIOSDFPInfo( di );
832
833		// if BIOS doesn't know, ask the registers
834		if( di->fp_info.panel_xres == 0 || di->fp_info.panel_yres == 0)
835			Radeon_RevEnvDFPSize( di );
836
837		if( di->fp_info.h_blank == 0 || di->fp_info.v_blank == 0)
838			Radeon_RevEnvDFPTiming( di );
839
840		SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
841			di->fp_info.panel_xres, di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width );
842		SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
843			di->fp_info.panel_yres, di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.v_sync_width );
844		SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock );
845	}
846}
847*/
848
849// get info about Laptop flat panel
850static void Radeon_GetFPData( device_info *di )
851{
852    // reset all Flat Panel Info;
853    // it gets filled out step by step, and this way we know what's still missing
854    memset( &di->fp_info, 0, sizeof( di->fp_info ));
855
856	// we only use BIOS for Laptop flat panels
857	if( !di->is_mobility )
858		return;
859
860	// ask BIOS about flat panel spec
861	Radeon_GetBIOSDFPInfo( di );
862
863	// if BIOS doesn't know, ask the registers
864	if( di->fp_info.panel_xres == 0 || di->fp_info.panel_yres == 0)
865		Radeon_RevEnvDFPSize( di );
866
867	if( di->fp_info.h_blank == 0 || di->fp_info.v_blank == 0)
868		Radeon_RevEnvDFPTiming( di );
869
870	SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
871		di->fp_info.panel_xres, di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width );
872	SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
873		di->fp_info.panel_yres, di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.v_sync_width );
874	SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock );
875}
876
877
878// Depending on card genertation, chipset bugs, etc... the amount of vram
879// accessible to the CPU can vary. This function is our best shot at figuring
880// it out. Returns a value in KB.
881static uint32 RADEON_GetAccessibleVRAM( device_info *di )
882{
883	vuint8 *regs = di->regs;
884	pci_info *pcii = &(di->pcii);
885
886    uint32 aper_size = INREG( regs, RADEON_CONFIG_APER_SIZE );
887
888    // Set HDP_APER_CNTL only on cards that are known not to be broken,
889    // that is has the 2nd generation multifunction PCI interface
890    if (di->asic == rt_rv280 ||
891		di->asic == rt_rv350 ||
892		di->asic == rt_rv380 ||
893		di->asic == rt_r420  ) {
894			OUTREGP( regs, RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
895		     ~RADEON_HDP_APER_CNTL);
896	    SHOW_INFO0( 0, "Generation 2 PCI interface, using max accessible memory");
897	    return aper_size * 2;
898    }
899
900    // Older cards have all sorts of funny issues to deal with. First
901    // check if it's a multifunction card by reading the PCI config
902    // header type... Limit those to one aperture size
903    if (get_pci(PCI_header_type, 1) & 0x80) {
904		SHOW_INFO0( 0, "Generation 1 PCI interface in multifunction mode"
905				", accessible memory limited to one aperture\n");
906		return aper_size;
907    }
908
909    // Single function older card. We read HDP_APER_CNTL to see how the BIOS
910    // have set it up. We don't write this as it's broken on some ASICs but
911    // we expect the BIOS to have done the right thing (might be too optimistic...)
912    if (INREG( regs, RADEON_HOST_PATH_CNTL ) & RADEON_HDP_APER_CNTL )
913        return aper_size * 2;
914
915    return aper_size;
916}
917
918
919// detect amount of graphics memory
920static void Radeon_DetectRAM( device_info *di )
921{
922	vuint8 *regs = di->regs;
923	uint32 accessible, bar_size, tmp = 0;
924
925	if( di->is_igp	) {
926		uint32 tom;
927
928		tom = INREG( regs, RADEON_NB_TOM );
929		di->local_mem_size = ((tom >> 16) + 1 - (tom & 0xffff)) << 16;
930		OUTREG( regs, RADEON_CONFIG_MEMSIZE, di->local_mem_size * 1024);
931	} else {
932		di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK;
933	}
934
935	// some production boards of m6 will return 0 if it's 8 MB
936	if( di->local_mem_size == 0 ) {
937		di->local_mem_size = 8 * 1024 *1024;
938		OUTREG( regs, RADEON_CONFIG_MEMSIZE, di->local_mem_size);
939	}
940
941
942	// Get usable Vram, after asic bugs, configuration screw ups etc
943	accessible = RADEON_GetAccessibleVRAM( di );
944
945	// Crop it to the size of the PCI BAR
946	bar_size = di->pcii.u.h0.base_register_sizes[0];
947	if (bar_size == 0)
948	    bar_size = 0x200000;
949	if (accessible > bar_size)
950	    accessible = bar_size;
951
952	SHOW_INFO( 0, "Detected total video RAM=%ldK, accessible=%ldK (PCI BAR=%ldK)"
953		, di->local_mem_size/1024, accessible/1024, bar_size/1024);
954	if (di->local_mem_size > accessible)
955	    di->local_mem_size = accessible;
956
957	// detect ram bus width only used by dynamic clocks for now.
958	tmp = INREG( regs, RADEON_MEM_CNTL );
959	if (IS_DI_R300_VARIANT) {
960		tmp &=  R300_MEM_NUM_CHANNELS_MASK;
961		switch (tmp) {
962			case 0: di->ram.width = 64; break;
963			case 1: di->ram.width = 128; break;
964			case 2: di->ram.width = 256; break;
965			default: di->ram.width = 128; break;
966		}
967	} else if ( (di->asic >= rt_rv100) ||
968				(di->asic >= rt_rs100) ||
969				(di->asic >= rt_rs200)) {
970		if (tmp & RV100_HALF_MODE)
971			di->ram.width = 32;
972		else
973			di->ram.width = 64;
974	} else {
975		if (tmp & RADEON_MEM_NUM_CHANNELS_MASK)
976			di->ram.width = 128;
977		else
978			di->ram.width = 64;
979	}
980
981	if (di->is_igp || (di->asic >= rt_r300))
982	{
983		uint32 mem_type = INREG( regs, RADEON_MEM_SDRAM_MODE_REG ) & RADEON_MEM_CFG_TYPE_MASK;
984		if ( mem_type == RADEON_MEM_CFG_SDR) {
985				// SDR SGRAM (2:1)
986				strcpy(di->ram_type, "SDR SGRAM");
987				di->ram.ml = 4;
988				di->ram.MB = 4;
989				di->ram.Trcd = 1;
990				di->ram.Trp = 2;
991				di->ram.Twr = 1;
992				di->ram.CL = 2;
993				di->ram.loop_latency = 16;
994				di->ram.Rloop = 16;
995				di->ram.Tr2w = 0;
996		} else {  // RADEON_MEM_CFG_DDR
997				// DDR SGRAM
998				strcpy(di->ram_type, "DDR SGRAM");
999				di->ram.ml = 4;
1000				di->ram.MB = 4;
1001				di->ram.Trcd = 3;
1002				di->ram.Trp = 3;
1003				di->ram.Twr = 2;
1004				di->ram.CL = 3;
1005				di->ram.Tr2w = 1;
1006				di->ram.loop_latency = 16;
1007				di->ram.Rloop = 16;
1008		}
1009	}
1010
1011	SHOW_INFO( 1, "%ld MB %s found on %d wide bus",
1012		di->local_mem_size / 1024 / 1024, di->ram_type, di->ram.width);
1013
1014/*	if( di->local_mem_size > 64 * 1024 * 1024 ) {
1015		di->local_mem_size = 64 * 1024 * 1024;
1016
1017		SHOW_INFO0( 1, "restricted to 64 MB" );
1018	}*/
1019}
1020
1021
1022// map and verify card's BIOS to see whether this really is a Radeon
1023// (as we need BIOS for further info we have to make sure we use the right one)
1024status_t Radeon_MapBIOS( pci_info *pcii, rom_info *ri )
1025{
1026	char buffer[100];
1027
1028	sprintf(buffer, "%04X_%04X_%02X%02X%02X bios",
1029		pcii->vendor_id, pcii->device_id,
1030		pcii->bus, pcii->device, pcii->function);
1031
1032	// we only scan BIOS at legacy location in first MB;
1033	// using the PCI location would improve detection, especially
1034	// if multiple graphics cards are installed
1035	// BUT: BeOS uses the first graphics card it finds (sorted by
1036	// device name), thus you couldn't choose in BIOS which card
1037	// to use; checking the legacy location ensures that the card is
1038	// only detected if it's the primary card
1039	ri->phys_address = 0xc0000;
1040	ri->size = 0x40000;
1041
1042	ri->bios_area = map_physical_memory( buffer, ri->phys_address,
1043		ri->size, B_ANY_KERNEL_ADDRESS, B_READ_AREA, (void **)&ri->bios_ptr );
1044	if( ri->bios_area < 0 )
1045		return ri->bios_area;
1046
1047	ri->rom_ptr = Radeon_FindRom( ri );
1048
1049	// on success, adjust physical address to found ROM
1050	if( ri->rom_ptr != NULL )
1051		ri->phys_address += ri->rom_ptr - ri->bios_ptr;
1052
1053	return ri->rom_ptr != NULL ? B_OK : B_ERROR;
1054}
1055
1056
1057// unmap card's BIOS
1058void Radeon_UnmapBIOS( rom_info *ri )
1059{
1060	delete_area( ri->bios_area );
1061
1062	ri->bios_ptr = ri->rom_ptr = NULL;
1063}
1064
1065
1066// get everything valuable from BIOS (BIOS must be mapped)
1067status_t Radeon_ReadBIOSData( device_info *di )
1068{
1069	shared_info dummy_si;
1070	status_t result = B_OK;
1071
1072	// give Radeon_MapDevice something to play with
1073	di->si = &dummy_si;
1074
1075	// don't map frame buffer - we don't know its proper size yet!
1076	result = Radeon_MapDevice( di, true );
1077	if( result < 0 )
1078		goto err1;
1079
1080	Radeon_GetPLLInfo( di );
1081
1082	// setup defaults
1083	di->routing.port_info[0].mon_type = mt_unknown;
1084	di->routing.port_info[0].ddc_type = ddc_none_detected;
1085	di->routing.port_info[0].dac_type = dac_unknown;
1086	di->routing.port_info[0].tmds_type = tmds_unknown;
1087	di->routing.port_info[0].connector_type = connector_none;
1088
1089	di->routing.port_info[1].mon_type = mt_unknown;
1090	di->routing.port_info[1].ddc_type = ddc_none_detected;
1091	di->routing.port_info[1].dac_type = dac_unknown;
1092	di->routing.port_info[1].tmds_type = tmds_unknown;
1093	di->routing.port_info[1].connector_type = connector_none;
1094
1095	if ( !Radeon_GetConnectorInfoFromBIOS( di ) )
1096	{
1097		di->routing.port_info[0].mon_type = mt_unknown;
1098		di->routing.port_info[0].ddc_type = ddc_none_detected;
1099		di->routing.port_info[0].dac_type = dac_tvdac;
1100		di->routing.port_info[0].tmds_type = tmds_unknown;
1101		di->routing.port_info[0].connector_type = connector_proprietary;
1102
1103		di->routing.port_info[1].mon_type = mt_unknown;
1104		di->routing.port_info[1].ddc_type = ddc_none_detected;
1105		di->routing.port_info[1].dac_type = dac_primary;
1106		di->routing.port_info[1].tmds_type = tmds_ext;
1107		di->routing.port_info[1].connector_type = connector_crt;
1108
1109	}
1110	Radeon_GetFPData( di );
1111	Radeon_GetTMDSInfoFromBios( di );
1112	Radeon_DetectRAM( di );
1113
1114	Radeon_UnmapDevice( di );
1115
1116err1:
1117	di->si = NULL;
1118
1119	return result;
1120}
1121