]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
f30c2269 | 2 | * sound/oss/opl3sa2.c |
1da177e4 LT |
3 | * |
4 | * A low level driver for Yamaha OPL3-SA2 and SA3 cards. | |
5 | * NOTE: All traces of the name OPL3-SAx have now (December 2000) been | |
6 | * removed from the driver code, as an email exchange with Yamaha | |
7 | * provided the information that the YMF-719 is indeed just a | |
8 | * re-badged 715. | |
9 | * | |
10 | * Copyright 1998-2001 Scott Murray <scott@spiteful.org> | |
11 | * | |
12 | * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen | |
13 | * and others. Now incorporates code/ideas from pss.c, also by Hannu | |
14 | * Savolainen. Both of those files are distributed with the following | |
15 | * license: | |
16 | * | |
17 | * "Copyright (C) by Hannu Savolainen 1993-1997 | |
18 | * | |
19 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) | |
20 | * Version 2 (June 1991). See the "COPYING" file distributed with this software | |
21 | * for more info." | |
22 | * | |
23 | * As such, in accordance with the above license, this file, opl3sa2.c, is | |
24 | * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991). | |
25 | * See the "COPYING" file distributed with this software for more information. | |
26 | * | |
27 | * Change History | |
28 | * -------------- | |
29 | * Scott Murray Original driver (Jun 14, 1998) | |
30 | * Paul J.Y. Lahaie Changed probing / attach code order | |
31 | * Scott Murray Added mixer support (Dec 03, 1998) | |
32 | * Scott Murray Changed detection code to be more forgiving, | |
33 | * added force option as last resort, | |
34 | * fixed ioctl return values. (Dec 30, 1998) | |
35 | * Scott Murray Simpler detection code should work all the time now | |
36 | * (with thanks to Ben Hutchings for the heuristic), | |
37 | * removed now unnecessary force option. (Jan 5, 1999) | |
38 | * Christoph Hellwig Adapted to module_init/module_exit (Mar 4, 2000) | |
39 | * Scott Murray Reworked SA2 versus SA3 mixer code, updated chipset | |
40 | * version detection code (again!). (Dec 5, 2000) | |
41 | * Scott Murray Adjusted master volume mixer scaling. (Dec 6, 2000) | |
42 | * Scott Murray Based on a patch by Joel Yliluoma (aka Bisqwit), | |
43 | * integrated wide mixer and adjusted mic, bass, treble | |
44 | * scaling. (Dec 6, 2000) | |
45 | * Scott Murray Based on a patch by Peter Englmaier, integrated | |
46 | * ymode and loopback options. (Dec 6, 2000) | |
47 | * Scott Murray Inspired by a patch by Peter Englmaier, and based on | |
48 | * what ALSA does, added initialization code for the | |
49 | * default DMA and IRQ settings. (Dec 6, 2000) | |
50 | * Scott Murray Added some more checks to the card detection code, | |
51 | * based on what ALSA does. (Dec 12, 2000) | |
52 | * Scott Murray Inspired by similar patches from John Fremlin, | |
53 | * Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4 | |
54 | * ISA PnP API support, mainly based on bits from | |
55 | * sb_card.c and awe_wave.c. (Dec 12, 2000) | |
56 | * Scott Murray Some small cleanups to the init code output. | |
57 | * (Jan 7, 2001) | |
58 | * Zwane Mwaikambo Added PM support. (Dec 4 2001) | |
59 | * | |
60 | * Adam Belay Converted driver to new PnP Layer (Oct 12, 2002) | |
61 | * Zwane Mwaikambo Code, data structure cleanups. (Feb 15 2002) | |
62 | * Zwane Mwaikambo Free resources during auxiliary device probe | |
63 | * failures (Apr 29 2002) | |
64 | * | |
65 | */ | |
66 | ||
1da177e4 LT |
67 | #include <linux/pnp.h> |
68 | #include <linux/init.h> | |
69 | #include <linux/module.h> | |
70 | #include <linux/delay.h> | |
1da177e4 LT |
71 | #include "sound_config.h" |
72 | ||
73 | #include "ad1848.h" | |
74 | #include "mpu401.h" | |
75 | ||
76 | #define OPL3SA2_MODULE_NAME "opl3sa2" | |
77 | #define PFX OPL3SA2_MODULE_NAME ": " | |
78 | ||
79 | /* Useful control port indexes: */ | |
80 | #define OPL3SA2_PM 0x01 | |
81 | #define OPL3SA2_SYS_CTRL 0x02 | |
82 | #define OPL3SA2_IRQ_CONFIG 0x03 | |
83 | #define OPL3SA2_DMA_CONFIG 0x06 | |
84 | #define OPL3SA2_MASTER_LEFT 0x07 | |
85 | #define OPL3SA2_MASTER_RIGHT 0x08 | |
86 | #define OPL3SA2_MIC 0x09 | |
87 | #define OPL3SA2_MISC 0x0A | |
88 | ||
89 | #define OPL3SA3_WIDE 0x14 | |
90 | #define OPL3SA3_BASS 0x15 | |
91 | #define OPL3SA3_TREBLE 0x16 | |
92 | ||
93 | /* Useful constants: */ | |
94 | #define DEFAULT_VOLUME 50 | |
95 | #define DEFAULT_MIC 50 | |
96 | #define DEFAULT_TIMBRE 0 | |
97 | ||
98 | /* Power saving modes */ | |
99 | #define OPL3SA2_PM_MODE0 0x00 | |
100 | #define OPL3SA2_PM_MODE1 0x04 /* PSV */ | |
101 | #define OPL3SA2_PM_MODE2 0x05 /* PSV | PDX */ | |
102 | #define OPL3SA2_PM_MODE3 0x27 /* ADOWN | PSV | PDN | PDX */ | |
103 | ||
104 | ||
105 | /* For checking against what the card returns: */ | |
106 | #define VERSION_UNKNOWN 0 | |
107 | #define VERSION_YMF711 1 | |
108 | #define VERSION_YMF715 2 | |
109 | #define VERSION_YMF715B 3 | |
110 | #define VERSION_YMF715E 4 | |
111 | /* also assuming that anything > 4 but <= 7 is a 715E */ | |
112 | ||
113 | /* Chipset type constants for use below */ | |
114 | #define CHIPSET_UNKNOWN -1 | |
115 | #define CHIPSET_OPL3SA2 0 | |
116 | #define CHIPSET_OPL3SA3 1 | |
117 | static const char *CHIPSET_TABLE[] = {"OPL3-SA2", "OPL3-SA3"}; | |
118 | ||
119 | #ifdef CONFIG_PNP | |
120 | #define OPL3SA2_CARDS_MAX 4 | |
121 | #else | |
122 | #define OPL3SA2_CARDS_MAX 1 | |
123 | #endif | |
124 | ||
125 | /* This should be pretty obvious */ | |
126 | static int opl3sa2_cards_num; | |
127 | ||
128 | typedef struct { | |
129 | /* device resources */ | |
130 | unsigned short cfg_port; | |
131 | struct address_info cfg; | |
132 | struct address_info cfg_mss; | |
133 | struct address_info cfg_mpu; | |
134 | #ifdef CONFIG_PNP | |
135 | /* PnP Stuff */ | |
136 | struct pnp_dev* pdev; | |
137 | int activated; /* Whether said devices have been activated */ | |
1da177e4 LT |
138 | #endif |
139 | unsigned int card; | |
140 | int chipset; /* What's my version(s)? */ | |
141 | char *chipset_name; | |
142 | ||
143 | /* mixer data */ | |
144 | int mixer; | |
145 | unsigned int volume_l; | |
146 | unsigned int volume_r; | |
147 | unsigned int mic; | |
148 | unsigned int bass_l; | |
149 | unsigned int bass_r; | |
150 | unsigned int treble_l; | |
151 | unsigned int treble_r; | |
152 | unsigned int wide_l; | |
153 | unsigned int wide_r; | |
154 | } opl3sa2_state_t; | |
155 | static opl3sa2_state_t opl3sa2_state[OPL3SA2_CARDS_MAX]; | |
156 | ||
157 | ||
158 | ||
159 | /* Our parameters */ | |
160 | static int __initdata io = -1; | |
161 | static int __initdata mss_io = -1; | |
162 | static int __initdata mpu_io = -1; | |
163 | static int __initdata irq = -1; | |
164 | static int __initdata dma = -1; | |
165 | static int __initdata dma2 = -1; | |
166 | static int __initdata ymode = -1; | |
167 | static int __initdata loopback = -1; | |
168 | ||
169 | #ifdef CONFIG_PNP | |
170 | /* PnP specific parameters */ | |
171 | static int __initdata isapnp = 1; | |
172 | static int __initdata multiple = 1; | |
173 | ||
174 | /* Whether said devices have been activated */ | |
175 | static int opl3sa2_activated[OPL3SA2_CARDS_MAX]; | |
176 | #else | |
177 | static int __initdata isapnp; /* = 0 */ | |
178 | static int __initdata multiple; /* = 0 */ | |
179 | #endif | |
180 | ||
181 | MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver)."); | |
182 | MODULE_AUTHOR("Scott Murray <scott@spiteful.org>"); | |
183 | MODULE_LICENSE("GPL"); | |
184 | ||
185 | ||
186 | module_param(io, int, 0); | |
187 | MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370. Address must be even and must be from 0x100 to 0xFFE)"); | |
188 | ||
189 | module_param(mss_io, int, 0); | |
190 | MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)"); | |
191 | ||
192 | module_param(mpu_io, int, 0); | |
193 | MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)"); | |
194 | ||
195 | module_param(irq, int, 0); | |
d390493b | 196 | MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)"); |
1da177e4 LT |
197 | |
198 | module_param(dma, int, 0); | |
199 | MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)"); | |
200 | ||
201 | module_param(dma2, int, 0); | |
202 | MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)"); | |
203 | ||
204 | module_param(ymode, int, 0); | |
205 | MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)"); | |
206 | ||
207 | module_param(loopback, int, 0); | |
208 | MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)"); | |
209 | ||
210 | #ifdef CONFIG_PNP | |
211 | module_param(isapnp, bool, 0); | |
212 | MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled"); | |
213 | ||
214 | module_param(multiple, bool, 0); | |
215 | MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards"); | |
216 | #endif | |
217 | ||
218 | ||
219 | /* | |
220 | * Standard read and write functions | |
221 | */ | |
222 | ||
223 | static inline void opl3sa2_write(unsigned short port, | |
224 | unsigned char index, | |
225 | unsigned char data) | |
226 | { | |
227 | outb_p(index, port); | |
228 | outb(data, port + 1); | |
229 | } | |
230 | ||
231 | ||
232 | static inline void opl3sa2_read(unsigned short port, | |
233 | unsigned char index, | |
234 | unsigned char* data) | |
235 | { | |
236 | outb_p(index, port); | |
237 | *data = inb(port + 1); | |
238 | } | |
239 | ||
240 | ||
241 | /* | |
242 | * All of the mixer functions... | |
243 | */ | |
244 | ||
245 | static void opl3sa2_set_volume(opl3sa2_state_t* devc, int left, int right) | |
246 | { | |
247 | static unsigned char scale[101] = { | |
248 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, | |
249 | 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, | |
250 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, | |
251 | 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, | |
252 | 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, | |
253 | 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, | |
254 | 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, | |
255 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, | |
256 | 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, | |
257 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
258 | 0x00 | |
259 | }; | |
260 | unsigned char vol; | |
261 | ||
262 | vol = scale[left]; | |
263 | ||
264 | /* If level is zero, turn on mute */ | |
265 | if(!left) | |
266 | vol |= 0x80; | |
267 | ||
268 | opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol); | |
269 | ||
270 | vol = scale[right]; | |
271 | ||
272 | /* If level is zero, turn on mute */ | |
273 | if(!right) | |
274 | vol |= 0x80; | |
275 | ||
276 | opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol); | |
277 | } | |
278 | ||
279 | ||
280 | static void opl3sa2_set_mic(opl3sa2_state_t* devc, int level) | |
281 | { | |
282 | unsigned char vol = 0x1F; | |
283 | ||
284 | if((level >= 0) && (level <= 100)) | |
285 | vol = 0x1F - (unsigned char) (32 * level / 101); | |
286 | ||
287 | /* If level is zero, turn on mute */ | |
288 | if(!level) | |
289 | vol |= 0x80; | |
290 | ||
291 | opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol); | |
292 | } | |
293 | ||
294 | ||
295 | static void opl3sa3_set_bass(opl3sa2_state_t* devc, int left, int right) | |
296 | { | |
297 | unsigned char bass; | |
298 | ||
299 | bass = left ? ((unsigned char) (8 * left / 101)) : 0; | |
300 | bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4; | |
301 | ||
302 | opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass); | |
303 | } | |
304 | ||
305 | ||
306 | static void opl3sa3_set_treble(opl3sa2_state_t* devc, int left, int right) | |
307 | { | |
308 | unsigned char treble; | |
309 | ||
310 | treble = left ? ((unsigned char) (8 * left / 101)) : 0; | |
311 | treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4; | |
312 | ||
313 | opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble); | |
314 | } | |
315 | ||
316 | ||
317 | ||
318 | ||
319 | static void opl3sa2_mixer_reset(opl3sa2_state_t* devc) | |
320 | { | |
321 | if (devc) { | |
322 | opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME); | |
323 | devc->volume_l = devc->volume_r = DEFAULT_VOLUME; | |
324 | ||
325 | opl3sa2_set_mic(devc, DEFAULT_MIC); | |
326 | devc->mic = DEFAULT_MIC; | |
327 | ||
328 | if (devc->chipset == CHIPSET_OPL3SA3) { | |
329 | opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE); | |
330 | devc->bass_l = devc->bass_r = DEFAULT_TIMBRE; | |
331 | opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE); | |
332 | devc->treble_l = devc->treble_r = DEFAULT_TIMBRE; | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
1da177e4 LT |
337 | static inline void arg_to_vol_mono(unsigned int vol, int* value) |
338 | { | |
339 | int left; | |
340 | ||
341 | left = vol & 0x00ff; | |
342 | if (left > 100) | |
343 | left = 100; | |
344 | *value = left; | |
345 | } | |
346 | ||
347 | ||
348 | static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright) | |
349 | { | |
350 | arg_to_vol_mono(vol, aleft); | |
351 | arg_to_vol_mono(vol >> 8, aright); | |
352 | } | |
353 | ||
354 | ||
355 | static inline int ret_vol_mono(int vol) | |
356 | { | |
357 | return ((vol << 8) | vol); | |
358 | } | |
359 | ||
360 | ||
361 | static inline int ret_vol_stereo(int left, int right) | |
362 | { | |
363 | return ((right << 8) | left); | |
364 | } | |
365 | ||
366 | ||
367 | static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) | |
368 | { | |
369 | int retval, value, cmdf = cmd & 0xff; | |
370 | int __user *p = (int __user *)arg; | |
371 | ||
372 | opl3sa2_state_t* devc = &opl3sa2_state[dev]; | |
373 | ||
374 | switch (cmdf) { | |
375 | case SOUND_MIXER_VOLUME: | |
376 | case SOUND_MIXER_MIC: | |
377 | case SOUND_MIXER_DEVMASK: | |
378 | case SOUND_MIXER_STEREODEVS: | |
379 | case SOUND_MIXER_RECMASK: | |
380 | case SOUND_MIXER_RECSRC: | |
381 | case SOUND_MIXER_CAPS: | |
382 | break; | |
383 | ||
384 | default: | |
385 | return -EINVAL; | |
386 | } | |
387 | ||
388 | if (((cmd >> 8) & 0xff) != 'M') | |
389 | return -EINVAL; | |
390 | ||
391 | retval = 0; | |
392 | if (_SIOC_DIR (cmd) & _SIOC_WRITE) { | |
393 | switch (cmdf) { | |
394 | case SOUND_MIXER_VOLUME: | |
395 | retval = get_user(value, (unsigned __user *) arg); | |
396 | if (retval) | |
397 | break; | |
398 | arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r); | |
399 | opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r); | |
400 | value = ret_vol_stereo(devc->volume_l, devc->volume_r); | |
401 | retval = put_user(value, p); | |
402 | break; | |
403 | ||
404 | case SOUND_MIXER_MIC: | |
405 | retval = get_user(value, (unsigned __user *) arg); | |
406 | if (retval) | |
407 | break; | |
408 | arg_to_vol_mono(value, &devc->mic); | |
409 | opl3sa2_set_mic(devc, devc->mic); | |
410 | value = ret_vol_mono(devc->mic); | |
411 | retval = put_user(value, p); | |
412 | break; | |
413 | ||
414 | default: | |
415 | retval = -EINVAL; | |
416 | } | |
417 | } | |
418 | else { | |
419 | /* | |
420 | * Return parameters | |
421 | */ | |
422 | switch (cmdf) { | |
423 | case SOUND_MIXER_DEVMASK: | |
424 | retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, p); | |
425 | break; | |
426 | ||
427 | case SOUND_MIXER_STEREODEVS: | |
428 | retval = put_user(SOUND_MASK_VOLUME, p); | |
429 | break; | |
430 | ||
431 | case SOUND_MIXER_RECMASK: | |
432 | /* No recording devices */ | |
433 | retval = put_user(0, p); | |
434 | break; | |
435 | ||
436 | case SOUND_MIXER_CAPS: | |
437 | retval = put_user(SOUND_CAP_EXCL_INPUT, p); | |
438 | break; | |
439 | ||
440 | case SOUND_MIXER_RECSRC: | |
441 | /* No recording source */ | |
442 | retval = put_user(0, p); | |
443 | break; | |
444 | ||
445 | case SOUND_MIXER_VOLUME: | |
446 | value = ret_vol_stereo(devc->volume_l, devc->volume_r); | |
447 | retval = put_user(value, p); | |
448 | break; | |
449 | ||
450 | case SOUND_MIXER_MIC: | |
451 | value = ret_vol_mono(devc->mic); | |
452 | put_user(value, p); | |
453 | break; | |
454 | ||
455 | default: | |
456 | retval = -EINVAL; | |
457 | } | |
458 | } | |
459 | return retval; | |
460 | } | |
461 | /* opl3sa2_mixer_ioctl end */ | |
462 | ||
463 | ||
464 | static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) | |
465 | { | |
466 | int value, retval, cmdf = cmd & 0xff; | |
467 | ||
468 | opl3sa2_state_t* devc = &opl3sa2_state[dev]; | |
469 | ||
470 | switch (cmdf) { | |
471 | case SOUND_MIXER_BASS: | |
472 | value = ret_vol_stereo(devc->bass_l, devc->bass_r); | |
473 | retval = put_user(value, (int __user *) arg); | |
474 | break; | |
475 | ||
476 | case SOUND_MIXER_TREBLE: | |
477 | value = ret_vol_stereo(devc->treble_l, devc->treble_r); | |
478 | retval = put_user(value, (int __user *) arg); | |
479 | break; | |
480 | ||
481 | case SOUND_MIXER_DIGITAL1: | |
482 | value = ret_vol_stereo(devc->wide_l, devc->wide_r); | |
483 | retval = put_user(value, (int __user *) arg); | |
484 | break; | |
485 | ||
486 | default: | |
487 | retval = -EINVAL; | |
488 | } | |
489 | return retval; | |
490 | } | |
491 | /* opl3sa3_mixer_ioctl end */ | |
492 | ||
493 | ||
494 | static struct mixer_operations opl3sa2_mixer_operations = | |
495 | { | |
496 | .owner = THIS_MODULE, | |
497 | .id = "OPL3-SA2", | |
498 | .name = "Yamaha OPL3-SA2", | |
499 | .ioctl = opl3sa2_mixer_ioctl | |
500 | }; | |
501 | ||
502 | static struct mixer_operations opl3sa3_mixer_operations = | |
503 | { | |
504 | .owner = THIS_MODULE, | |
505 | .id = "OPL3-SA3", | |
506 | .name = "Yamaha OPL3-SA3", | |
507 | .ioctl = opl3sa3_mixer_ioctl | |
508 | }; | |
509 | ||
510 | /* End of mixer-related stuff */ | |
511 | ||
512 | ||
513 | /* | |
514 | * Component probe, attach, unload functions | |
515 | */ | |
516 | ||
517 | static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config) | |
518 | { | |
519 | unload_mpu401(hw_config); | |
520 | } | |
521 | ||
522 | ||
523 | static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports) | |
524 | { | |
525 | int initial_mixers; | |
526 | ||
527 | initial_mixers = num_mixers; | |
528 | attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */ | |
529 | if (hw_config->slots[0] != -1) { | |
530 | /* Did the MSS driver install? */ | |
531 | if(num_mixers == (initial_mixers + 1)) { | |
575c9687 | 532 | /* The MSS mixer is installed, reroute mixers appropriately */ |
1da177e4 LT |
533 | AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); |
534 | AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); | |
535 | AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); | |
536 | } | |
537 | else { | |
538 | printk(KERN_ERR PFX "MSS mixer not installed?\n"); | |
539 | } | |
540 | } | |
541 | } | |
542 | ||
543 | ||
544 | static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config) | |
545 | { | |
546 | unload_ms_sound(hw_config); | |
547 | } | |
548 | ||
549 | ||
550 | static int __init probe_opl3sa2(struct address_info* hw_config, int card) | |
551 | { | |
552 | unsigned char misc; | |
553 | unsigned char tmp; | |
554 | unsigned char version; | |
555 | ||
556 | /* | |
557 | * Try and allocate our I/O port range. | |
558 | */ | |
559 | if (!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) { | |
560 | printk(KERN_ERR PFX "Control I/O port %#x not free\n", | |
561 | hw_config->io_base); | |
562 | goto out_nodev; | |
563 | } | |
564 | ||
565 | /* | |
566 | * Check if writing to the read-only version bits of the miscellaneous | |
567 | * register succeeds or not (it should not). | |
568 | */ | |
569 | opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc); | |
570 | opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07); | |
571 | opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp); | |
572 | if(tmp != misc) { | |
573 | printk(KERN_ERR PFX "Control I/O port %#x is not a YMF7xx chipset!\n", | |
574 | hw_config->io_base); | |
575 | goto out_region; | |
576 | } | |
577 | ||
578 | /* | |
579 | * Check if the MIC register is accessible. | |
580 | */ | |
581 | opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp); | |
582 | opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a); | |
583 | opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp); | |
584 | if((tmp & 0x9f) != 0x8a) { | |
585 | printk(KERN_ERR | |
586 | PFX "Control I/O port %#x is not a YMF7xx chipset!\n", | |
587 | hw_config->io_base); | |
588 | goto out_region; | |
589 | } | |
590 | opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp); | |
591 | ||
592 | /* | |
593 | * Determine chipset type (SA2 or SA3) | |
594 | * | |
595 | * This is done by looking at the chipset version in the lower 3 bits | |
596 | * of the miscellaneous register. | |
597 | */ | |
598 | version = misc & 0x07; | |
599 | printk(KERN_DEBUG PFX "Chipset version = %#x\n", version); | |
600 | switch (version) { | |
601 | case 0: | |
602 | opl3sa2_state[card].chipset = CHIPSET_UNKNOWN; | |
603 | printk(KERN_ERR | |
604 | PFX "Unknown Yamaha audio controller version\n"); | |
605 | break; | |
606 | ||
607 | case VERSION_YMF711: | |
608 | opl3sa2_state[card].chipset = CHIPSET_OPL3SA2; | |
609 | printk(KERN_INFO PFX "Found OPL3-SA2 (YMF711)\n"); | |
610 | break; | |
611 | ||
612 | case VERSION_YMF715: | |
613 | opl3sa2_state[card].chipset = CHIPSET_OPL3SA3; | |
614 | printk(KERN_INFO | |
615 | PFX "Found OPL3-SA3 (YMF715 or YMF719)\n"); | |
616 | break; | |
617 | ||
618 | case VERSION_YMF715B: | |
619 | opl3sa2_state[card].chipset = CHIPSET_OPL3SA3; | |
620 | printk(KERN_INFO | |
621 | PFX "Found OPL3-SA3 (YMF715B or YMF719B)\n"); | |
622 | break; | |
623 | ||
624 | case VERSION_YMF715E: | |
625 | default: | |
626 | opl3sa2_state[card].chipset = CHIPSET_OPL3SA3; | |
627 | printk(KERN_INFO | |
628 | PFX "Found OPL3-SA3 (YMF715E or YMF719E)\n"); | |
629 | break; | |
630 | } | |
631 | ||
632 | if (opl3sa2_state[card].chipset != CHIPSET_UNKNOWN) { | |
633 | /* Generate a pretty name */ | |
634 | opl3sa2_state[card].chipset_name = (char *)CHIPSET_TABLE[opl3sa2_state[card].chipset]; | |
635 | return 0; | |
636 | } | |
637 | ||
638 | out_region: | |
639 | release_region(hw_config->io_base, 2); | |
640 | out_nodev: | |
641 | return -ENODEV; | |
642 | } | |
643 | ||
644 | ||
645 | static void __init attach_opl3sa2(struct address_info* hw_config, int card) | |
646 | { | |
647 | /* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */ | |
648 | opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d); | |
649 | ||
650 | /* Initialize DMA configuration */ | |
651 | if(hw_config->dma2 == hw_config->dma) { | |
652 | /* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */ | |
653 | opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03); | |
654 | } | |
655 | else { | |
656 | /* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */ | |
657 | opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21); | |
658 | } | |
659 | } | |
660 | ||
661 | ||
662 | static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card) | |
663 | { | |
664 | struct mixer_operations* mixer_operations; | |
665 | opl3sa2_state_t* devc = &opl3sa2_state[card]; | |
666 | ||
667 | /* Install master mixer */ | |
668 | if (devc->chipset == CHIPSET_OPL3SA3) { | |
669 | mixer_operations = &opl3sa3_mixer_operations; | |
670 | } | |
671 | else { | |
672 | mixer_operations = &opl3sa2_mixer_operations; | |
673 | } | |
674 | ||
675 | devc->cfg_port = hw_config->io_base; | |
676 | devc->mixer = sound_install_mixer(MIXER_DRIVER_VERSION, | |
677 | mixer_operations->name, | |
678 | mixer_operations, | |
679 | sizeof(struct mixer_operations), | |
680 | devc); | |
681 | if(devc->mixer < 0) { | |
682 | printk(KERN_ERR PFX "Could not install %s master mixer\n", | |
683 | mixer_operations->name); | |
684 | } | |
685 | else { | |
686 | opl3sa2_mixer_reset(devc); | |
687 | ||
688 | } | |
689 | } | |
690 | ||
691 | ||
692 | static void opl3sa2_clear_slots(struct address_info* hw_config) | |
693 | { | |
694 | int i; | |
695 | ||
696 | for(i = 0; i < 6; i++) { | |
697 | hw_config->slots[i] = -1; | |
698 | } | |
699 | } | |
700 | ||
701 | ||
702 | static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode) | |
703 | { | |
704 | /* | |
705 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and | |
706 | * it's supported. | |
707 | * | |
708 | * 0: Desktop (aka normal) 5-12 cm speakers | |
709 | * 1: Notebook PC mode 1 3 cm speakers | |
710 | * 2: Notebook PC mode 2 1.5 cm speakers | |
711 | * 3: Hi-fi 16-38 cm speakers | |
712 | */ | |
713 | if(ymode >= 0 && ymode <= 3) { | |
714 | unsigned char sys_ctrl; | |
715 | ||
716 | opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl); | |
717 | sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4); | |
718 | opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl); | |
719 | } | |
720 | else { | |
721 | printk(KERN_ERR PFX "not setting ymode, it must be one of 0,1,2,3\n"); | |
722 | } | |
723 | } | |
724 | ||
725 | ||
726 | static void __init opl3sa2_set_loopback(struct address_info* hw_config, int loopback) | |
727 | { | |
728 | if(loopback >= 0 && loopback <= 1) { | |
729 | unsigned char misc; | |
730 | ||
731 | opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc); | |
732 | misc = (misc & 0xef) | ((loopback & 1) << 4); | |
733 | opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc); | |
734 | } | |
735 | else { | |
736 | printk(KERN_ERR PFX "not setting loopback, it must be either 0 or 1\n"); | |
737 | } | |
738 | } | |
739 | ||
740 | ||
741 | static void __exit unload_opl3sa2(struct address_info* hw_config, int card) | |
742 | { | |
743 | /* Release control ports */ | |
744 | release_region(hw_config->io_base, 2); | |
745 | ||
746 | /* Unload mixer */ | |
747 | if(opl3sa2_state[card].mixer >= 0) | |
748 | sound_unload_mixerdev(opl3sa2_state[card].mixer); | |
749 | ||
750 | } | |
751 | ||
752 | #ifdef CONFIG_PNP | |
753 | static struct pnp_device_id pnp_opl3sa2_list[] = { | |
754 | {.id = "YMH0021", .driver_data = 0}, | |
755 | {.id = ""} | |
756 | }; | |
757 | ||
758 | MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list); | |
759 | ||
760 | static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | |
761 | { | |
762 | int card = opl3sa2_cards_num; | |
763 | ||
764 | /* we don't actually want to return an error as the user may have specified | |
765 | * no multiple card search | |
766 | */ | |
767 | ||
768 | if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX) | |
769 | return 0; | |
770 | opl3sa2_activated[card] = 1; | |
771 | ||
772 | /* Our own config: */ | |
773 | opl3sa2_state[card].cfg.io_base = pnp_port_start(dev, 4); | |
774 | opl3sa2_state[card].cfg.irq = pnp_irq(dev, 0); | |
775 | opl3sa2_state[card].cfg.dma = pnp_dma(dev, 0); | |
776 | opl3sa2_state[card].cfg.dma2 = pnp_dma(dev, 1); | |
777 | ||
778 | /* The MSS config: */ | |
779 | opl3sa2_state[card].cfg_mss.io_base = pnp_port_start(dev, 1); | |
780 | opl3sa2_state[card].cfg_mss.irq = pnp_irq(dev, 0); | |
781 | opl3sa2_state[card].cfg_mss.dma = pnp_dma(dev, 0); | |
782 | opl3sa2_state[card].cfg_mss.dma2 = pnp_dma(dev, 1); | |
783 | opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */ | |
784 | ||
785 | opl3sa2_state[card].cfg_mpu.io_base = pnp_port_start(dev, 3); | |
786 | opl3sa2_state[card].cfg_mpu.irq = pnp_irq(dev, 0); | |
787 | opl3sa2_state[card].cfg_mpu.dma = -1; | |
788 | opl3sa2_state[card].cfg_mpu.dma2 = -1; | |
789 | opl3sa2_state[card].cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */ | |
790 | ||
791 | /* Call me paranoid: */ | |
792 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg); | |
793 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss); | |
794 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu); | |
795 | ||
796 | opl3sa2_state[card].pdev = dev; | |
797 | opl3sa2_cards_num++; | |
798 | ||
799 | return 0; | |
800 | } | |
801 | ||
802 | static struct pnp_driver opl3sa2_driver = { | |
803 | .name = "opl3sa2", | |
804 | .id_table = pnp_opl3sa2_list, | |
805 | .probe = opl3sa2_pnp_probe, | |
806 | }; | |
807 | ||
808 | #endif /* CONFIG_PNP */ | |
809 | ||
810 | /* End of component functions */ | |
811 | ||
1da177e4 LT |
812 | /* |
813 | * Install OPL3-SA2 based card(s). | |
814 | * | |
815 | * Need to have ad1848 and mpu401 loaded ready. | |
816 | */ | |
817 | static int __init init_opl3sa2(void) | |
818 | { | |
819 | int card, max; | |
820 | ||
821 | /* Sanitize isapnp and multiple settings */ | |
822 | isapnp = isapnp != 0 ? 1 : 0; | |
823 | multiple = multiple != 0 ? 1 : 0; | |
824 | ||
825 | max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1; | |
826 | ||
827 | #ifdef CONFIG_PNP | |
828 | if (isapnp){ | |
829 | pnp_register_driver(&opl3sa2_driver); | |
830 | if(!opl3sa2_cards_num){ | |
831 | printk(KERN_INFO PFX "No PnP cards found\n"); | |
832 | isapnp = 0; | |
833 | } | |
834 | max = opl3sa2_cards_num; | |
835 | } | |
836 | #endif | |
837 | ||
838 | for (card = 0; card < max; card++) { | |
839 | /* If a user wants an I/O then assume they meant it */ | |
840 | struct resource *ports; | |
841 | int base; | |
842 | ||
843 | if (!isapnp) { | |
844 | if (io == -1 || irq == -1 || dma == -1 || | |
845 | dma2 == -1 || mss_io == -1) { | |
846 | printk(KERN_ERR | |
847 | PFX "io, mss_io, irq, dma, and dma2 must be set\n"); | |
848 | return -EINVAL; | |
849 | } | |
850 | opl3sa2_cards_num++; | |
851 | ||
852 | /* | |
853 | * Our own config: | |
854 | * (NOTE: IRQ and DMA aren't used, so they're set to | |
855 | * give pretty output from conf_printf. :) | |
856 | */ | |
857 | opl3sa2_state[card].cfg.io_base = io; | |
858 | opl3sa2_state[card].cfg.irq = irq; | |
859 | opl3sa2_state[card].cfg.dma = dma; | |
860 | opl3sa2_state[card].cfg.dma2 = dma2; | |
861 | ||
862 | /* The MSS config: */ | |
863 | opl3sa2_state[card].cfg_mss.io_base = mss_io; | |
864 | opl3sa2_state[card].cfg_mss.irq = irq; | |
865 | opl3sa2_state[card].cfg_mss.dma = dma; | |
866 | opl3sa2_state[card].cfg_mss.dma2 = dma2; | |
867 | opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */ | |
868 | ||
869 | opl3sa2_state[card].cfg_mpu.io_base = mpu_io; | |
870 | opl3sa2_state[card].cfg_mpu.irq = irq; | |
871 | opl3sa2_state[card].cfg_mpu.dma = -1; | |
872 | opl3sa2_state[card].cfg_mpu.always_detect = 1; /* Use shared IRQs */ | |
873 | ||
874 | /* Call me paranoid: */ | |
875 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg); | |
876 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss); | |
877 | opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu); | |
878 | } | |
879 | ||
880 | /* FIXME: leak */ | |
881 | if (probe_opl3sa2(&opl3sa2_state[card].cfg, card)) | |
882 | return -ENODEV; | |
883 | ||
884 | base = opl3sa2_state[card].cfg_mss.io_base; | |
885 | ||
886 | if (!request_region(base, 4, "WSS config")) | |
887 | goto failed; | |
888 | ||
889 | ports = request_region(base + 4, 4, "ad1848"); | |
890 | if (!ports) | |
891 | goto failed2; | |
892 | ||
893 | if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) { | |
894 | /* | |
895 | * If one or more cards are already registered, don't | |
896 | * return an error but print a warning. Note, this | |
897 | * should never really happen unless the hardware or | |
898 | * ISA PnP screwed up. | |
899 | */ | |
900 | release_region(base + 4, 4); | |
901 | failed2: | |
902 | release_region(base, 4); | |
903 | failed: | |
904 | release_region(opl3sa2_state[card].cfg.io_base, 2); | |
905 | ||
906 | if (opl3sa2_cards_num) { | |
907 | printk(KERN_WARNING | |
908 | PFX "There was a problem probing one " | |
909 | " of the ISA PNP cards, continuing\n"); | |
910 | opl3sa2_cards_num--; | |
911 | continue; | |
912 | } else | |
913 | return -ENODEV; | |
914 | } | |
915 | ||
916 | attach_opl3sa2(&opl3sa2_state[card].cfg, card); | |
917 | conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg); | |
918 | attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card); | |
919 | attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports); | |
920 | ||
921 | /* ewww =) */ | |
922 | opl3sa2_state[card].card = card; | |
1da177e4 LT |
923 | |
924 | /* | |
925 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and | |
926 | * it's supported. | |
927 | */ | |
928 | if (ymode != -1) { | |
929 | if (opl3sa2_state[card].chipset == CHIPSET_OPL3SA2) { | |
930 | printk(KERN_ERR | |
931 | PFX "ymode not supported on OPL3-SA2\n"); | |
932 | } | |
933 | else { | |
934 | opl3sa2_set_ymode(&opl3sa2_state[card].cfg, ymode); | |
935 | } | |
936 | } | |
937 | ||
938 | ||
939 | /* Set A/D input to Mono loopback if asked to. */ | |
940 | if (loopback != -1) { | |
941 | opl3sa2_set_loopback(&opl3sa2_state[card].cfg, loopback); | |
942 | } | |
943 | ||
944 | /* Attach MPU if we've been asked to do so, failure isn't fatal */ | |
945 | if (opl3sa2_state[card].cfg_mpu.io_base != -1) { | |
946 | int base = opl3sa2_state[card].cfg_mpu.io_base; | |
947 | struct resource *ports; | |
948 | ports = request_region(base, 2, "mpu401"); | |
949 | if (!ports) | |
950 | goto out; | |
951 | if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) { | |
952 | release_region(base, 2); | |
953 | goto out; | |
954 | } | |
955 | if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) { | |
956 | printk(KERN_ERR PFX "failed to attach MPU401\n"); | |
957 | opl3sa2_state[card].cfg_mpu.slots[1] = -1; | |
958 | } | |
959 | } | |
960 | } | |
961 | ||
962 | out: | |
963 | if (isapnp) { | |
964 | printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num); | |
965 | } | |
966 | ||
967 | return 0; | |
968 | } | |
969 | ||
970 | ||
971 | /* | |
972 | * Uninstall OPL3-SA2 based card(s). | |
973 | */ | |
974 | static void __exit cleanup_opl3sa2(void) | |
975 | { | |
976 | int card; | |
977 | ||
978 | for(card = 0; card < opl3sa2_cards_num; card++) { | |
1da177e4 LT |
979 | if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) { |
980 | unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu); | |
981 | } | |
982 | unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss); | |
983 | unload_opl3sa2(&opl3sa2_state[card].cfg, card); | |
984 | #ifdef CONFIG_PNP | |
985 | pnp_unregister_driver(&opl3sa2_driver); | |
986 | #endif | |
987 | } | |
988 | } | |
989 | ||
990 | module_init(init_opl3sa2); | |
991 | module_exit(cleanup_opl3sa2); | |
992 | ||
993 | #ifndef MODULE | |
994 | static int __init setup_opl3sa2(char *str) | |
995 | { | |
996 | /* io, irq, dma, dma2,... */ | |
997 | #ifdef CONFIG_PNP | |
998 | int ints[11]; | |
999 | #else | |
1000 | int ints[9]; | |
1001 | #endif | |
1002 | str = get_options(str, ARRAY_SIZE(ints), ints); | |
1003 | ||
1004 | io = ints[1]; | |
1005 | irq = ints[2]; | |
1006 | dma = ints[3]; | |
1007 | dma2 = ints[4]; | |
1008 | mss_io = ints[5]; | |
1009 | mpu_io = ints[6]; | |
1010 | ymode = ints[7]; | |
1011 | loopback = ints[8]; | |
1012 | #ifdef CONFIG_PNP | |
1013 | isapnp = ints[9]; | |
1014 | multiple = ints[10]; | |
1015 | #endif | |
1016 | return 1; | |
1017 | } | |
1018 | ||
1019 | __setup("opl3sa2=", setup_opl3sa2); | |
1020 | #endif |