4 * Low level driver for Yamaha YMF701B aka OPL3-SA chip
8 * Copyright (C) by Hannu Savolainen 1993-1997
10 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11 * Version 2 (June 1991). See the "COPYING" file distributed with this software
15 * Alan Cox Modularisation
16 * Christoph Hellwig Adapted to module_init/module_exit
17 * Arnaldo C. de Melo got rid of attach_uart401
20 * Check for install of mpu etc is wrong, should check result of the mss stuff
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/spinlock.h>
29 #include "sound_config.h"
36 static int sb_initialized
;
39 static spinlock_t lock
=SPIN_LOCK_UNLOCKED
;
41 static unsigned char opl3sa_read(int addr
)
46 spin_lock_irqsave(&lock
,flags
);
47 outb((0x1d), 0xf86); /* password */
48 outb(((unsigned char) addr
), 0xf86); /* address */
49 tmp
= inb(0xf87); /* data */
50 spin_unlock_irqrestore(&lock
,flags
);
55 static void opl3sa_write(int addr
, int data
)
59 spin_lock_irqsave(&lock
,flags
);
60 outb((0x1d), 0xf86); /* password */
61 outb(((unsigned char) addr
), 0xf86); /* address */
62 outb(((unsigned char) data
), 0xf87); /* data */
63 spin_unlock_irqrestore(&lock
,flags
);
66 static int __init
opl3sa_detect(void)
70 if (((tmp
= opl3sa_read(0x01)) & 0xc4) != 0x04)
72 DDB(printk("OPL3-SA detect error 1 (%x)\n", opl3sa_read(0x01)));
77 * Check that the password feature has any effect
80 if (inb(0xf87) == tmp
)
82 DDB(printk("OPL3-SA detect failed 2 (%x/%x)\n", tmp
, inb(0xf87)));
85 tmp
= (opl3sa_read(0x04) & 0xe0) >> 5;
87 if (tmp
!= 0 && tmp
!= 1)
89 DDB(printk("OPL3-SA detect failed 3 (%d)\n", tmp
));
92 DDB(printk("OPL3-SA mode %x detected\n", tmp
));
94 opl3sa_write(0x01, 0x00); /* Disable MSS */
95 opl3sa_write(0x02, 0x00); /* Disable SB */
96 opl3sa_write(0x03, 0x00); /* Disable MPU */
102 * Probe and attach routines for the Windows Sound System mode of
106 static int __init
probe_opl3sa_wss(struct address_info
*hw_config
, struct resource
*ports
)
108 unsigned char tmp
= 0x24; /* WSS enable */
111 * Check if the IO port returns valid signature. The original MS Sound
112 * system returns 0x04 while some cards (OPL3-SA for example)
116 if (!opl3sa_detect())
118 printk(KERN_ERR
"OSS: OPL3-SA chip not found\n");
122 switch (hw_config
->io_base
)
137 printk(KERN_ERR
"OSS: Unsupported OPL3-SA/WSS base %x\n", hw_config
->io_base
);
141 opl3sa_write(0x01, tmp
); /* WSS setup register */
143 return probe_ms_sound(hw_config
, ports
);
146 static void __init
attach_opl3sa_wss(struct address_info
*hw_config
, struct resource
*ports
)
151 attach_ms_sound(hw_config
, ports
, THIS_MODULE
);
152 if (num_mixers
> nm
) /* A mixer was installed */
154 AD1848_REROUTE(SOUND_MIXER_LINE1
, SOUND_MIXER_CD
);
155 AD1848_REROUTE(SOUND_MIXER_LINE2
, SOUND_MIXER_SYNTH
);
156 AD1848_REROUTE(SOUND_MIXER_LINE3
, SOUND_MIXER_LINE
);
161 static int __init
probe_opl3sa_mpu(struct address_info
*hw_config
)
164 static signed char irq_bits
[] = {
165 -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
168 if (hw_config
->irq
> 10)
170 printk(KERN_ERR
"OPL3-SA: Bad MPU IRQ %d\n", hw_config
->irq
);
173 if (irq_bits
[hw_config
->irq
] == -1)
175 printk(KERN_ERR
"OPL3-SA: Bad MPU IRQ %d\n", hw_config
->irq
);
178 switch (hw_config
->io_base
)
193 return 0; /* Invalid port */
196 conf
|= 0x83; /* MPU & OPL3 (synth) & game port enable */
197 conf
|= irq_bits
[hw_config
->irq
] << 2;
199 opl3sa_write(0x03, conf
);
201 hw_config
->name
= "OPL3-SA (MPU401)";
203 return probe_uart401(hw_config
, THIS_MODULE
);
206 static void __exit
unload_opl3sa_wss(struct address_info
*hw_config
)
208 int dma2
= hw_config
->dma2
;
211 dma2
= hw_config
->dma
;
213 release_region(0xf86, 2);
214 release_region(hw_config
->io_base
, 4);
216 ad1848_unload(hw_config
->io_base
+ 4,
221 sound_unload_audiodev(hw_config
->slots
[0]);
224 static inline void __exit
unload_opl3sa_mpu(struct address_info
*hw_config
)
226 unload_uart401(hw_config
);
230 static inline void __exit
unload_opl3sa_sb(struct address_info
*hw_config
)
232 sb_dsp_unload(hw_config
);
236 static int found_mpu
;
238 static struct address_info cfg
;
239 static struct address_info cfg_mpu
;
241 static int __initdata io
= -1;
242 static int __initdata irq
= -1;
243 static int __initdata dma
= -1;
244 static int __initdata dma2
= -1;
245 static int __initdata mpu_io
= -1;
246 static int __initdata mpu_irq
= -1;
249 MODULE_PARM(irq
,"i");
250 MODULE_PARM(dma
,"i");
251 MODULE_PARM(dma2
,"i");
252 MODULE_PARM(mpu_io
,"i");
253 MODULE_PARM(mpu_irq
,"i");
255 static int __init
init_opl3sa(void)
257 struct resource
*ports
;
258 if (io
== -1 || irq
== -1 || dma
== -1) {
259 printk(KERN_ERR
"opl3sa: dma, irq and io must be set.\n");
268 cfg_mpu
.io_base
= mpu_io
;
269 cfg_mpu
.irq
= mpu_irq
;
271 ports
= request_region(io
+ 4, 4, "ad1848");
275 if (!request_region(0xf86, 2, "OPL3-SA"))/* Control port is busy */ {
276 release_region(io
+ 4, 4);
280 if (!request_region(io
, 4, "WSS config")) {
281 release_region(0x86, 2);
282 release_region(io
+ 4, 4);
286 if (probe_opl3sa_wss(&cfg
, ports
) == 0) {
287 release_region(0xf86, 2);
288 release_region(io
, 4);
289 release_region(io
+ 4, 4);
293 found_mpu
=probe_opl3sa_mpu(&cfg_mpu
);
295 attach_opl3sa_wss(&cfg
, ports
);
299 static void __exit
cleanup_opl3sa(void)
302 unload_opl3sa_mpu(&cfg_mpu
);
303 unload_opl3sa_wss(&cfg
);
306 module_init(init_opl3sa
);
307 module_exit(cleanup_opl3sa
);
310 static int __init
setup_opl3sa(char *str
)
312 /* io, irq, dma, dma2, mpu_io, mpu_irq */
315 str
= get_options(str
, ARRAY_SIZE(ints
), ints
);
327 __setup("opl3sa=", setup_opl3sa
);
329 MODULE_LICENSE("GPL");