xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.cpp (revision 07910542fd067906c6028cfc48f5ad38b32181fd)
1*07910542SSiarzhuk Zharski /*
2*07910542SSiarzhuk Zharski  *	SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
3*07910542SSiarzhuk Zharski  *	Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li>
4*07910542SSiarzhuk Zharski  *	Distributed under the terms of the MIT license.
5*07910542SSiarzhuk Zharski  *
6*07910542SSiarzhuk Zharski  */
7*07910542SSiarzhuk Zharski 
8*07910542SSiarzhuk Zharski 
9*07910542SSiarzhuk Zharski #include "Driver.h"
10*07910542SSiarzhuk Zharski 
11*07910542SSiarzhuk Zharski #include <kernel_cpp.h>
12*07910542SSiarzhuk Zharski #include <string.h>
13*07910542SSiarzhuk Zharski 
14*07910542SSiarzhuk Zharski #include "Device.h"
15*07910542SSiarzhuk Zharski #include "Settings.h"
16*07910542SSiarzhuk Zharski 
17*07910542SSiarzhuk Zharski 
18*07910542SSiarzhuk Zharski int32 api_version = B_CUR_DRIVER_API_VERSION;
19*07910542SSiarzhuk Zharski 
20*07910542SSiarzhuk Zharski size_t gNumCards = 0;
21*07910542SSiarzhuk Zharski Device *gDevices[MAX_DEVICES] = { 0 };
22*07910542SSiarzhuk Zharski char *gDeviceNames[MAX_DEVICES + 1] = { 0 };
23*07910542SSiarzhuk Zharski pci_module_info *gPCI = NULL;
24*07910542SSiarzhuk Zharski 
25*07910542SSiarzhuk Zharski 
26*07910542SSiarzhuk Zharski static Device::Info cardInfos[] = {
27*07910542SSiarzhuk Zharski 	{ SiS7018, "SiS 7018" },
28*07910542SSiarzhuk Zharski 	{ ALi5451, "ALi M5451" },
29*07910542SSiarzhuk Zharski 	{ TridentDX, "Trident DX" },
30*07910542SSiarzhuk Zharski 	{ TridentNX, "Trident NX" }
31*07910542SSiarzhuk Zharski };
32*07910542SSiarzhuk Zharski 
33*07910542SSiarzhuk Zharski 
34*07910542SSiarzhuk Zharski status_t
35*07910542SSiarzhuk Zharski init_hardware()
36*07910542SSiarzhuk Zharski {
37*07910542SSiarzhuk Zharski 	dprintf("sis7018:init_hardware:ver:%s\n", kVersion);
38*07910542SSiarzhuk Zharski 	status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
39*07910542SSiarzhuk Zharski 	if (result < B_OK) {
40*07910542SSiarzhuk Zharski 		return ENOSYS;
41*07910542SSiarzhuk Zharski 	}
42*07910542SSiarzhuk Zharski 
43*07910542SSiarzhuk Zharski 	pci_info info = {0};
44*07910542SSiarzhuk Zharski 	for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) {
45*07910542SSiarzhuk Zharski 		for (size_t idx = 0; idx < _countof(cardInfos); idx++) {
46*07910542SSiarzhuk Zharski 			if (info.vendor_id == cardInfos[idx].VendorId() &&
47*07910542SSiarzhuk Zharski 				info.device_id == cardInfos[idx].DeviceId())
48*07910542SSiarzhuk Zharski 			{
49*07910542SSiarzhuk Zharski 				put_module(B_PCI_MODULE_NAME);
50*07910542SSiarzhuk Zharski 				return B_OK;
51*07910542SSiarzhuk Zharski 			}
52*07910542SSiarzhuk Zharski 		}
53*07910542SSiarzhuk Zharski 	}
54*07910542SSiarzhuk Zharski 
55*07910542SSiarzhuk Zharski 	put_module(B_PCI_MODULE_NAME);
56*07910542SSiarzhuk Zharski 	return ENODEV;
57*07910542SSiarzhuk Zharski }
58*07910542SSiarzhuk Zharski 
59*07910542SSiarzhuk Zharski 
60*07910542SSiarzhuk Zharski status_t
61*07910542SSiarzhuk Zharski init_driver()
62*07910542SSiarzhuk Zharski {
63*07910542SSiarzhuk Zharski 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
64*07910542SSiarzhuk Zharski 	if (status < B_OK) {
65*07910542SSiarzhuk Zharski 		return ENOSYS;
66*07910542SSiarzhuk Zharski 	}
67*07910542SSiarzhuk Zharski 
68*07910542SSiarzhuk Zharski 	load_settings();
69*07910542SSiarzhuk Zharski 
70*07910542SSiarzhuk Zharski 	pci_info info = { 0 };
71*07910542SSiarzhuk Zharski 	for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) {
72*07910542SSiarzhuk Zharski 		for (size_t idx = 0; idx < _countof(cardInfos); idx++) {
73*07910542SSiarzhuk Zharski 			if (info.vendor_id == cardInfos[idx].VendorId() &&
74*07910542SSiarzhuk Zharski 				info.device_id == cardInfos[idx].DeviceId())
75*07910542SSiarzhuk Zharski 			{
76*07910542SSiarzhuk Zharski 				if (gNumCards == MAX_DEVICES) {
77*07910542SSiarzhuk Zharski 					ERROR("Skipped:%s [%#06x:%#06x]\n", cardInfos[idx].Name(),
78*07910542SSiarzhuk Zharski 						cardInfos[idx].VendorId(), cardInfos[idx].DeviceId());
79*07910542SSiarzhuk Zharski 					break;
80*07910542SSiarzhuk Zharski 				}
81*07910542SSiarzhuk Zharski 
82*07910542SSiarzhuk Zharski 				Device* device = new Device(cardInfos[idx], info);
83*07910542SSiarzhuk Zharski 				if (device == 0) {
84*07910542SSiarzhuk Zharski 					return ENODEV;
85*07910542SSiarzhuk Zharski 				}
86*07910542SSiarzhuk Zharski 
87*07910542SSiarzhuk Zharski 				status_t status = device->InitCheck();
88*07910542SSiarzhuk Zharski 				if (status < B_OK) {
89*07910542SSiarzhuk Zharski 					delete device;
90*07910542SSiarzhuk Zharski 					break;
91*07910542SSiarzhuk Zharski 				}
92*07910542SSiarzhuk Zharski 
93*07910542SSiarzhuk Zharski 				status = device->Setup();
94*07910542SSiarzhuk Zharski 				if (status < B_OK) {
95*07910542SSiarzhuk Zharski 					delete device;
96*07910542SSiarzhuk Zharski 					break;
97*07910542SSiarzhuk Zharski 				}
98*07910542SSiarzhuk Zharski 
99*07910542SSiarzhuk Zharski 				char name[32] = {0};
100*07910542SSiarzhuk Zharski 				sprintf(name, "audio/hmulti/%s/%ld",
101*07910542SSiarzhuk Zharski 								cardInfos[idx].Name(), gNumCards);
102*07910542SSiarzhuk Zharski 				gDeviceNames[gNumCards] = strdup(name);
103*07910542SSiarzhuk Zharski 				gDevices[gNumCards++] = device;
104*07910542SSiarzhuk Zharski 
105*07910542SSiarzhuk Zharski 				TRACE("Found:%s [%#06x:%#06x]\n", cardInfos[idx].Name(),
106*07910542SSiarzhuk Zharski 						cardInfos[idx].VendorId(), cardInfos[idx].DeviceId());
107*07910542SSiarzhuk Zharski 			}
108*07910542SSiarzhuk Zharski 		}
109*07910542SSiarzhuk Zharski 	}
110*07910542SSiarzhuk Zharski 
111*07910542SSiarzhuk Zharski 	if (gNumCards == 0) {
112*07910542SSiarzhuk Zharski 		put_module(B_PCI_MODULE_NAME);
113*07910542SSiarzhuk Zharski 		return ENODEV;
114*07910542SSiarzhuk Zharski 	}
115*07910542SSiarzhuk Zharski 
116*07910542SSiarzhuk Zharski 	return B_OK;
117*07910542SSiarzhuk Zharski }
118*07910542SSiarzhuk Zharski 
119*07910542SSiarzhuk Zharski 
120*07910542SSiarzhuk Zharski void
121*07910542SSiarzhuk Zharski uninit_driver()
122*07910542SSiarzhuk Zharski {
123*07910542SSiarzhuk Zharski 	for (size_t i = 0; i < MAX_DEVICES; i++) {
124*07910542SSiarzhuk Zharski 		if (gDevices[i]) {
125*07910542SSiarzhuk Zharski 			delete gDevices[i];
126*07910542SSiarzhuk Zharski 			gDevices[i] = NULL;
127*07910542SSiarzhuk Zharski 		}
128*07910542SSiarzhuk Zharski 
129*07910542SSiarzhuk Zharski 		free(gDeviceNames[i]);
130*07910542SSiarzhuk Zharski 		gDeviceNames[i] = NULL;
131*07910542SSiarzhuk Zharski 	}
132*07910542SSiarzhuk Zharski 
133*07910542SSiarzhuk Zharski 	put_module(B_PCI_MODULE_NAME);
134*07910542SSiarzhuk Zharski 
135*07910542SSiarzhuk Zharski 	release_settings();
136*07910542SSiarzhuk Zharski }
137*07910542SSiarzhuk Zharski 
138*07910542SSiarzhuk Zharski 
139*07910542SSiarzhuk Zharski static status_t
140*07910542SSiarzhuk Zharski SiS7018_open(const char *name, uint32 flags, void **cookie)
141*07910542SSiarzhuk Zharski {
142*07910542SSiarzhuk Zharski 	status_t status = ENODEV;
143*07910542SSiarzhuk Zharski 	*cookie = NULL;
144*07910542SSiarzhuk Zharski 	for (size_t i = 0; i < MAX_DEVICES; i++) {
145*07910542SSiarzhuk Zharski 		if (gDeviceNames[i] && !strcmp(gDeviceNames[i], name)) {
146*07910542SSiarzhuk Zharski 			status = gDevices[i]->Open(flags);
147*07910542SSiarzhuk Zharski 			*cookie = gDevices[i];
148*07910542SSiarzhuk Zharski 		}
149*07910542SSiarzhuk Zharski 	}
150*07910542SSiarzhuk Zharski 
151*07910542SSiarzhuk Zharski 	return status;
152*07910542SSiarzhuk Zharski }
153*07910542SSiarzhuk Zharski 
154*07910542SSiarzhuk Zharski 
155*07910542SSiarzhuk Zharski static status_t
156*07910542SSiarzhuk Zharski SiS7018_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
157*07910542SSiarzhuk Zharski {
158*07910542SSiarzhuk Zharski 	Device *device = (Device *)cookie;
159*07910542SSiarzhuk Zharski 	return device->Read((uint8 *)buffer, numBytes);
160*07910542SSiarzhuk Zharski }
161*07910542SSiarzhuk Zharski 
162*07910542SSiarzhuk Zharski 
163*07910542SSiarzhuk Zharski static status_t
164*07910542SSiarzhuk Zharski SiS7018_write(void *cookie, off_t position,
165*07910542SSiarzhuk Zharski 							const void *buffer, size_t *numBytes)
166*07910542SSiarzhuk Zharski {
167*07910542SSiarzhuk Zharski 	Device *device = (Device *)cookie;
168*07910542SSiarzhuk Zharski 	return device->Write((const uint8 *)buffer, numBytes);
169*07910542SSiarzhuk Zharski }
170*07910542SSiarzhuk Zharski 
171*07910542SSiarzhuk Zharski 
172*07910542SSiarzhuk Zharski static status_t
173*07910542SSiarzhuk Zharski SiS7018_control(void *cookie, uint32 op, void *buffer, size_t length)
174*07910542SSiarzhuk Zharski {
175*07910542SSiarzhuk Zharski 	Device *device = (Device *)cookie;
176*07910542SSiarzhuk Zharski 	return device->Control(op, buffer, length);
177*07910542SSiarzhuk Zharski }
178*07910542SSiarzhuk Zharski 
179*07910542SSiarzhuk Zharski 
180*07910542SSiarzhuk Zharski static status_t
181*07910542SSiarzhuk Zharski SiS7018_close(void *cookie)
182*07910542SSiarzhuk Zharski {
183*07910542SSiarzhuk Zharski 	Device *device = (Device *)cookie;
184*07910542SSiarzhuk Zharski 	return device->Close();
185*07910542SSiarzhuk Zharski }
186*07910542SSiarzhuk Zharski 
187*07910542SSiarzhuk Zharski 
188*07910542SSiarzhuk Zharski static status_t
189*07910542SSiarzhuk Zharski SiS7018_free(void *cookie)
190*07910542SSiarzhuk Zharski {
191*07910542SSiarzhuk Zharski 	Device *device = (Device *)cookie;
192*07910542SSiarzhuk Zharski 	return device->Free();
193*07910542SSiarzhuk Zharski }
194*07910542SSiarzhuk Zharski 
195*07910542SSiarzhuk Zharski 
196*07910542SSiarzhuk Zharski const char **
197*07910542SSiarzhuk Zharski publish_devices()
198*07910542SSiarzhuk Zharski {
199*07910542SSiarzhuk Zharski 	for (size_t i = 0; i < MAX_DEVICES; i++) {
200*07910542SSiarzhuk Zharski 		if (gDevices[i] == NULL)
201*07910542SSiarzhuk Zharski 			continue;
202*07910542SSiarzhuk Zharski 
203*07910542SSiarzhuk Zharski 		if (gDeviceNames[i])
204*07910542SSiarzhuk Zharski 			TRACE("%s\n", gDeviceNames[i]);
205*07910542SSiarzhuk Zharski 	}
206*07910542SSiarzhuk Zharski 
207*07910542SSiarzhuk Zharski 	return (const char **)&gDeviceNames[0];
208*07910542SSiarzhuk Zharski }
209*07910542SSiarzhuk Zharski 
210*07910542SSiarzhuk Zharski 
211*07910542SSiarzhuk Zharski device_hooks *
212*07910542SSiarzhuk Zharski find_device(const char *name)
213*07910542SSiarzhuk Zharski {
214*07910542SSiarzhuk Zharski 	static device_hooks deviceHooks = {
215*07910542SSiarzhuk Zharski 		SiS7018_open,
216*07910542SSiarzhuk Zharski 		SiS7018_close,
217*07910542SSiarzhuk Zharski 		SiS7018_free,
218*07910542SSiarzhuk Zharski 		SiS7018_control,
219*07910542SSiarzhuk Zharski 		SiS7018_read,
220*07910542SSiarzhuk Zharski 		SiS7018_write,
221*07910542SSiarzhuk Zharski 		NULL,				// select
222*07910542SSiarzhuk Zharski 		NULL				// deselect
223*07910542SSiarzhuk Zharski 	};
224*07910542SSiarzhuk Zharski 
225*07910542SSiarzhuk Zharski 	return &deviceHooks;
226*07910542SSiarzhuk Zharski }
227*07910542SSiarzhuk Zharski 
228