xref: /haiku/src/add-ons/kernel/drivers/audio/hda/driver.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
1 /*
2  * Copyright 2007-2008, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ithamar Adema, ithamar AT unet DOT nl
7  */
8 
9 
10 #include "driver.h"
11 
12 
13 int32 api_version = B_CUR_DRIVER_API_VERSION;
14 
15 hda_controller gCards[MAX_CARDS];
16 uint32 gNumCards;
17 pci_module_info* gPci;
18 
19 
20 static struct {
21 	uint16	vendor;
22 	uint16	device;
23 } kSupportedDevices[] = {
24 	{ 0x8086, 0xa170},	// 100 Series HD Audio
25 	{ 0x8086, 0x9d71},	// 200 Series HD Audio
26 	{ 0x8086, 0xa348},	// 300 Series cAVS
27 	{ 0x8086, 0x9dc8},	// 300 Series HD Audio
28 	{ 0x8086, 0x06c8},	// 400 Series cAVS
29 	{ 0x8086, 0x02c8},	// 400 Series HD Audio
30 	{ 0x8086, 0xa0c8},	// 500 Series HD Audio
31 	{ 0x8086, 0x51c8},	// 600 Series HD Audio
32 	{ 0x8086, 0x4dc8},	// JasperLake HD Audio
33 	{ 0x8086, 0x43c8},	// Tiger Lake-H HD Audio
34 	{ 0x8086, 0xa171},	// CM238 HD Audio
35 	{ 0x8086, 0x3198},	// GeminiLake HD Audio
36 };
37 
38 
39 static bool
40 supports_device(pci_info &info)
41 {
42 	for (size_t i = 0; i < B_COUNT_OF(kSupportedDevices); i++) {
43 		if (info.vendor_id == kSupportedDevices[i].vendor
44 			&& info.device_id == kSupportedDevices[i].device) {
45 			return true;
46 		}
47 	}
48 	return false;
49 }
50 
51 
52 extern "C" status_t
53 init_hardware(void)
54 {
55 	pci_info info;
56 	long i;
57 
58 	if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK)
59 		return ENODEV;
60 
61 	for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) {
62 		if ((info.class_base == PCI_multimedia
63 				&& info.class_sub == PCI_hd_audio)
64 			|| supports_device(info)) {
65 			put_module(B_PCI_MODULE_NAME);
66 			return B_OK;
67 		}
68 	}
69 
70 	put_module(B_PCI_MODULE_NAME);
71 	return ENODEV;
72 }
73 
74 
75 extern "C" status_t
76 init_driver(void)
77 {
78 	char path[B_PATH_NAME_LENGTH];
79 	pci_info info;
80 	long i;
81 
82 	if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK)
83 		return ENODEV;
84 
85 	gNumCards = 0;
86 
87 	for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK
88 			&& gNumCards < MAX_CARDS; i++) {
89 		if ((info.class_base == PCI_multimedia
90 				&& info.class_sub == PCI_hd_audio)
91 			|| supports_device(info)) {
92 #ifdef __HAIKU__
93 			if ((*gPci->reserve_device)(info.bus, info.device, info.function,
94 				"hda", &gCards[gNumCards]) < B_OK) {
95 				dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n",
96 					info.bus, info.device, info.function);
97 				continue;
98 			}
99 #endif
100 			memset(&gCards[gNumCards], 0, sizeof(hda_controller));
101 			gCards[gNumCards].pci_info = info;
102 			gCards[gNumCards].opened = 0;
103 			sprintf(path, DEVFS_PATH_FORMAT, gNumCards);
104 			gCards[gNumCards++].devfs_path = strdup(path);
105 
106 			dprintf("HDA: Detected controller @ PCI:%d:%d:%d, IRQ:%d, "
107 				"type %04x/%04x (%04x/%04x)\n",
108 				info.bus, info.device, info.function,
109 				info.u.h0.interrupt_line, info.vendor_id, info.device_id,
110 				info.u.h0.subsystem_vendor_id, info.u.h0.subsystem_id);
111 		}
112 	}
113 
114 	if (gNumCards == 0) {
115 		put_module(B_PCI_MODULE_NAME);
116 		return ENODEV;
117 	}
118 
119 	return B_OK;
120 }
121 
122 
123 extern "C" void
124 uninit_driver(void)
125 {
126 	for (uint32 i = 0; i < gNumCards; i++) {
127 #ifdef __HAIKU__
128 		(*gPci->unreserve_device)(gCards[i].pci_info.bus,
129 			gCards[i].pci_info.device, gCards[i].pci_info.function, "hda",
130 			&gCards[i]);
131 #endif
132 		free((void*)gCards[i].devfs_path);
133 		gCards[i].devfs_path = NULL;
134 	}
135 
136 	put_module(B_PCI_MODULE_NAME);
137 }
138 
139 
140 extern "C" const char**
141 publish_devices(void)
142 {
143 	static const char* devs[MAX_CARDS + 1];
144 	uint32 i;
145 
146 	for (i = 0; i < gNumCards; i++)
147 		devs[i] = gCards[i].devfs_path;
148 
149 	devs[i] = NULL;
150 
151 	return devs;
152 }
153 
154 
155 extern "C" device_hooks*
156 find_device(const char* name)
157 {
158 	return &gDriverHooks;
159 }
160