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