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