xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/detect.c (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon kernel driver
6 
7 	Graphics card detection
8 */
9 
10 
11 #include "radeon_driver.h"
12 
13 #include <stdio.h>
14 
15 
16 // this table is gathered from different sources
17 // and may even contain some wrong entries
18 #define VENDOR_ID_ATI		0x1002
19 
20 // R100
21 #define DEVICE_ID_RADEON_QD		0x5144
22 #define DEVICE_ID_RADEON_QE		0x5145
23 #define DEVICE_ID_RADEON_QF		0x5146
24 #define DEVICE_ID_RADEON_QG		0x5147
25 
26 // RV100
27 #define DEVICE_ID_RADEON_QY		0x5159
28 #define DEVICE_ID_RADEON_QZ		0x515a
29 
30 // M6
31 #define DEVICE_ID_RADEON_LY		0x4c59
32 #define DEVICE_ID_RADEON_LZ		0x4c5a
33 
34 // RV200
35 #define DEVICE_ID_RADEON_QW		0x5157
36 #define DEVICE_ID_RADEON_QX		0x5158
37 
38 // R200 mobility
39 #define DEVICE_ID_RADEON_LW		0x4c57
40 #define DEVICE_ID_RADEON_LX		0x4c58
41 
42 // R200
43 #define DEVICE_ID_RADEON_QH		0x5148
44 #define DEVICE_ID_RADEON_QI		0x5149
45 #define DEVICE_ID_RADEON_QJ		0x514a
46 #define DEVICE_ID_RADEON_QK		0x514b
47 #define DEVICE_ID_RADEON_QL		0x514c
48 #define DEVICE_ID_RADEON_QM		0x514d
49 
50 #define DEVICE_ID_RADEON_Qh		0x5168
51 #define DEVICE_ID_RADEON_Qi		0x5169
52 #define DEVICE_ID_RADEON_Qj		0x516a
53 #define DEVICE_ID_RADEON_Qk		0x516b
54 
55 #define DEVICE_ID_RADEON_BB		0x4242
56 
57 // RV250
58 #define DEVICE_ID_RADEON_Id     0x4964
59 #define DEVICE_ID_RADEON_Ie     0x4965
60 #define DEVICE_ID_RADEON_If     0x4966
61 #define DEVICE_ID_RADEON_Ig     0x4967
62 
63 // M9
64 #define DEVICE_ID_RADEON_Ld     0x4c64
65 #define DEVICE_ID_RADEON_Le     0x4c65
66 #define DEVICE_ID_RADEON_Lf     0x4c66
67 #define DEVICE_ID_RADEON_Lg     0x4c67
68 
69 // M9+
70 #define DEVICE_ID_RADEON_5c61   0x5c61
71 
72 // RV280
73 #define DEVICE_ID_RADEON_Zprea	0x5960
74 #define DEVICE_ID_RADEON_Za		0x5961
75 #define DEVICE_ID_RADEON_Zd		0x5964
76 
77 // r300
78 #define DEVICE_ID_RADEON_ND     0x4e44
79 #define DEVICE_ID_RADEON_NE     0x4e45
80 #define DEVICE_ID_RADEON_NF     0x4e46
81 #define DEVICE_ID_RADEON_NG     0x4e47
82 
83 // r300-4P
84 #define DEVICE_ID_RADEON_AD     0x4144
85 #define DEVICE_ID_RADEON_AE     0x4145
86 #define DEVICE_ID_RADEON_AF     0x4146
87 #define DEVICE_ID_RADEON_AG     0x4147
88 
89 // rv350
90 #define DEVICE_ID_RADEON_AP		0x4150
91 #define DEVICE_ID_RADEON_AQ		0x4151
92 #define DEVICE_ID_RADEON_AS		0x4153
93 
94 // m10
95 #define DEVICE_ID_RADEON_NP		0x4e50
96 // Mobility Fire GL T2 - any idea about the chip?
97 #define DEVICE_ID_RADEON_NT		0x4e54
98 
99 // rv360
100 #define DEVICE_ID_RADEON_AR		0x4152
101 
102 // r350
103 #define DEVICE_ID_RADEON_AH		0x4148
104 #define DEVICE_ID_RADEON_NH		0x4e48
105 #define DEVICE_ID_RADEON_NI		0x4e49
106 
107 // r360
108 #define DEVICE_ID_RADEON_NJ		0x4e4a
109 
110 // rs100
111 #define DEVICE_ID_IGP320M		0x4336
112 
113 // rs200
114 #define DEVICE_ID_RADEON_C7		0x4337
115 #define DEVICE_ID_RADEON_A7		0x4137
116 
117 typedef struct {
118 	uint16 device_id;
119 	radeon_type asic;
120 	char *name;
121 } RadeonDevice;
122 
123 // list of supported devices
124 RadeonDevice radeon_device_list[] = {
125 	// original Radeons, now called r100
126 	{ DEVICE_ID_RADEON_QD,	rt_r100,	"Radeon 7200 / Radeon / ALL-IN-WONDER Radeon" },
127 	{ DEVICE_ID_RADEON_QE,	rt_r100,	"Radeon QE" },
128 	{ DEVICE_ID_RADEON_QF,	rt_r100,	"Radeon QF" },
129 	{ DEVICE_ID_RADEON_QG,	rt_r100,	"Radeon QG" },
130 
131 	// Radeon VE (low-cost, dual CRT, no TCL), now called RV100
132 	{ DEVICE_ID_RADEON_QY,	rt_ve,		"Radeon 7000 / Radeon VE" },
133 	{ DEVICE_ID_RADEON_QZ,	rt_ve, 		"Radeon QZ VE" },
134 
135 	// mobility version of original Radeon (based on VE), now called M6
136 	{ DEVICE_ID_RADEON_LY,	rt_m6,		"Radeon Mobility" },
137 	{ DEVICE_ID_RADEON_LZ,	rt_m6, 		"Radeon Mobility M6 LZ" },
138 
139 	// rs100 (integrated Radeon, seems to be a Radeon VE)
140 	{ DEVICE_ID_IGP320M,	rt_rs100,	"IGP320M" },
141 
142 	// RV200 (dual CRT)
143 	{ DEVICE_ID_RADEON_QW,	rt_rv200,	"Radeon 7500 / ALL-IN-WONDER Radeon 7500" },
144 	{ DEVICE_ID_RADEON_QX,	rt_rv200,	"Radeon 7500 QX" },
145 
146 	// M7 (based on RV200)
147 	{ DEVICE_ID_RADEON_LW,	rt_m7,		"Radeon Mobility 7500" },
148 	{ DEVICE_ID_RADEON_LX,	rt_m7,		"Radeon Mobility 7500 GL" },
149 
150 	// R200
151 	{ DEVICE_ID_RADEON_QH,	rt_r200,	"ATI Fire GL E1" },	// chip type: fgl8800
152 	{ DEVICE_ID_RADEON_QI,	rt_r200,	"Radeon 8500 QI" },
153 	{ DEVICE_ID_RADEON_QJ,	rt_r200,	"Radeon 8500 QJ" },
154 	{ DEVICE_ID_RADEON_QK,	rt_r200,	"Radeon 8500 QK" },
155 	{ DEVICE_ID_RADEON_QL,	rt_r200,	"Radeon 8500 / 8500LE / ALL-IN-WONDER Radeon 8500" },
156 	{ DEVICE_ID_RADEON_QM,	rt_r200,	"Radeon 9100" },
157 
158 	{ DEVICE_ID_RADEON_Qh,	rt_r200,	"Radeon 8500 Qh" },
159 	{ DEVICE_ID_RADEON_Qi,	rt_r200,	"Radeon 8500 Qi" },
160 	{ DEVICE_ID_RADEON_Qj,	rt_r200,	"Radeon 8500 Qj" },
161 	{ DEVICE_ID_RADEON_Qk,	rt_r200,	"Radeon 8500 Qk" },
162 	{ DEVICE_ID_RADEON_BB,	rt_r200,	"ALL-IN-Wonder Radeon 8500 DV" },
163 
164 	// RV250 (cut-down R200 with integrated TV-Out)
165 	{ DEVICE_ID_RADEON_Id,  rt_rv250,	"Radeon 9000 Id" },
166 	{ DEVICE_ID_RADEON_Ie,  rt_rv250,	"Radeon 9000 Ie" },
167 	{ DEVICE_ID_RADEON_If,  rt_rv250,	"Radeon 9000" },
168 	{ DEVICE_ID_RADEON_Ig,  rt_rv250,	"Radeon 9000 Ig" },
169 
170 	// M9 (based on rv250)
171 	{ DEVICE_ID_RADEON_Ld,	rt_m9,		"Radeon Mobility 9000 Ld" },
172 	{ DEVICE_ID_RADEON_Le,	rt_m9,		"Radeon Mobility 9000 Le" },
173 	{ DEVICE_ID_RADEON_Lf,	rt_m9,		"Radeon Mobility 9000 Lf" },
174 	{ DEVICE_ID_RADEON_Lg,	rt_m9,		"Radeon Mobility 9000 Lg" },
175 
176 	// RV280 (rv250 with higher frequency)
177 	// this entry violates naming scheme, so it's probably wrong
178 	{ DEVICE_ID_RADEON_Zprea, rt_rv280,	"Radeon 9200" },
179 	{ DEVICE_ID_RADEON_Za,	rt_rv280,	"Radeon 9200" },
180 	{ DEVICE_ID_RADEON_Zd,	rt_rv280,	"Radeon 9200 SE" },
181 
182 	// M9+ (based on rv280)
183 	{ DEVICE_ID_RADEON_5c61,rt_m9plus,	"Radeon Mobility 9200" },
184 
185 	// R300
186 	{ DEVICE_ID_RADEON_ND,	rt_r300,	"Radeon 9700 ND" },
187 	{ DEVICE_ID_RADEON_NE,	rt_r300,	"Radeon 9700 NE" },
188 	{ DEVICE_ID_RADEON_NF,	rt_r300,	"Radeon 9600 XT" },
189 	{ DEVICE_ID_RADEON_NG,	rt_r300,	"Radeon 9700 NG" },
190 
191 	{ DEVICE_ID_RADEON_AD,	rt_r300,	"Radeon 9700 AD" },
192 	{ DEVICE_ID_RADEON_AE,	rt_r300,	"Radeon 9700 AE" },
193 	{ DEVICE_ID_RADEON_AF,	rt_r300,	"Radeon 9700 AF" },
194 	{ DEVICE_ID_RADEON_AG,	rt_r300,	"Radeon 9700 AG" },
195 
196 	// RV350
197 	{ DEVICE_ID_RADEON_AP, 	rt_rv350,	"Radeon 9600 AP" },
198 	{ DEVICE_ID_RADEON_AQ, 	rt_rv350,	"Radeon 9600 AQ" },
199 	{ DEVICE_ID_RADEON_AS, 	rt_rv350,	"Radeon 9600 AS" },
200 
201 	// M10 (based on rv350)
202 	{ DEVICE_ID_RADEON_NP,	rt_m10,		"Radeon Mobility 9600 NP" },
203 	// not sure about that: ROM signature is "RADEON" which means r100
204 	{ DEVICE_ID_RADEON_NT,	rt_m10,		"Radeon Mobility FireGL T2" },
205 
206 	// RV360 (probably minor revision of rv350)
207 	{ DEVICE_ID_RADEON_AR, 	rt_rv360,	"Radeon 9600 AR" },
208 
209 	// R350
210 	{ DEVICE_ID_RADEON_AH,	rt_r350,	"Radeon 9800 AH" },
211 	{ DEVICE_ID_RADEON_NH,	rt_r350,	"Radeon 9800 Pro NH" },
212 	{ DEVICE_ID_RADEON_NI,	rt_r350,	"Radeon 9800 NI" },
213 
214 	// R360 (probably minor revision of r350)
215 	{ DEVICE_ID_RADEON_NJ, 	rt_r360,	"Radeon 9800 XT" },
216 
217 	// rs100 (aka IGP 320)
218 	{ DEVICE_ID_IGP320M, 	rt_rs100,	"Radeon IGP 320M" },
219 
220 	// rs200 (aka IGP 340)
221 	{ DEVICE_ID_RADEON_C7,	rt_rs200,	"IGP330M/340M/350M (U2) 4337" },
222 	{ DEVICE_ID_RADEON_A7,	rt_rs200,	"IGP 340" },
223 
224 	{ 0, 0, NULL }
225 };
226 
227 
228 // list of supported vendors (there aren't many ;)
229 static struct {
230 	uint16	vendor_id;
231 	RadeonDevice *devices;
232 } SupportedVendors[] = {
233 	{ VENDOR_ID_ATI, radeon_device_list },
234 	{ 0x0000, NULL }
235 };
236 
237 // check, whether there is *any* supported card plugged in
238 bool Radeon_CardDetect( void )
239 {
240 	long		pci_index = 0;
241 	pci_info	pcii;
242 	bool		found_one = FALSE;
243 
244 	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
245 		return B_ERROR;
246 
247 	while ((*pci_bus->get_nth_pci_info)(pci_index, &pcii) == B_NO_ERROR) {
248 		int vendor = 0;
249 
250 		while (SupportedVendors[vendor].vendor_id) {
251 			if (SupportedVendors[vendor].vendor_id == pcii.vendor_id) {
252 				RadeonDevice *devices = SupportedVendors[vendor].devices;
253 
254 				while (devices->device_id) {
255 					if (devices->device_id == pcii.device_id ) {
256 						rom_info ri;
257 
258 						if( Radeon_MapBIOS( &pcii, &ri ) == B_OK ) {
259 							Radeon_UnmapBIOS( &ri );
260 
261 							SHOW_INFO( 0, "found supported device pci index %ld, device 0x%04x/0x%04x",
262 								pci_index, pcii.vendor_id, pcii.device_id );
263 							found_one = TRUE;
264 							goto done;
265 						}
266 					}
267 					devices++;
268 				}
269 			}
270 			vendor++;
271 		}
272 
273 		pci_index++;
274 	}
275 	SHOW_INFO0( 0, "no supported devices found" );
276 
277 done:
278 	put_module(B_PCI_MODULE_NAME);
279 
280 	return (found_one ? B_OK : B_ERROR);
281 }
282 
283 // !extend this array whenever a new ASIC is a added!
284 static struct {
285 	const char 		*name;			// name of ASIC
286 	tv_chip_type	tv_chip;		// TV-Out chip (if any)
287 	bool 			has_crtc2;		// has second CRTC
288 	bool			is_mobility;	// mobility chip
289 	bool			has_vip;		// has VIP/I2C
290 	bool			new_pll;		// reference divider of PPLL moved to other location
291 	bool			is_igp;			// integrated graphics
292 } asic_properties[] =
293 {
294 	{ "r100",	tc_external_rt1,	false,	false,	true,	false,	false },	// only original Radeons have one crtc only
295 	{ "ve",		tc_internal_rt1, 	true,	false,	true,	false,	false },
296 	{ "m6",		tc_internal_rt1, 	true,	true,	false,	false,	false },
297 	{ "rs100",	tc_internal_rt1,	true,	true,	false,	false,	true },
298 	{ "rv200",	tc_internal_rt2, 	true,	false,	true,	false,	false },
299 	{ "m7",		tc_internal_rt1, 	true,	true,	false,	false,	false },
300 	{ "rs200",	tc_internal_rt1, 	true,	true,	false,	false,	true },
301 	{ "r200",	tc_external_rt1, 	true,	false,	true,	false,	false },	// r200 has external TV-Out encoder
302 	{ "rv250",	tc_internal_rt2, 	true,	false,	true,	false,	false },
303 	{ "m9",		tc_internal_rt2, 	true,	true,	false,	false,	false },
304 	{ "rv280",	tc_internal_rt2, 	true,	false,	true,	false,	false },
305 	{ "m9plus",	tc_internal_rt2, 	true,	true,	false,	false,	false },
306 	{ "r300",	tc_internal_rt2, 	true,	false,	true,	true,	false },
307 	{ "r300_4p",tc_internal_rt2, 	true,	false,	true,	true,	false },
308 	{ "rv350",	tc_internal_rt2, 	true,	false,	true,	true,	false },
309 	{ "m10",	tc_internal_rt2, 	true,	true,	false,	true,	false },
310 	{ "rv360",	tc_internal_rt2, 	true,	false,	true,	true,	false },
311 	{ "r350",	tc_internal_rt2, 	true,	false,	true,	true,	false },
312 	{ "r360",	tc_internal_rt2, 	true,	false,	true,	true,	false }
313 };
314 
315 
316 // get next supported device
317 static bool probeDevice( device_info *di )
318 {
319 	int vendor;
320 
321 	/* if we match a supported vendor */
322 	for( vendor = 0; SupportedVendors[vendor].vendor_id; ++vendor ) {
323 		RadeonDevice *device;
324 
325 		if( SupportedVendors[vendor].vendor_id != di->pcii.vendor_id )
326 			continue;
327 
328 		for( device = SupportedVendors[vendor].devices; device->device_id; ++device ) {
329 			// avoid double-detection
330 			if (device->device_id != di->pcii.device_id )
331 				continue;
332 
333 			di->num_crtc = asic_properties[device->asic].has_crtc2 ? 2 : 1;
334 			di->tv_chip = asic_properties[device->asic].tv_chip;
335 			di->asic = device->asic;
336 			di->is_mobility = asic_properties[device->asic].is_mobility;
337 			di->has_vip = asic_properties[device->asic].has_vip;
338 			di->new_pll = asic_properties[device->asic].new_pll;
339 			di->is_igp = asic_properties[device->asic].is_igp;
340 
341 			if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK )
342 				// give up checking this device - no BIOS, no fun
343 				return false;
344 
345 			if( Radeon_ReadBIOSData( di ) != B_OK ) {
346 				Radeon_UnmapBIOS( &di->rom );
347 				return false;
348 			}
349 
350 			// we don't need BIOS any more
351 			Radeon_UnmapBIOS( &di->rom );
352 
353 			SHOW_INFO( 0, "found %s; ASIC: %s", device->name, asic_properties[device->asic].name );
354 
355 			sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X",
356 				di->pcii.vendor_id, di->pcii.device_id,
357 				di->pcii.bus, di->pcii.device, di->pcii.function);
358 			SHOW_FLOW( 3, "making /dev/%s", di->name );
359 
360 			// we always publish it as a video grabber; we should check for Rage
361 			// Theater, but the corresponding code (vip.c) needs a fully initialized
362 			// driver, and this is too much hazzly, so we leave it to the media add-on
363 			// to verify that the card really supports video-in
364 			sprintf(di->video_name, "video/radeon/%04X_%04X_%02X%02X%02X",
365 				di->pcii.vendor_id, di->pcii.device_id,
366 				di->pcii.bus, di->pcii.device, di->pcii.function);
367 
368 			di->is_open = 0;
369 			di->shared_area = -1;
370 			di->si = NULL;
371 
372 			return true;
373 		}
374 	}
375 
376 	return false;
377 }
378 
379 
380 // gather list of supported devices
381 // (currently, we rely on proper BIOS detection, which
382 //  only works for primary graphics adapter, so multiple
383 //  devices won't really work)
384 void Radeon_ProbeDevices( void )
385 {
386 	uint32 pci_index = 0;
387 	uint32 count = 0;
388 	device_info *di = devices->di;
389 
390 	while( count < MAX_DEVICES ) {
391 		memset( di, 0, sizeof( *di ));
392 
393 		if( (*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) != B_NO_ERROR)
394 			break;
395 
396 		if( probeDevice( di )) {
397 			devices->device_names[2*count] = di->name;
398 			devices->device_names[2*count+1] = di->video_name;
399 			di++;
400 			count++;
401 		}
402 
403 		pci_index++;
404 	}
405 
406 	devices->count = count;
407 	devices->device_names[2*count] = NULL;
408 
409 	SHOW_INFO( 0, "%ld supported devices", count );
410 }
411