xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "driver.h"
11 #include "device.h"
12 #include "lock.h"
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <AGP.h>
19 #include <KernelExport.h>
20 #include <OS.h>
21 #include <PCI.h>
22 #include <SupportDefs.h>
23 
24 
25 #define TRACE_DRIVER
26 #ifdef TRACE_DRIVER
27 #	define TRACE(x...) dprintf("intel_extreme: " x)
28 #else
29 #	define TRACE(x) ;
30 #endif
31 
32 #define ERROR(x...) dprintf("intel_extreme: " x)
33 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
34 
35 
36 #define MAX_CARDS 4
37 
38 
39 // list of supported devices
40 const struct supported_device {
41 	uint32		device_id;
42 	int32		type;
43 	const char*	name;
44 } kSupportedDevices[] = {
45 	{0x3577, INTEL_GROUP_83x, "i830GM"},
46 	{0x2562, INTEL_GROUP_83x, "i845G"},
47 
48 	{0x2572, INTEL_GROUP_85x, "i865G"},
49 	{0x3582, INTEL_GROUP_85x, "i855G"},
50 	{0x358e, INTEL_GROUP_85x, "i855G"},
51 
52 	{0x2582, INTEL_MODEL_915, "i915G"},
53 	{0x258a, INTEL_MODEL_915, "i915"},
54 	{0x2592, INTEL_MODEL_915M, "i915GM"},
55 	{0x2792, INTEL_MODEL_915, "i910"},
56 	{0x2772, INTEL_MODEL_945, "i945G"},
57 	{0x27a2, INTEL_MODEL_945M, "i945GM"},
58 	{0x27ae, INTEL_MODEL_945M, "i945GME"},
59 	{0x2972, INTEL_MODEL_965, "i946G"},
60 	{0x2982, INTEL_MODEL_965, "G35"},
61 	{0x2992, INTEL_MODEL_965, "i965Q"},
62 	{0x29a2, INTEL_MODEL_965, "i965G"},
63 	{0x2a02, INTEL_MODEL_965M, "i965GM"},
64 	{0x2a12, INTEL_MODEL_965M, "i965GME"},
65 	{0x29b2, INTEL_MODEL_G33, "G33G"},
66 	{0x29c2, INTEL_MODEL_G33, "Q35G"},
67 	{0x29d2, INTEL_MODEL_G33, "Q33G"},
68 
69 	{0x2a42, INTEL_MODEL_GM45, "GM45"},
70 	{0x2e02, INTEL_MODEL_G45, "IGD"},
71 	{0x2e12, INTEL_MODEL_G45, "Q45"},
72 	{0x2e22, INTEL_MODEL_G45, "G45"},
73 	{0x2e32, INTEL_MODEL_G45, "G41"},
74 	{0x2e42, INTEL_MODEL_G45, "B43"},
75 	{0x2e92, INTEL_MODEL_G45, "B43"},
76 
77 	{0xa001, INTEL_MODEL_PINE, "Atom D4xx"},
78 	{0xa002, INTEL_MODEL_PINE, "Atom D5xx"},
79 	{0xa011, INTEL_MODEL_PINEM, "Atom N4xx"},
80 	{0xa012, INTEL_MODEL_PINEM, "Atom N5xx"},
81 
82 	{0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"},
83 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
84 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
85 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
86 
87 	{0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"},
88 	{0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"},
89 	{0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"},
90 	{0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"},
91 	{0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"},
92 	{0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"},
93 	{0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"},
94 
95 	{0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"},
96 	{0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"},
97 	{0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"},
98 	{0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"},
99 	{0x0152, INTEL_MODEL_IVBGS, "IvyBridge Server"},
100 	{0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"},
101 	{0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"},
102 
103 	{0x0a06, INTEL_MODEL_HASM, "Haswell ULT GT1 Mobile"},
104 	{0x0412, INTEL_MODEL_HAS, "Haswell GT2 Desktop"},
105 	{0x0416, INTEL_MODEL_HASM, "Haswell GT2 Mobile"},
106 	{0x0a16, INTEL_MODEL_HASM, "Haswell ULT GT2 Mobile"},
107 	{0x0d26, INTEL_MODEL_HASM, "Haswell CRW GT3 Mobile"},
108 
109 #if 0
110 	{0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
111 	{0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
112 	{0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
113 	{0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
114 #endif
115 
116 	{0x1606, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"},
117 	{0x160b, INTEL_MODEL_BDWM, "Broadwell GT1 Iris"},
118 	{0x160e, INTEL_MODEL_BDWM, "Broadwell GT1 ULX"},
119 	{0x1602, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"},
120 	{0x160a, INTEL_MODEL_BDWS, "Broadwell GT1 Server"},
121 	{0x160d, INTEL_MODEL_BDW,  "Broadwell GT1 Workstation"},
122 	{0x1616, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"},
123 	{0x161b, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"},
124 	{0x161e, INTEL_MODEL_BDWM, "Broadwell GT2 ULX"},
125 	{0x1612, INTEL_MODEL_BDWM, "Broadwell GT2 Halo"},
126 	{0x161a, INTEL_MODEL_BDWS, "Broadwell GT2 Server"},
127 	{0x161d, INTEL_MODEL_BDW,  "Broadwell GT2 Workstation"},
128 	{0x1626, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"},
129 	{0x162b, INTEL_MODEL_BDWM, "Broadwell GT3 Iris"},
130 	{0x162e, INTEL_MODEL_BDWM, "Broadwell GT3 ULX"},
131 	{0x1622, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"},
132 	{0x162a, INTEL_MODEL_BDWS, "Broadwell GT3 Server"},
133 	{0x162d, INTEL_MODEL_BDW,  "Broadwell GT3 Workstation"},
134 
135 	{0x1902, INTEL_MODEL_SKY,  "Skylake GT1"},
136 	{0x1906, INTEL_MODEL_SKYM, "Skylake GT1"},
137 	{0x190a, INTEL_MODEL_SKYS, "Skylake GT1"},
138 	{0x190b, INTEL_MODEL_SKY,  "Skylake GT1"},
139 	{0x190e, INTEL_MODEL_SKYM, "Skylake GT1"},
140 	{0x1912, INTEL_MODEL_SKY,  "Skylake GT2"}, //confirmed OK
141 	{0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, //confirmed native mode panel OK
142 	{0x191a, INTEL_MODEL_SKYS, "Skylake GT2"},
143 	{0x191b, INTEL_MODEL_SKY,  "Skylake GT2"},
144 	{0x191d, INTEL_MODEL_SKY,  "Skylake GT2"},
145 	{0x191e, INTEL_MODEL_SKYM, "Skylake GT2"},
146 	{0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"},
147 	{0x1926, INTEL_MODEL_SKYM, "Skylake GT3"},
148 	{0x192a, INTEL_MODEL_SKYS, "Skylake GT3"},
149 	{0x192b, INTEL_MODEL_SKY,  "Skylake GT3"},
150 
151 	{0x5906, INTEL_MODEL_KBY,  "Kabylake ULT GT1"},
152 	{0x5902, INTEL_MODEL_KBY,  "Kabylake DT GT1"},
153 	{0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"},
154 	{0x5921, INTEL_MODEL_KBYM, "Kabylake ULT GT2F"},
155 	{0x591c, INTEL_MODEL_KBY,  "Kabylake ULX GT2"},
156 	{0x591e, INTEL_MODEL_KBY,  "Kabylake ULX GT2"},
157 	{0x5912, INTEL_MODEL_KBY,  "Kabylake DT GT2"},
158 	{0x5917, INTEL_MODEL_KBYM, "Kabylake Mobile GT2"},
159 	{0x591b, INTEL_MODEL_KBYM, "Kabylake Halo GT2"},
160 	{0x591d, INTEL_MODEL_KBY,  "Kabylake WKS GT2"},
161 	{0x5926, INTEL_MODEL_KBY,  "Kabylake ULT GT3"},
162 	{0x5927, INTEL_MODEL_KBY,  "Kabylake ULT GT3"},
163 
164 	{0x3185, INTEL_MODEL_KBYM, "GeminiLake GT1"},	// Same device id for desktop and mobile.
165 	{0x3184, INTEL_MODEL_KBYM, "GeminiLake GT1.5"},	// Same device id for desktop and mobile.
166 
167 	{0x3e90, INTEL_MODEL_CFL,  "CoffeeLake GT1"},
168 	{0x3e93, INTEL_MODEL_CFL,  "CoffeeLake GT1"},
169 	{0x3e91, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
170 	{0x3e92, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
171 	{0x3e96, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
172 	{0x3e98, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
173 	{0x3e9a, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
174 	{0x3e9b, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"},
175 	{0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"},
176 	{0x3ea5, INTEL_MODEL_CFL,  "CoffeeLake GT3"},
177 	{0x3ea6, INTEL_MODEL_CFL,  "CoffeeLake GT3"},
178 
179 	{0x8a56, INTEL_MODEL_CFLM, "IceLake GT1"},
180 	{0x8a5c, INTEL_MODEL_CFLM, "IceLake GT1.5"},
181 	{0x8a5a, INTEL_MODEL_CFLM, "IceLake GT1.5"},
182 	{0x8a51, INTEL_MODEL_CFLM, "IceLake GT2"},
183 	{0x8a52, INTEL_MODEL_CFLM, "IceLake GT2"},
184 	{0x8a53, INTEL_MODEL_CFLM, "IceLake GT2"},
185 
186 	{0x9ba4, INTEL_MODEL_CML,	"CometLake GT1"},
187 	{0x9ba8, INTEL_MODEL_CML,	"CometLake GT1"},
188 	{0x9b21, INTEL_MODEL_CMLM,	"CometLake U GT1"},
189 	{0x9baa, INTEL_MODEL_CMLM,	"CometLake U GT1"},
190 	{0x9bc4, INTEL_MODEL_CML,	"CometLake GT2"},
191 	{0x9bc5, INTEL_MODEL_CML,	"CometLake GT2"},
192 	{0x9bc6, INTEL_MODEL_CML,	"CometLake GT2"},
193 	{0x9bc8, INTEL_MODEL_CML,	"CometLake GT2"},
194 	{0x9be6, INTEL_MODEL_CML,	"CometLake GT2"},
195 	{0x9bf6, INTEL_MODEL_CML,	"CometLake GT2"},
196 	{0x9b41, INTEL_MODEL_CMLM,	"CometLake U GT2"},
197 	{0x9bca, INTEL_MODEL_CMLM,	"CometLake U GT2"},
198 	{0x9bcc, INTEL_MODEL_CMLM,	"CometLake U GT2"},
199 
200 	{0x4e55, INTEL_MODEL_JSL,	"JasperLake"},
201 	{0x4e61, INTEL_MODEL_JSL,	"JasperLake"},
202 	{0x4e71, INTEL_MODEL_JSLM,	"JasperLake"},
203 
204 	{0x9a49, INTEL_MODEL_TGLM,	"TigerLake"},
205 	{0x9a78, INTEL_MODEL_TGLM,	"TigerLake"},
206 	{0x9a40, INTEL_MODEL_TGLM,	"TigerLake"},
207 	{0x9a60, INTEL_MODEL_TGLM,	"TigerLake"},
208 	{0x9a68, INTEL_MODEL_TGLM,	"TigerLake"},
209 	{0x9a70, INTEL_MODEL_TGLM,	"TigerLake"},
210 };
211 
212 int32 api_version = B_CUR_DRIVER_API_VERSION;
213 
214 char* gDeviceNames[MAX_CARDS + 1];
215 intel_info* gDeviceInfo[MAX_CARDS];
216 pci_module_info* gPCI;
217 agp_gart_module_info* gGART;
218 mutex gLock;
219 
220 
221 static status_t
222 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type)
223 {
224 	int32 index = *_cookie;
225 
226 	// find devices
227 
228 	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
229 		// check vendor
230 		if (info.vendor_id != VENDOR_ID_INTEL
231 			|| info.class_base != PCI_display
232 			|| (info.class_sub != PCI_vga && info.class_sub != PCI_display_other))
233 			continue;
234 
235 		// check device
236 		for (uint32 i = 0; i < sizeof(kSupportedDevices)
237 				/ sizeof(kSupportedDevices[0]); i++) {
238 			if (info.device_id == kSupportedDevices[i].device_id) {
239 				type = i;
240 				*_cookie = index + 1;
241 				ERROR("%s: Intel gfx deviceID: 0x%04x\n", __func__, info.device_id);
242 				return B_OK;
243 			}
244 		}
245 	}
246 
247 	return B_ENTRY_NOT_FOUND;
248 }
249 
250 
251 static enum pch_info
252 detect_intel_pch()
253 {
254 	pci_info info;
255 
256 	// find devices
257 	for (int32 i = 0; gPCI->get_nth_pci_info(i, &info) == B_OK; i++) {
258 		// check vendor
259 		if (info.vendor_id != VENDOR_ID_INTEL
260 			|| info.class_base != PCI_bridge
261 			|| info.class_sub != PCI_isa) {
262 			continue;
263 		}
264 
265 		// check device
266 		unsigned short id = info.device_id & INTEL_PCH_DEVICE_ID_MASK;
267 		ERROR("%s: Intel PCH deviceID: 0x%04x\n", __func__, info.device_id);
268 		switch(id) {
269 			case INTEL_PCH_IBX_DEVICE_ID:
270 				ERROR("%s: Found Ibex Peak PCH\n", __func__);
271 				return INTEL_PCH_IBX;
272 			case INTEL_PCH_CPT_DEVICE_ID:
273 				ERROR("%s: Found CougarPoint PCH\n", __func__);
274 				return INTEL_PCH_CPT;
275 			case INTEL_PCH_PPT_DEVICE_ID:
276 				ERROR("%s: Found PantherPoint PCH\n", __func__);
277 				return INTEL_PCH_CPT;
278 			case INTEL_PCH_LPT_DEVICE_ID:
279 			case INTEL_PCH_LPT_LP_DEVICE_ID:
280 				ERROR("%s: Found LynxPoint PCH\n", __func__);
281 				return INTEL_PCH_LPT;
282 			case INTEL_PCH_WPT_DEVICE_ID:
283 			case INTEL_PCH_WPT_LP_DEVICE_ID:
284 				ERROR("%s: Found WildcatPoint PCH\n", __func__);
285 				return INTEL_PCH_LPT;
286 			case INTEL_PCH_SPT_DEVICE_ID:
287 			case INTEL_PCH_SPT_LP_DEVICE_ID:
288 				ERROR("%s: Found SunrisePoint PCH\n", __func__);
289 				return INTEL_PCH_SPT;
290 			case INTEL_PCH_KBP_DEVICE_ID:
291 				ERROR("%s: Found Kaby Lake PCH\n", __func__);
292 				return INTEL_PCH_SPT;
293 			case INTEL_PCH_GMP_DEVICE_ID:
294 				ERROR("%s: Found Gemini Lake PCH\n", __func__);
295 				return INTEL_PCH_CNP;
296 			case INTEL_PCH_CNP_DEVICE_ID:
297 			case INTEL_PCH_CNP_LP_DEVICE_ID:
298 				ERROR("%s: Found Cannon Lake PCH\n", __func__);
299 				return INTEL_PCH_CNP;
300 			case INTEL_PCH_CMP_DEVICE_ID:
301 			case INTEL_PCH_CMP2_DEVICE_ID:
302 				ERROR("%s: Found Comet Lake PCH\n", __func__);
303 				return INTEL_PCH_CNP;
304 			case INTEL_PCH_CMP_V_DEVICE_ID:
305 				ERROR("%s: Found Comet Lake V PCH\n", __func__);
306 				return INTEL_PCH_SPT;
307 			case INTEL_PCH_ICP_DEVICE_ID:
308 			case INTEL_PCH_ICP2_DEVICE_ID:
309 				ERROR("%s: Found Ice Lake PCH\n", __func__);
310 				return INTEL_PCH_ICP;
311 			case INTEL_PCH_MCC_DEVICE_ID:
312 				ERROR("%s: Found Mule Creek Canyon PCH\n", __func__);
313 				return INTEL_PCH_MCC;
314 			case INTEL_PCH_TGP_DEVICE_ID:
315 			case INTEL_PCH_TGP2_DEVICE_ID:
316 				ERROR("%s: Found Tiger Lake PCH\n", __func__);
317 				return INTEL_PCH_TGP;
318 			case INTEL_PCH_JSP_DEVICE_ID:
319 				ERROR("%s: Found Jasper Lake PCH\n", __func__);
320 				return INTEL_PCH_JSP;
321 			case INTEL_PCH_ADP_DEVICE_ID:
322 			case INTEL_PCH_ADP2_DEVICE_ID:
323 			case INTEL_PCH_ADP3_DEVICE_ID:
324 			case INTEL_PCH_ADP4_DEVICE_ID:
325 				ERROR("%s: Found Alder Lake PCH\n", __func__);
326 				return INTEL_PCH_ADP;
327 		}
328 	}
329 
330 	ERROR("%s: No PCH detected.\n", __func__);
331 	return INTEL_PCH_NONE;
332 }
333 
334 
335 extern "C" const char**
336 publish_devices(void)
337 {
338 	CALLED();
339 	return (const char**)gDeviceNames;
340 }
341 
342 
343 extern "C" status_t
344 init_hardware(void)
345 {
346 	CALLED();
347 
348 	status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI);
349 	if (status != B_OK) {
350 		ERROR("pci module unavailable\n");
351 		return status;
352 	}
353 
354 	int32 cookie = 0;
355 	uint32 type;
356 	pci_info info;
357 	status = get_next_intel_extreme(&cookie, info, type);
358 
359 	put_module(B_PCI_MODULE_NAME);
360 	return status;
361 }
362 
363 
364 extern "C" status_t
365 init_driver(void)
366 {
367 	CALLED();
368 
369 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
370 	if (status != B_OK) {
371 		ERROR("pci module unavailable\n");
372 		return status;
373 	}
374 
375 	status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
376 	if (status != B_OK) {
377 		ERROR("AGP GART module unavailable\n");
378 		put_module(B_PCI_MODULE_NAME);
379 		return status;
380 	}
381 
382 	mutex_init(&gLock, "intel extreme ksync");
383 
384 	// find the PCH device (if any)
385 	enum pch_info pchInfo = detect_intel_pch();
386 
387 	// find devices
388 
389 	int32 found = 0;
390 
391 	for (int32 cookie = 0; found < MAX_CARDS;) {
392 		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
393 		if (info == NULL)
394 			break;
395 
396 		uint32 type;
397 		status = get_next_intel_extreme(&cookie, *info, type);
398 		if (status < B_OK) {
399 			free(info);
400 			break;
401 		}
402 
403 		// create device names & allocate device info structure
404 
405 		char name[64];
406 		sprintf(name, "graphics/intel_extreme_%02x%02x%02x",
407 			 info->bus, info->device,
408 			 info->function);
409 
410 		gDeviceNames[found] = strdup(name);
411 		if (gDeviceNames[found] == NULL)
412 			break;
413 
414 		gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info));
415 		if (gDeviceInfo[found] == NULL) {
416 			free(gDeviceNames[found]);
417 			break;
418 		}
419 
420 		// initialize the structure for later use
421 
422 		memset(gDeviceInfo[found], 0, sizeof(intel_info));
423 		gDeviceInfo[found]->init_status = B_NO_INIT;
424 		gDeviceInfo[found]->id = found;
425 		gDeviceInfo[found]->pci = info;
426 		gDeviceInfo[found]->registers = info->u.h0.base_registers[0];
427 		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
428 		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
429 		gDeviceInfo[found]->pch_info = pchInfo;
430 
431 		dprintf(DEVICE_NAME ": (%" B_PRId32 ") %s, revision = 0x%x\n", found,
432 			kSupportedDevices[type].name, info->revision);
433 
434 		found++;
435 	}
436 
437 	gDeviceNames[found] = NULL;
438 
439 	if (found == 0) {
440 		mutex_destroy(&gLock);
441 		put_module(B_AGP_GART_MODULE_NAME);
442 		put_module(B_PCI_MODULE_NAME);
443 		return ENODEV;
444 	}
445 
446 	return B_OK;
447 }
448 
449 
450 extern "C" void
451 uninit_driver(void)
452 {
453 	CALLED();
454 
455 	mutex_destroy(&gLock);
456 
457 	// free device related structures
458 	char* name;
459 	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
460 		free(gDeviceInfo[index]);
461 		free(name);
462 	}
463 
464 	put_module(B_AGP_GART_MODULE_NAME);
465 	put_module(B_PCI_MODULE_NAME);
466 }
467 
468 
469 extern "C" device_hooks*
470 find_device(const char* name)
471 {
472 	CALLED();
473 
474 	int index;
475 	for (index = 0; gDeviceNames[index] != NULL; index++) {
476 		if (!strcmp(name, gDeviceNames[index]))
477 			return &gDeviceHooks;
478 	}
479 
480 	return NULL;
481 }
482