2 * Routines for Gravis UltraSound soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.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 <sound/driver.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/ioport.h>
28 #include <sound/core.h>
29 #include <sound/gus.h>
30 #include <sound/control.h>
34 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.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
)
107 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
109 snd_device_free(gus
->card
, gus
->seq_dev
);
114 snd_gus_init_dma_irq(gus
, 0);
116 release_and_free_resource(gus
->gf1
.res_port1
);
117 release_and_free_resource(gus
->gf1
.res_port2
);
118 if (gus
->gf1
.irq
>= 0)
119 free_irq(gus
->gf1
.irq
, (void *) gus
);
120 if (gus
->gf1
.dma1
>= 0) {
121 disable_dma(gus
->gf1
.dma1
);
122 free_dma(gus
->gf1
.dma1
);
124 if (!gus
->equal_dma
&& gus
->gf1
.dma2
>= 0) {
125 disable_dma(gus
->gf1
.dma2
);
126 free_dma(gus
->gf1
.dma2
);
132 static int snd_gus_dev_free(struct snd_device
*device
)
134 struct snd_gus_card
*gus
= device
->device_data
;
135 return snd_gus_free(gus
);
138 int snd_gus_create(struct snd_card
*card
,
140 int irq
, int dma1
, int dma2
,
145 struct snd_gus_card
**rgus
)
147 struct snd_gus_card
*gus
;
149 static struct snd_device_ops ops
= {
150 .dev_free
= snd_gus_dev_free
,
154 gus
= kzalloc(sizeof(*gus
), GFP_KERNEL
);
161 gus
->gf1
.port
= port
;
162 /* fill register variables for speedup */
163 gus
->gf1
.reg_page
= GUSP(gus
, GF1PAGE
);
164 gus
->gf1
.reg_regsel
= GUSP(gus
, GF1REGSEL
);
165 gus
->gf1
.reg_data8
= GUSP(gus
, GF1DATAHIGH
);
166 gus
->gf1
.reg_data16
= GUSP(gus
, GF1DATALOW
);
167 gus
->gf1
.reg_irqstat
= GUSP(gus
, IRQSTAT
);
168 gus
->gf1
.reg_dram
= GUSP(gus
, DRAM
);
169 gus
->gf1
.reg_timerctrl
= GUSP(gus
, TIMERCNTRL
);
170 gus
->gf1
.reg_timerdata
= GUSP(gus
, TIMERDATA
);
171 /* allocate resources */
172 if ((gus
->gf1
.res_port1
= request_region(port
, 16, "GUS GF1 (Adlib/SB)")) == NULL
) {
173 snd_printk(KERN_ERR
"gus: can't grab SB port 0x%lx\n", port
);
177 if ((gus
->gf1
.res_port2
= request_region(port
+ 0x100, 12, "GUS GF1 (Synth)")) == NULL
) {
178 snd_printk(KERN_ERR
"gus: can't grab synth port 0x%lx\n", port
+ 0x100);
182 if (irq
>= 0 && request_irq(irq
, snd_gus_interrupt
, SA_INTERRUPT
, "GUS GF1", (void *) gus
)) {
183 snd_printk(KERN_ERR
"gus: can't grab irq %d\n", irq
);
188 if (request_dma(dma1
, "GUS - 1")) {
189 snd_printk(KERN_ERR
"gus: can't grab DMA1 %d\n", dma1
);
193 gus
->gf1
.dma1
= dma1
;
194 if (dma2
>= 0 && dma1
!= dma2
) {
195 if (request_dma(dma2
, "GUS - 2")) {
196 snd_printk(KERN_ERR
"gus: can't grab DMA2 %d\n", dma2
);
200 gus
->gf1
.dma2
= dma2
;
202 gus
->gf1
.dma2
= gus
->gf1
.dma1
;
205 gus
->timer_dev
= timer_dev
;
210 if (pcm_channels
< 0)
212 if (pcm_channels
> 8)
216 gus
->gf1
.effect
= effect
? 1 : 0;
217 gus
->gf1
.active_voices
= voices
;
218 gus
->gf1
.pcm_channels
= pcm_channels
;
219 gus
->gf1
.volume_ramp
= 25;
220 gus
->gf1
.smooth_pan
= 1;
221 spin_lock_init(&gus
->reg_lock
);
222 spin_lock_init(&gus
->voice_alloc
);
223 spin_lock_init(&gus
->active_voice_lock
);
224 spin_lock_init(&gus
->event_lock
);
225 spin_lock_init(&gus
->dma_lock
);
226 spin_lock_init(&gus
->pcm_volume_level_lock
);
227 spin_lock_init(&gus
->uart_cmd_lock
);
228 init_MUTEX(&gus
->dma_mutex
);
229 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, gus
, &ops
)) < 0) {
238 * Memory detection routine for plain GF1 soundcards
241 static int snd_gus_detect_memory(struct snd_gus_card
* gus
)
246 snd_gf1_poke(gus
, 0L, 0xaa);
247 snd_gf1_poke(gus
, 1L, 0x55);
248 if (snd_gf1_peek(gus
, 0L) != 0xaa || snd_gf1_peek(gus
, 1L) != 0x55) {
249 snd_printk(KERN_ERR
"plain GF1 card at 0x%lx without onboard DRAM?\n", gus
->gf1
.port
);
252 for (idx
= 1, d
= 0xab; idx
< 4; idx
++, d
++) {
254 snd_gf1_poke(gus
, local
, d
);
255 snd_gf1_poke(gus
, local
+ 1, d
+ 1);
256 if (snd_gf1_peek(gus
, local
) != d
||
257 snd_gf1_peek(gus
, local
+ 1) != d
+ 1 ||
258 snd_gf1_peek(gus
, 0L) != 0xaa)
262 gus
->gf1
.memory
= idx
<< 18;
264 gus
->gf1
.memory
= 256 * 1024;
266 for (l
= 0, local
= gus
->gf1
.memory
; l
< 4; l
++, local
-= 256 * 1024) {
267 gus
->gf1
.mem_alloc
.banks_8
[l
].address
=
268 gus
->gf1
.mem_alloc
.banks_8
[l
].size
= 0;
269 gus
->gf1
.mem_alloc
.banks_16
[l
].address
= l
<< 18;
270 gus
->gf1
.mem_alloc
.banks_16
[l
].size
= local
> 0 ? 256 * 1024 : 0;
272 gus
->gf1
.mem_alloc
.banks_8
[0].size
= gus
->gf1
.memory
;
273 return 0; /* some memory were detected */
276 static int snd_gus_init_dma_irq(struct snd_gus_card
* gus
, int latches
)
278 struct snd_card
*card
;
281 static unsigned char irqs
[16] =
282 {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
283 static unsigned char dmas
[8] =
284 {6, 1, 0, 2, 0, 3, 4, 5};
286 snd_assert(gus
!= NULL
, return -EINVAL
);
288 snd_assert(card
!= NULL
, return -EINVAL
);
290 gus
->mix_cntrl_reg
&= 0xf8;
291 gus
->mix_cntrl_reg
|= 0x01; /* disable MIC, LINE IN, enable LINE OUT */
292 if (gus
->codec_flag
|| gus
->ess_flag
) {
293 gus
->mix_cntrl_reg
&= ~1; /* enable LINE IN */
294 gus
->mix_cntrl_reg
|= 4; /* enable MIC */
296 dma1
= gus
->gf1
.dma1
;
297 dma1
= dma1
< 0 ? -dma1
: dma1
;
298 dma1
= dmas
[dma1
& 7];
299 dma2
= gus
->gf1
.dma2
;
300 dma2
= dma2
< 0 ? -dma2
: dma2
;
301 dma2
= dmas
[dma2
& 7];
302 dma1
|= gus
->equal_dma
? 0x40 : (dma2
<< 3);
304 if ((dma1
& 7) == 0 || (dma2
& 7) == 0) {
305 snd_printk(KERN_ERR
"Error! DMA isn't defined.\n");
309 irq
= irq
< 0 ? -irq
: irq
;
310 irq
= irqs
[irq
& 0x0f];
312 snd_printk(KERN_ERR
"Error! IRQ isn't defined.\n");
317 card
->mixer
.mix_ctrl_reg
|= 0x10;
320 spin_lock_irqsave(&gus
->reg_lock
, flags
);
321 outb(5, GUSP(gus
, REGCNTRLS
));
322 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
323 outb(0x00, GUSP(gus
, IRQDMACNTRLREG
));
324 outb(0, GUSP(gus
, REGCNTRLS
));
325 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
329 spin_lock_irqsave(&gus
->reg_lock
, flags
);
330 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
331 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
333 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
334 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
336 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
340 spin_lock_irqsave(&gus
->reg_lock
, flags
);
341 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
342 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
344 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
345 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
347 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
352 gus
->mix_cntrl_reg
|= 0x08; /* enable latches */
354 gus
->mix_cntrl_reg
&= ~0x08; /* disable latches */
355 spin_lock_irqsave(&gus
->reg_lock
, flags
);
356 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
357 outb(0, GUSP(gus
, GF1PAGE
));
358 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
363 static int snd_gus_check_version(struct snd_gus_card
* gus
)
366 unsigned char val
, rev
;
367 struct snd_card
*card
;
370 spin_lock_irqsave(&gus
->reg_lock
, flags
);
371 outb(0x20, GUSP(gus
, REGCNTRLS
));
372 val
= inb(GUSP(gus
, REGCNTRLS
));
373 rev
= inb(GUSP(gus
, BOARDVERSION
));
374 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
375 snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus
->gf1
.port
, val
, rev
);
376 strcpy(card
->driver
, "GUS");
377 strcpy(card
->longname
, "Gravis UltraSound Classic (2.4)");
378 if ((val
!= 255 && (val
& 0x06)) || (rev
>= 5 && rev
!= 255)) {
379 if (rev
>= 5 && rev
<= 9) {
382 gus
->ics_flipped
= 1;
383 card
->longname
[27] = '3';
384 card
->longname
[29] = rev
== 5 ? '5' : '7';
386 if (rev
>= 10 && rev
!= 255) {
387 if (rev
>= 10 && rev
<= 11) {
388 strcpy(card
->driver
, "GUS MAX");
389 strcpy(card
->longname
, "Gravis UltraSound MAX");
391 } else if (rev
== 0x30) {
392 strcpy(card
->driver
, "GUS ACE");
393 strcpy(card
->longname
, "Gravis UltraSound Ace");
395 } else if (rev
== 0x50) {
396 strcpy(card
->driver
, "GUS Extreme");
397 strcpy(card
->longname
, "Gravis UltraSound Extreme");
400 snd_printk(KERN_ERR
"unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus
->gf1
.port
, rev
, val
);
401 snd_printk(KERN_ERR
" please - report to <perex@suse.cz>\n");
405 strcpy(card
->shortname
, card
->longname
);
406 gus
->uart_enable
= 1; /* standard GUSes doesn't have midi uart trouble */
407 snd_gus_init_control(gus
);
411 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
412 static void snd_gus_seq_dev_free(struct snd_seq_device
*seq_dev
)
414 struct snd_gus_card
*gus
= seq_dev
->private_data
;
419 int snd_gus_initialize(struct snd_gus_card
*gus
)
423 if (!gus
->interwave
) {
424 if ((err
= snd_gus_check_version(gus
)) < 0) {
425 snd_printk(KERN_ERR
"version check failed\n");
428 if ((err
= snd_gus_detect_memory(gus
)) < 0)
431 if ((err
= snd_gus_init_dma_irq(gus
, 1)) < 0)
433 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
434 if (snd_seq_device_new(gus
->card
, 1, SNDRV_SEQ_DEV_ID_GUS
,
435 sizeof(struct snd_gus_card
*), &gus
->seq_dev
) >= 0) {
436 strcpy(gus
->seq_dev
->name
, "GUS");
437 *(struct snd_gus_card
**)SNDRV_SEQ_DEVICE_ARGPTR(gus
->seq_dev
) = gus
;
438 gus
->seq_dev
->private_data
= gus
;
439 gus
->seq_dev
->private_free
= snd_gus_seq_dev_free
;
443 gus
->initialized
= 1;
448 EXPORT_SYMBOL(snd_gf1_delay
);
449 EXPORT_SYMBOL(snd_gf1_write8
);
450 EXPORT_SYMBOL(snd_gf1_look8
);
451 EXPORT_SYMBOL(snd_gf1_write16
);
452 EXPORT_SYMBOL(snd_gf1_look16
);
453 EXPORT_SYMBOL(snd_gf1_i_write8
);
454 EXPORT_SYMBOL(snd_gf1_i_look8
);
455 EXPORT_SYMBOL(snd_gf1_i_look16
);
456 EXPORT_SYMBOL(snd_gf1_dram_addr
);
457 EXPORT_SYMBOL(snd_gf1_write_addr
);
458 EXPORT_SYMBOL(snd_gf1_poke
);
459 EXPORT_SYMBOL(snd_gf1_peek
);
461 EXPORT_SYMBOL(snd_gf1_alloc_voice
);
462 EXPORT_SYMBOL(snd_gf1_free_voice
);
463 EXPORT_SYMBOL(snd_gf1_ctrl_stop
);
464 EXPORT_SYMBOL(snd_gf1_stop_voice
);
466 EXPORT_SYMBOL(snd_gf1_new_mixer
);
468 EXPORT_SYMBOL(snd_gf1_pcm_new
);
470 EXPORT_SYMBOL(snd_gus_use_inc
);
471 EXPORT_SYMBOL(snd_gus_use_dec
);
472 EXPORT_SYMBOL(snd_gus_create
);
473 EXPORT_SYMBOL(snd_gus_initialize
);
475 EXPORT_SYMBOL(snd_gus_interrupt
);
477 EXPORT_SYMBOL(snd_gf1_rawmidi_new
);
479 EXPORT_SYMBOL(snd_gus_dram_write
);
480 EXPORT_SYMBOL(snd_gus_dram_read
);
482 EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw
);
483 EXPORT_SYMBOL(snd_gf1_translate_freq
);
485 EXPORT_SYMBOL(snd_gf1_mem_alloc
);
486 EXPORT_SYMBOL(snd_gf1_mem_xfree
);
487 EXPORT_SYMBOL(snd_gf1_mem_free
);
488 EXPORT_SYMBOL(snd_gf1_mem_lock
);
494 static int __init
alsa_gus_init(void)
499 static void __exit
alsa_gus_exit(void)
503 module_init(alsa_gus_init
)
504 module_exit(alsa_gus_exit
)