Import changeset
[linux-flexiantxendom0-3.2.10.git] / drivers / sound / opl3sa2.c
1 /*
2  * sound/opl3sa2.c
3  *
4  * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
5  * SAx cards should work, as they are just variants of the SA3.
6  *
7  * Copyright 1998, 1999 Scott Murray <scottm@interlog.com>
8  *
9  * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
10  * and others.  Now incorporates code/ideas from pss.c, also by Hannu
11  * Savolainen.  Both of those files are distributed with the following
12  * license:
13  *
14  * "Copyright (C) by Hannu Savolainen 1993-1997
15  *
16  *  OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
17  *  Version 2 (June 1991). See the "COPYING" file distributed with this software
18  *  for more info."
19  *
20  * As such, in accordance with the above license, this file, opl3sa2.c, is
21  * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
22  * See the "COPYING" file distributed with this software for more information.
23  *
24  * Change History
25  * --------------
26  * Scott Murray            Original driver (Jun 14, 1998)
27  * Paul J.Y. Lahaie        Changed probing / attach code order
28  * Scott Murray            Added mixer support (Dec 03, 1998)
29  * Scott Murray            Changed detection code to be more forgiving,
30  *                         added force option as last resort,
31  *                         fixed ioctl return values. (Dec 30, 1998)
32  * Scott Murray            Simpler detection code should work all the time now
33  *                         (with thanks to Ben Hutchings for the heuristic),
34  *                         removed now unnecessary force option. (Jan 5, 1999)
35  * Christoph Hellwig       Adapted to module_init/module_exit (Mar 4, 2000)
36  *
37  */
38
39 #include <linux/config.h>
40 #include <linux/init.h>
41 #include <linux/module.h>
42
43 #include "sound_config.h"
44
45 #include "ad1848.h"
46 #include "mpu401.h"
47
48 /* Useful control port indexes: */
49 #define OPL3SA2_MASTER_LEFT  0x07
50 #define OPL3SA2_MASTER_RIGHT 0x08
51 #define OPL3SA2_MIC          0x09
52 #define OPL3SA2_MISC         0x0A
53
54 #define OPL3SA3_WIDE         0x14
55 #define OPL3SA3_BASS         0x15
56 #define OPL3SA3_TREBLE       0x16
57
58 /* Useful constants: */
59 #define DEFAULT_VOLUME 50
60 #define DEFAULT_MIC    50
61 #define DEFAULT_TIMBRE 0
62
63 #define CHIPSET_UNKNOWN -1
64
65 /*
66  * These are used both as masks against what the card returns,
67  * and as constants.
68  */
69 #define CHIPSET_OPL3SA2  1
70 #define CHIPSET_OPL3SA3  2
71 #define CHIPSET_OPL3SAX  4
72
73
74 /* What's my version? */
75 static int chipset = CHIPSET_UNKNOWN;
76
77 /* Oh well, let's just cache the name */
78 static char chipset_name[16];
79
80 /* Where's my mixer */
81 static int opl3sa2_mixer = -1;
82
83 /* Bag o' mixer data */
84 typedef struct opl3sa2_mixerdata {
85         unsigned short cfg_port;
86         unsigned short padding;
87         int            ad_mixer_dev;
88         unsigned int   volume_l;
89         unsigned int   volume_r;
90         unsigned int   mic;
91         unsigned int   bass;
92         unsigned int   treble;
93 } opl3sa2_mixerdata;
94
95 #ifdef CONFIG_OPL3SA2_CTRL_BASE
96 /* Set control port if compiled into the kernel */
97 static opl3sa2_mixerdata opl3sa2_data = { CONFIG_OPL3SA2_CTRL_BASE, };
98 #else
99 static opl3sa2_mixerdata opl3sa2_data;
100 #endif
101
102 static opl3sa2_mixerdata *devc = &opl3sa2_data;
103
104
105 /* Standard read and write functions */
106
107 static void opl3sa2_write(unsigned short port,
108                           unsigned char  index,
109                           unsigned char  data)
110 {
111         outb_p(index, port);
112         outb(data, port + 1);
113 }
114
115
116 static void opl3sa2_read(unsigned short port,
117                          unsigned char  index,
118                          unsigned char* data)
119 {
120         outb_p(index, port);
121         *data = inb(port + 1);
122 }
123
124
125 /* All of the mixer functions... */
126
127 static void opl3sa2_set_volume(opl3sa2_mixerdata *devc, int left, int right)
128 {
129         static unsigned char scale[101] = {
130                 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 
131                 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 
132                 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 
133                 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 
134                 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 
135                 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
136                 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 
137                 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
138                 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 
139                 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
140                 0x00
141         };
142         unsigned char vol;
143
144         vol = scale[left];
145
146         /* If level is zero, turn on mute */
147         if(!left)
148                 vol |= 0x80;
149
150         opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
151
152         vol = scale[right];
153
154         /* If level is zero, turn on mute */
155         if(!right)
156                 vol |= 0x80;
157
158         opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
159 }
160
161
162 static void opl3sa2_set_mic(opl3sa2_mixerdata *devc, int level)
163 {
164         unsigned char vol = 0x1F;
165
166         if((level >= 0) && (level <= 100))
167                 vol = 0x1F - (unsigned char) (0x1F * level / 100L);
168
169         /* If level is zero, turn on mute */
170         if(!level)
171                 vol |= 0x80;
172
173         opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
174 }
175
176
177 static void opl3sa3_set_bass(opl3sa2_mixerdata *devc, int level)
178 {
179         unsigned char bass;
180
181         bass = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
182         bass |= (bass << 4);
183
184         opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
185 }
186
187
188 static void opl3sa3_set_treble(opl3sa2_mixerdata *devc, int level)
189 {       
190         unsigned char treble;
191
192         treble = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
193         treble |= (treble << 4);
194
195         opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
196 }
197
198
199 static void opl3sa2_mixer_reset(opl3sa2_mixerdata *devc)
200 {
201         if(devc)
202         {
203                 opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
204                 devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
205
206                 opl3sa2_set_mic(devc, DEFAULT_MIC);
207                 devc->mic = DEFAULT_MIC;
208
209                 opl3sa3_set_bass(devc, DEFAULT_TIMBRE);
210                 opl3sa3_set_treble(devc, DEFAULT_TIMBRE);
211                 devc->bass = devc->treble = DEFAULT_TIMBRE;
212         }
213 }
214
215
216 static void arg_to_volume_mono(unsigned int volume, int *aleft)
217 {
218         int left;
219         
220         left = volume & 0x00ff;
221         if (left > 100)
222                 left = 100;
223         *aleft = left;
224 }
225
226
227 static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
228 {
229         arg_to_volume_mono(volume, aleft);
230         arg_to_volume_mono(volume >> 8, aright);
231 }
232
233
234 static int ret_vol_mono(int left)
235 {
236         return ((left << 8) | left);
237 }
238
239
240 static int ret_vol_stereo(int left, int right)
241 {
242         return ((right << 8) | left);
243 }
244
245
246 static int call_ad_mixer(opl3sa2_mixerdata *devc, unsigned int cmd, caddr_t arg)
247 {
248         if(devc->ad_mixer_dev != -1) 
249                 return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev,
250                                                              cmd,
251                                                              arg);
252         else 
253                 return -EINVAL;
254 }
255
256
257 static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
258 {
259         int cmdf = cmd & 0xff;
260
261         opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
262         
263         switch(cmdf)
264         {
265                 case SOUND_MIXER_VOLUME:
266                 case SOUND_MIXER_MIC:
267                 case SOUND_MIXER_BASS:
268                 case SOUND_MIXER_TREBLE:
269                 case SOUND_MIXER_DEVMASK:
270                 case SOUND_MIXER_STEREODEVS: 
271                 case SOUND_MIXER_RECMASK:
272                 case SOUND_MIXER_CAPS: 
273                 case SOUND_MIXER_RECSRC:
274                         break;
275
276                 default:
277                         return call_ad_mixer(devc, cmd, arg);
278         }
279         
280         if(((cmd >> 8) & 0xff) != 'M')
281                 return -EINVAL;
282                 
283         if(_SIOC_DIR (cmd) & _SIOC_WRITE)
284         {
285                 switch (cmdf)   
286                 {
287                         case SOUND_MIXER_RECSRC:
288                                 if(devc->ad_mixer_dev != -1)
289                                         return call_ad_mixer(devc, cmd, arg);
290                                 else
291                                 {
292                                         if(*(int*)arg != 0)
293                                                 return -EINVAL;
294                                         return 0;
295                                 }
296
297                         case SOUND_MIXER_VOLUME:
298                                 arg_to_volume_stereo(*(unsigned int*)arg,
299                                                      &devc->volume_l,
300                                                      &devc->volume_r); 
301                                 opl3sa2_set_volume(devc, devc->volume_l,
302                                                    devc->volume_r);
303                                 *(int*)arg = ret_vol_stereo(devc->volume_l,
304                                                              devc->volume_r);
305                                 return 0;
306                   
307                         case SOUND_MIXER_MIC:
308                                 arg_to_volume_mono(*(unsigned int*)arg,
309                                                    &devc->mic);
310                                 opl3sa2_set_mic(devc, devc->mic);
311                                 *(int*)arg = ret_vol_mono(devc->mic);
312                                 return 0;
313                   
314                         case SOUND_MIXER_BASS:
315                                 if(chipset != CHIPSET_OPL3SA2)
316                                 {
317                                         arg_to_volume_mono(*(unsigned int*)arg,
318                                                            &devc->bass);
319                                         opl3sa3_set_bass(devc, devc->bass);
320                                         *(int*)arg = ret_vol_mono(devc->bass);
321                                         return 0;
322                                 }
323                                 return -EINVAL;
324                   
325                         case SOUND_MIXER_TREBLE:
326                                 if(chipset != CHIPSET_OPL3SA2)
327                                 {
328                                         arg_to_volume_mono(*(unsigned int *)arg,
329                                                            &devc->treble);
330                                         opl3sa3_set_treble(devc, devc->treble);
331                                         *(int*)arg = ret_vol_mono(devc->treble);
332                                         return 0;
333                                 }
334                                 return -EINVAL;
335                   
336                         default:
337                                 return -EINVAL;
338                 }
339         }
340         else                    
341         {
342                 /*
343                  * Return parameters
344                  */
345                 switch (cmdf)
346                 {
347                         case SOUND_MIXER_DEVMASK:
348                                 if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
349                                         *(int*)arg = 0; /* no mixer devices */
350
351                                 *(int*)arg |= (SOUND_MASK_VOLUME | SOUND_MASK_MIC);
352
353                                 /* OPL3-SA2 has no bass and treble mixers */
354                                 if(chipset != CHIPSET_OPL3SA2)
355                                         *(int*)arg |= (SOUND_MASK_BASS |
356                                                        SOUND_MASK_TREBLE);
357                                 return 0;
358                   
359                         case SOUND_MIXER_STEREODEVS:
360                                 if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
361                                         *(int*)arg = 0; /* no stereo devices */
362                                 *(int*)arg |= SOUND_MASK_VOLUME;
363                                 return 0;
364                   
365                         case SOUND_MIXER_RECMASK:
366                                 if(devc->ad_mixer_dev != -1)
367                                 {
368                                         return call_ad_mixer(devc, cmd, arg);
369                                 }
370                                 else
371                                 {
372                                         /* No recording devices */
373                                         return (*(int*)arg = 0);
374                                 }
375
376                         case SOUND_MIXER_CAPS:
377                                 if(devc->ad_mixer_dev != -1)
378                                 {
379                                         return call_ad_mixer(devc, cmd, arg);
380                                 }
381                                 else
382                                 {
383                                         *(int*)arg = SOUND_CAP_EXCL_INPUT;
384                                         return 0;
385                                 }
386
387                         case SOUND_MIXER_RECSRC:
388                                 if(devc->ad_mixer_dev != -1)
389                                 {
390                                         return call_ad_mixer(devc, cmd, arg);
391                                 }
392                                 else
393                                 {
394                                         /* No recording source */
395                                         return (*(int*)arg = 0);
396                                 }
397
398                         case SOUND_MIXER_VOLUME:
399                                 *(int*)arg = ret_vol_stereo(devc->volume_l,
400                                                             devc->volume_r);
401                                 return 0;
402                           
403                         case SOUND_MIXER_MIC:
404                                 *(int*)arg = ret_vol_mono(devc->mic);
405                                 return 0;
406
407                         case SOUND_MIXER_BASS:
408                                 if(chipset != CHIPSET_OPL3SA2)
409                                 {
410                                         *(int*)arg = ret_vol_mono(devc->bass);
411                                         return 0;
412                                 }
413                                 else
414                                 {
415                                         return -EINVAL;
416                                 }
417                           
418                         case SOUND_MIXER_TREBLE:
419                                 if(chipset != CHIPSET_OPL3SA2)
420                                 {
421                                         *(int*)arg = ret_vol_mono(devc->treble);
422                                         return 0;
423                                 }
424                                 else
425                                 {
426                                         return -EINVAL;
427                                 }
428                           
429                         default:
430                                 return -EINVAL;
431                 }
432         }
433 }
434
435
436 static struct mixer_operations opl3sa2_mixer_operations =
437 {
438         owner:  THIS_MODULE,
439         id:     "Yamaha",
440         name:   "", /* hmm? */
441         ioctl:  opl3sa2_mixer_ioctl
442 };
443
444 /* End of mixer-related stuff */
445
446
447 static inline int __init probe_opl3sa2_mpu(struct address_info *hw_config)
448 {
449         return probe_mpu401(hw_config);
450 }
451
452
453 static inline void __init attach_opl3sa2_mpu(struct address_info *hw_config)
454 {
455         attach_mpu401(hw_config, THIS_MODULE);
456 }
457
458
459 static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
460 {
461         unload_mpu401(hw_config);
462 }
463
464
465 static inline int __init probe_opl3sa2_mss(struct address_info *hw_config)
466 {
467         return probe_ms_sound(hw_config);
468 }
469
470
471 static void __init attach_opl3sa2_mss(struct address_info *hw_config)
472 {
473         char mixer_name[64];
474
475         /* Create pretty names for mixer stuff */
476         strncpy(mixer_name, chipset_name, 16);
477         strncat(mixer_name, " and AD1848 (through MSS)", 64);
478
479         strncpy(opl3sa2_mixer_operations.name, chipset_name, 16);
480         strncat(opl3sa2_mixer_operations.name, "-AD1848", 64);
481
482         /* Install master mixer */
483         devc->ad_mixer_dev = -1;
484         if((opl3sa2_mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
485                                                 mixer_name,
486                                                 &opl3sa2_mixer_operations,
487                                                 sizeof(struct mixer_operations),
488                                                 devc)) < 0) 
489         {
490                 printk(KERN_ERR "Could not install %s master mixer\n", chipset_name);
491                 return;
492         }
493
494         opl3sa2_mixer_reset(devc);
495
496         attach_ms_sound(hw_config, THIS_MODULE);        /* Slot 0 */
497         if(hw_config->slots[0] != -1)
498         {
499                 /* Did the MSS driver install? */
500                 if(num_mixers == (opl3sa2_mixer + 2))
501                 {
502                         /* The MSS mixer is installed */
503                         devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
504
505                         /* Reroute mixers appropiately */
506                         AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
507                         AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
508                         AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
509                 }
510         }
511 }
512
513
514 static inline void __exit unload_opl3sa2_mss(struct address_info *hw_config)
515 {
516         unload_ms_sound(hw_config);
517 }
518
519
520 static int __init probe_opl3sa2(struct address_info *hw_config)
521 {
522         unsigned char version = 0;
523         char tag;
524
525         /*
526          * Verify that the I/O port range is free.
527          */
528         if(check_region(hw_config->io_base, 2))
529         {
530             printk(KERN_ERR
531                    "%s: Control I/O port 0x%03x not free\n",
532                    __FILE__,
533                    hw_config->io_base);
534             return 0;
535         }
536
537         /*
538          * Determine chipset type (SA2, SA3, or SAx)
539          */
540
541         /*
542          * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
543          */
544         opl3sa2_read(hw_config->io_base,
545                      OPL3SA2_MISC,
546                      (unsigned char*) &version);
547         version &= 0x07;
548
549         /* Match version number to appropiate chipset */
550         if(version & CHIPSET_OPL3SAX)
551         {
552                 chipset = CHIPSET_OPL3SAX;
553                 tag = 'x';
554                 printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
555         }
556         else
557         {
558                 if(version & CHIPSET_OPL3SA3)
559                 {
560                         chipset = CHIPSET_OPL3SA3;
561                         tag = '3';
562                         printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
563                 }
564                 else
565                 {
566                         if(version & CHIPSET_OPL3SA2)
567                         {
568                                 chipset = CHIPSET_OPL3SA2;
569                                 tag = '2';
570                                 printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
571                         }
572                         else
573                         {
574                                 chipset = CHIPSET_UNKNOWN;
575                                 tag = '?';
576                                 printk(KERN_ERR
577                                        "Unknown Yamaha audio controller version\n");
578                                 printk(KERN_INFO
579                                        "%s: chipset version = %x\n",
580                                        __FILE__,
581                                        version);
582                         }
583                 }
584         }
585
586         if(chipset != CHIPSET_UNKNOWN)
587         {
588                 /* Generate a pretty name */
589                 sprintf(chipset_name, "OPL3-SA%c", tag);
590                 return 1;
591         }
592         return 0;
593 }
594
595
596 static void __init attach_opl3sa2(struct address_info *hw_config)
597 {
598         request_region(hw_config->io_base, 2, chipset_name);
599
600         devc->cfg_port = hw_config->io_base;
601 }
602
603
604 static void __exit unload_opl3sa2(struct address_info *hw_config)
605 {
606         /* Release control ports */
607         release_region(hw_config->io_base, 2);
608
609         /* Unload mixer */
610         if(opl3sa2_mixer >= 0)
611                 sound_unload_mixerdev(opl3sa2_mixer);
612 }
613
614 static struct address_info cfg;
615 static struct address_info cfg2;
616 static struct address_info cfg_mpu;
617
618 static int __initdata io        = -1;
619 static int __initdata mss_io    = -1;
620 static int __initdata mpu_io    = -1;
621 static int __initdata irq       = -1;
622 static int __initdata dma       = -1;
623 static int __initdata dma2      = -1;
624
625 MODULE_PARM(io, "i");
626 MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
627
628 MODULE_PARM(mss_io, "i");
629 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)");
630
631 MODULE_PARM(mpu_io, "i");
632 MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be on 4 location boundaries and must be from 0x300 to 0x334)");
633
634 MODULE_PARM(irq, "i");
635 MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
636
637 MODULE_PARM(dma, "i");
638 MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
639
640 MODULE_PARM(dma2, "i");
641 MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
642
643 MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
644 MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
645
646 /*
647  * Install a OPL3SA2 based card.
648  *
649  * Need to have ad1848 and mpu401 loaded ready.
650  */
651 static int __init init_opl3sa2(void)
652 {
653         int i;
654
655         /* Our own config: */
656         cfg.io_base = io;
657         cfg.irq     = irq;
658         cfg.dma     = dma;
659         cfg.dma2    = dma2;
660         
661         /* The MSS config: */
662         cfg2.io_base      = mss_io;
663         cfg2.irq          = irq;
664         cfg2.dma          = dma;
665         cfg2.dma2         = dma2;
666         cfg2.card_subtype = 1;      /* No IRQ or DMA setup */
667
668         cfg_mpu.io_base       = mpu_io;
669         cfg_mpu.irq           = irq;
670         cfg_mpu.dma           = dma;
671         cfg_mpu.always_detect = 1;  /* It's there, so use shared IRQs */
672
673         if(cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.dma2 == -1 || cfg2.io_base == -1) {
674                 printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
675                 return -EINVAL;
676         }
677
678         /* Call me paranoid: */
679         for(i = 0; i < 6; i++)
680         {
681                 cfg.slots[i] = cfg2.slots[i] = cfg_mpu.slots[i] = -1;
682         }
683
684         if(probe_opl3sa2(&cfg) == 0)
685         {
686                 return -ENODEV;
687         }
688
689         if(probe_opl3sa2_mss(&cfg2) == 0)
690         {
691                 return -ENODEV;
692         }
693
694         attach_opl3sa2(&cfg);
695         attach_opl3sa2_mss(&cfg2);
696
697         if(cfg_mpu.io_base != -1) {
698                 if(probe_opl3sa2_mpu(&cfg_mpu)) {
699                         attach_opl3sa2_mpu(&cfg_mpu);
700                 }
701         }
702
703         return 0;
704 }
705
706
707 static void __exit cleanup_opl3sa2(void)
708 {
709         if(cfg_mpu.slots[1] != -1) {
710                 unload_opl3sa2_mpu(&cfg_mpu);
711         }
712         unload_opl3sa2_mss(&cfg2);
713         unload_opl3sa2(&cfg);
714 }
715
716 module_init(init_opl3sa2);
717 module_exit(cleanup_opl3sa2);
718
719 #ifndef MODULE
720 static int __init setup_opl3sa2(char *str)
721 {
722         /* io, irq, dma, dma2 */
723         int ints[7];
724         
725         str = get_options(str, ARRAY_SIZE(ints), ints);
726         
727         io      = ints[1];
728         irq     = ints[2];
729         dma     = ints[3];
730         dma2    = ints[4];
731         mss_io  = ints[5];
732         mpu_io  = ints[6];
733
734         return 1;
735 }
736
737 __setup("opl3sa2=", setup_opl3sa2);
738 #endif