2 * Routines for Gravis UltraSound soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/module.h>
28 #include <sound/core.h>
29 #include <sound/gus.h>
30 #include <sound/control.h>
34 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
35 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
36 MODULE_LICENSE("GPL");
38 static int snd_gus_init_dma_irq(struct snd_gus_card
* gus
, int latches
);
40 int snd_gus_use_inc(struct snd_gus_card
* gus
)
42 if (!try_module_get(gus
->card
->module
))
47 void snd_gus_use_dec(struct snd_gus_card
* gus
)
49 module_put(gus
->card
->module
);
52 static int snd_gus_joystick_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
54 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
56 uinfo
->value
.integer
.min
= 0;
57 uinfo
->value
.integer
.max
= 31;
61 static int snd_gus_joystick_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
63 struct snd_gus_card
*gus
= snd_kcontrol_chip(kcontrol
);
65 ucontrol
->value
.integer
.value
[0] = gus
->joystick_dac
& 31;
69 static int snd_gus_joystick_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
71 struct snd_gus_card
*gus
= snd_kcontrol_chip(kcontrol
);
76 nval
= ucontrol
->value
.integer
.value
[0] & 31;
77 spin_lock_irqsave(&gus
->reg_lock
, flags
);
78 change
= gus
->joystick_dac
!= nval
;
79 gus
->joystick_dac
= nval
;
80 snd_gf1_write8(gus
, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL
, gus
->joystick_dac
);
81 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
85 static struct snd_kcontrol_new snd_gus_joystick_control
= {
86 .iface
= SNDRV_CTL_ELEM_IFACE_CARD
,
87 .name
= "Joystick Speed",
88 .info
= snd_gus_joystick_info
,
89 .get
= snd_gus_joystick_get
,
90 .put
= snd_gus_joystick_put
93 static void snd_gus_init_control(struct snd_gus_card
*gus
)
96 snd_ctl_add(gus
->card
, snd_ctl_new1(&snd_gus_joystick_control
, gus
));
103 static int snd_gus_free(struct snd_gus_card
*gus
)
105 if (gus
->gf1
.res_port2
== NULL
)
108 snd_gus_init_dma_irq(gus
, 0);
110 release_and_free_resource(gus
->gf1
.res_port1
);
111 release_and_free_resource(gus
->gf1
.res_port2
);
112 if (gus
->gf1
.irq
>= 0)
113 free_irq(gus
->gf1
.irq
, (void *) gus
);
114 if (gus
->gf1
.dma1
>= 0) {
115 disable_dma(gus
->gf1
.dma1
);
116 free_dma(gus
->gf1
.dma1
);
118 if (!gus
->equal_dma
&& gus
->gf1
.dma2
>= 0) {
119 disable_dma(gus
->gf1
.dma2
);
120 free_dma(gus
->gf1
.dma2
);
126 static int snd_gus_dev_free(struct snd_device
*device
)
128 struct snd_gus_card
*gus
= device
->device_data
;
129 return snd_gus_free(gus
);
132 int snd_gus_create(struct snd_card
*card
,
134 int irq
, int dma1
, int dma2
,
139 struct snd_gus_card
**rgus
)
141 struct snd_gus_card
*gus
;
143 static struct snd_device_ops ops
= {
144 .dev_free
= snd_gus_dev_free
,
148 gus
= kzalloc(sizeof(*gus
), GFP_KERNEL
);
151 spin_lock_init(&gus
->reg_lock
);
152 spin_lock_init(&gus
->voice_alloc
);
153 spin_lock_init(&gus
->active_voice_lock
);
154 spin_lock_init(&gus
->event_lock
);
155 spin_lock_init(&gus
->dma_lock
);
156 spin_lock_init(&gus
->pcm_volume_level_lock
);
157 spin_lock_init(&gus
->uart_cmd_lock
);
158 mutex_init(&gus
->dma_mutex
);
163 gus
->gf1
.port
= port
;
164 /* fill register variables for speedup */
165 gus
->gf1
.reg_page
= GUSP(gus
, GF1PAGE
);
166 gus
->gf1
.reg_regsel
= GUSP(gus
, GF1REGSEL
);
167 gus
->gf1
.reg_data8
= GUSP(gus
, GF1DATAHIGH
);
168 gus
->gf1
.reg_data16
= GUSP(gus
, GF1DATALOW
);
169 gus
->gf1
.reg_irqstat
= GUSP(gus
, IRQSTAT
);
170 gus
->gf1
.reg_dram
= GUSP(gus
, DRAM
);
171 gus
->gf1
.reg_timerctrl
= GUSP(gus
, TIMERCNTRL
);
172 gus
->gf1
.reg_timerdata
= GUSP(gus
, TIMERDATA
);
173 /* allocate resources */
174 if ((gus
->gf1
.res_port1
= request_region(port
, 16, "GUS GF1 (Adlib/SB)")) == NULL
) {
175 snd_printk(KERN_ERR
"gus: can't grab SB port 0x%lx\n", port
);
179 if ((gus
->gf1
.res_port2
= request_region(port
+ 0x100, 12, "GUS GF1 (Synth)")) == NULL
) {
180 snd_printk(KERN_ERR
"gus: can't grab synth port 0x%lx\n", port
+ 0x100);
184 if (irq
>= 0 && request_irq(irq
, snd_gus_interrupt
, 0, "GUS GF1", (void *) gus
)) {
185 snd_printk(KERN_ERR
"gus: can't grab irq %d\n", irq
);
190 if (request_dma(dma1
, "GUS - 1")) {
191 snd_printk(KERN_ERR
"gus: can't grab DMA1 %d\n", dma1
);
195 gus
->gf1
.dma1
= dma1
;
196 if (dma2
>= 0 && dma1
!= dma2
) {
197 if (request_dma(dma2
, "GUS - 2")) {
198 snd_printk(KERN_ERR
"gus: can't grab DMA2 %d\n", dma2
);
202 gus
->gf1
.dma2
= dma2
;
204 gus
->gf1
.dma2
= gus
->gf1
.dma1
;
207 gus
->timer_dev
= timer_dev
;
212 if (pcm_channels
< 0)
214 if (pcm_channels
> 8)
218 gus
->gf1
.effect
= effect
? 1 : 0;
219 gus
->gf1
.active_voices
= voices
;
220 gus
->gf1
.pcm_channels
= pcm_channels
;
221 gus
->gf1
.volume_ramp
= 25;
222 gus
->gf1
.smooth_pan
= 1;
223 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, gus
, &ops
)) < 0) {
232 * Memory detection routine for plain GF1 soundcards
235 static int snd_gus_detect_memory(struct snd_gus_card
* gus
)
240 snd_gf1_poke(gus
, 0L, 0xaa);
241 snd_gf1_poke(gus
, 1L, 0x55);
242 if (snd_gf1_peek(gus
, 0L) != 0xaa || snd_gf1_peek(gus
, 1L) != 0x55) {
243 snd_printk(KERN_ERR
"plain GF1 card at 0x%lx without onboard DRAM?\n", gus
->gf1
.port
);
246 for (idx
= 1, d
= 0xab; idx
< 4; idx
++, d
++) {
248 snd_gf1_poke(gus
, local
, d
);
249 snd_gf1_poke(gus
, local
+ 1, d
+ 1);
250 if (snd_gf1_peek(gus
, local
) != d
||
251 snd_gf1_peek(gus
, local
+ 1) != d
+ 1 ||
252 snd_gf1_peek(gus
, 0L) != 0xaa)
256 gus
->gf1
.memory
= idx
<< 18;
258 gus
->gf1
.memory
= 256 * 1024;
260 for (l
= 0, local
= gus
->gf1
.memory
; l
< 4; l
++, local
-= 256 * 1024) {
261 gus
->gf1
.mem_alloc
.banks_8
[l
].address
=
262 gus
->gf1
.mem_alloc
.banks_8
[l
].size
= 0;
263 gus
->gf1
.mem_alloc
.banks_16
[l
].address
= l
<< 18;
264 gus
->gf1
.mem_alloc
.banks_16
[l
].size
= local
> 0 ? 256 * 1024 : 0;
266 gus
->gf1
.mem_alloc
.banks_8
[0].size
= gus
->gf1
.memory
;
267 return 0; /* some memory were detected */
270 static int snd_gus_init_dma_irq(struct snd_gus_card
* gus
, int latches
)
272 struct snd_card
*card
;
275 static unsigned char irqs
[16] =
276 {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
277 static unsigned char dmas
[8] =
278 {6, 1, 0, 2, 0, 3, 4, 5};
280 if (snd_BUG_ON(!gus
))
283 if (snd_BUG_ON(!card
))
286 gus
->mix_cntrl_reg
&= 0xf8;
287 gus
->mix_cntrl_reg
|= 0x01; /* disable MIC, LINE IN, enable LINE OUT */
288 if (gus
->codec_flag
|| gus
->ess_flag
) {
289 gus
->mix_cntrl_reg
&= ~1; /* enable LINE IN */
290 gus
->mix_cntrl_reg
|= 4; /* enable MIC */
292 dma1
= gus
->gf1
.dma1
;
294 dma1
= dmas
[dma1
& 7];
295 dma2
= gus
->gf1
.dma2
;
297 dma2
= dmas
[dma2
& 7];
298 dma1
|= gus
->equal_dma
? 0x40 : (dma2
<< 3);
300 if ((dma1
& 7) == 0 || (dma2
& 7) == 0) {
301 snd_printk(KERN_ERR
"Error! DMA isn't defined.\n");
306 irq
= irqs
[irq
& 0x0f];
308 snd_printk(KERN_ERR
"Error! IRQ isn't defined.\n");
313 card
->mixer
.mix_ctrl_reg
|= 0x10;
316 spin_lock_irqsave(&gus
->reg_lock
, flags
);
317 outb(5, GUSP(gus
, REGCNTRLS
));
318 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
319 outb(0x00, GUSP(gus
, IRQDMACNTRLREG
));
320 outb(0, GUSP(gus
, REGCNTRLS
));
321 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
325 spin_lock_irqsave(&gus
->reg_lock
, flags
);
326 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
327 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
329 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
330 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
332 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
336 spin_lock_irqsave(&gus
->reg_lock
, flags
);
337 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
338 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
340 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
341 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
343 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
348 gus
->mix_cntrl_reg
|= 0x08; /* enable latches */
350 gus
->mix_cntrl_reg
&= ~0x08; /* disable latches */
351 spin_lock_irqsave(&gus
->reg_lock
, flags
);
352 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
353 outb(0, GUSP(gus
, GF1PAGE
));
354 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
359 static int snd_gus_check_version(struct snd_gus_card
* gus
)
362 unsigned char val
, rev
;
363 struct snd_card
*card
;
366 spin_lock_irqsave(&gus
->reg_lock
, flags
);
367 outb(0x20, GUSP(gus
, REGCNTRLS
));
368 val
= inb(GUSP(gus
, REGCNTRLS
));
369 rev
= inb(GUSP(gus
, BOARDVERSION
));
370 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
371 snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus
->gf1
.port
, val
, rev
);
372 strcpy(card
->driver
, "GUS");
373 strcpy(card
->longname
, "Gravis UltraSound Classic (2.4)");
374 if ((val
!= 255 && (val
& 0x06)) || (rev
>= 5 && rev
!= 255)) {
375 if (rev
>= 5 && rev
<= 9) {
378 gus
->ics_flipped
= 1;
379 card
->longname
[27] = '3';
380 card
->longname
[29] = rev
== 5 ? '5' : '7';
382 if (rev
>= 10 && rev
!= 255) {
383 if (rev
>= 10 && rev
<= 11) {
384 strcpy(card
->driver
, "GUS MAX");
385 strcpy(card
->longname
, "Gravis UltraSound MAX");
387 } else if (rev
== 0x30) {
388 strcpy(card
->driver
, "GUS ACE");
389 strcpy(card
->longname
, "Gravis UltraSound Ace");
391 } else if (rev
== 0x50) {
392 strcpy(card
->driver
, "GUS Extreme");
393 strcpy(card
->longname
, "Gravis UltraSound Extreme");
396 snd_printk(KERN_ERR
"unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus
->gf1
.port
, rev
, val
);
397 snd_printk(KERN_ERR
" please - report to <perex@perex.cz>\n");
401 strcpy(card
->shortname
, card
->longname
);
402 gus
->uart_enable
= 1; /* standard GUSes doesn't have midi uart trouble */
403 snd_gus_init_control(gus
);
407 int snd_gus_initialize(struct snd_gus_card
*gus
)
411 if (!gus
->interwave
) {
412 if ((err
= snd_gus_check_version(gus
)) < 0) {
413 snd_printk(KERN_ERR
"version check failed\n");
416 if ((err
= snd_gus_detect_memory(gus
)) < 0)
419 if ((err
= snd_gus_init_dma_irq(gus
, 1)) < 0)
422 gus
->initialized
= 1;
427 EXPORT_SYMBOL(snd_gf1_delay
);
428 EXPORT_SYMBOL(snd_gf1_write8
);
429 EXPORT_SYMBOL(snd_gf1_look8
);
430 EXPORT_SYMBOL(snd_gf1_write16
);
431 EXPORT_SYMBOL(snd_gf1_look16
);
432 EXPORT_SYMBOL(snd_gf1_i_write8
);
433 EXPORT_SYMBOL(snd_gf1_i_look8
);
434 EXPORT_SYMBOL(snd_gf1_i_look16
);
435 EXPORT_SYMBOL(snd_gf1_dram_addr
);
436 EXPORT_SYMBOL(snd_gf1_write_addr
);
437 EXPORT_SYMBOL(snd_gf1_poke
);
438 EXPORT_SYMBOL(snd_gf1_peek
);
440 EXPORT_SYMBOL(snd_gf1_alloc_voice
);
441 EXPORT_SYMBOL(snd_gf1_free_voice
);
442 EXPORT_SYMBOL(snd_gf1_ctrl_stop
);
443 EXPORT_SYMBOL(snd_gf1_stop_voice
);
445 EXPORT_SYMBOL(snd_gf1_new_mixer
);
447 EXPORT_SYMBOL(snd_gf1_pcm_new
);
449 EXPORT_SYMBOL(snd_gus_use_inc
);
450 EXPORT_SYMBOL(snd_gus_use_dec
);
451 EXPORT_SYMBOL(snd_gus_create
);
452 EXPORT_SYMBOL(snd_gus_initialize
);
454 EXPORT_SYMBOL(snd_gus_interrupt
);
456 EXPORT_SYMBOL(snd_gf1_rawmidi_new
);
458 EXPORT_SYMBOL(snd_gus_dram_write
);
459 EXPORT_SYMBOL(snd_gus_dram_read
);
461 EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw
);
462 EXPORT_SYMBOL(snd_gf1_translate_freq
);
464 EXPORT_SYMBOL(snd_gf1_mem_alloc
);
465 EXPORT_SYMBOL(snd_gf1_mem_xfree
);
466 EXPORT_SYMBOL(snd_gf1_mem_free
);
467 EXPORT_SYMBOL(snd_gf1_mem_lock
);
473 static int __init
alsa_gus_init(void)
478 static void __exit
alsa_gus_exit(void)
482 module_init(alsa_gus_init
)
483 module_exit(alsa_gus_exit
)