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 <sound/core.h>
28 #include <sound/gus.h>
29 #include <sound/control.h>
33 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
34 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
35 MODULE_LICENSE("GPL");
37 static int snd_gus_init_dma_irq(struct snd_gus_card
* gus
, int latches
);
39 int snd_gus_use_inc(struct snd_gus_card
* gus
)
41 if (!try_module_get(gus
->card
->module
))
46 void snd_gus_use_dec(struct snd_gus_card
* gus
)
48 module_put(gus
->card
->module
);
51 static int snd_gus_joystick_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
53 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
55 uinfo
->value
.integer
.min
= 0;
56 uinfo
->value
.integer
.max
= 31;
60 static int snd_gus_joystick_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
62 struct snd_gus_card
*gus
= snd_kcontrol_chip(kcontrol
);
64 ucontrol
->value
.integer
.value
[0] = gus
->joystick_dac
& 31;
68 static int snd_gus_joystick_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
70 struct snd_gus_card
*gus
= snd_kcontrol_chip(kcontrol
);
75 nval
= ucontrol
->value
.integer
.value
[0] & 31;
76 spin_lock_irqsave(&gus
->reg_lock
, flags
);
77 change
= gus
->joystick_dac
!= nval
;
78 gus
->joystick_dac
= nval
;
79 snd_gf1_write8(gus
, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL
, gus
->joystick_dac
);
80 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
84 static struct snd_kcontrol_new snd_gus_joystick_control
= {
85 .iface
= SNDRV_CTL_ELEM_IFACE_CARD
,
86 .name
= "Joystick Speed",
87 .info
= snd_gus_joystick_info
,
88 .get
= snd_gus_joystick_get
,
89 .put
= snd_gus_joystick_put
92 static void snd_gus_init_control(struct snd_gus_card
*gus
)
95 snd_ctl_add(gus
->card
, snd_ctl_new1(&snd_gus_joystick_control
, gus
));
102 static int snd_gus_free(struct snd_gus_card
*gus
)
104 if (gus
->gf1
.res_port2
== NULL
)
107 snd_gus_init_dma_irq(gus
, 0);
109 release_and_free_resource(gus
->gf1
.res_port1
);
110 release_and_free_resource(gus
->gf1
.res_port2
);
111 if (gus
->gf1
.irq
>= 0)
112 free_irq(gus
->gf1
.irq
, (void *) gus
);
113 if (gus
->gf1
.dma1
>= 0) {
114 disable_dma(gus
->gf1
.dma1
);
115 free_dma(gus
->gf1
.dma1
);
117 if (!gus
->equal_dma
&& gus
->gf1
.dma2
>= 0) {
118 disable_dma(gus
->gf1
.dma2
);
119 free_dma(gus
->gf1
.dma2
);
125 static int snd_gus_dev_free(struct snd_device
*device
)
127 struct snd_gus_card
*gus
= device
->device_data
;
128 return snd_gus_free(gus
);
131 int snd_gus_create(struct snd_card
*card
,
133 int irq
, int dma1
, int dma2
,
138 struct snd_gus_card
**rgus
)
140 struct snd_gus_card
*gus
;
142 static struct snd_device_ops ops
= {
143 .dev_free
= snd_gus_dev_free
,
147 gus
= kzalloc(sizeof(*gus
), GFP_KERNEL
);
150 spin_lock_init(&gus
->reg_lock
);
151 spin_lock_init(&gus
->voice_alloc
);
152 spin_lock_init(&gus
->active_voice_lock
);
153 spin_lock_init(&gus
->event_lock
);
154 spin_lock_init(&gus
->dma_lock
);
155 spin_lock_init(&gus
->pcm_volume_level_lock
);
156 spin_lock_init(&gus
->uart_cmd_lock
);
157 mutex_init(&gus
->dma_mutex
);
162 gus
->gf1
.port
= port
;
163 /* fill register variables for speedup */
164 gus
->gf1
.reg_page
= GUSP(gus
, GF1PAGE
);
165 gus
->gf1
.reg_regsel
= GUSP(gus
, GF1REGSEL
);
166 gus
->gf1
.reg_data8
= GUSP(gus
, GF1DATAHIGH
);
167 gus
->gf1
.reg_data16
= GUSP(gus
, GF1DATALOW
);
168 gus
->gf1
.reg_irqstat
= GUSP(gus
, IRQSTAT
);
169 gus
->gf1
.reg_dram
= GUSP(gus
, DRAM
);
170 gus
->gf1
.reg_timerctrl
= GUSP(gus
, TIMERCNTRL
);
171 gus
->gf1
.reg_timerdata
= GUSP(gus
, TIMERDATA
);
172 /* allocate resources */
173 if ((gus
->gf1
.res_port1
= request_region(port
, 16, "GUS GF1 (Adlib/SB)")) == NULL
) {
174 snd_printk(KERN_ERR
"gus: can't grab SB port 0x%lx\n", port
);
178 if ((gus
->gf1
.res_port2
= request_region(port
+ 0x100, 12, "GUS GF1 (Synth)")) == NULL
) {
179 snd_printk(KERN_ERR
"gus: can't grab synth port 0x%lx\n", port
+ 0x100);
183 if (irq
>= 0 && request_irq(irq
, snd_gus_interrupt
, IRQF_DISABLED
, "GUS GF1", (void *) gus
)) {
184 snd_printk(KERN_ERR
"gus: can't grab irq %d\n", irq
);
189 if (request_dma(dma1
, "GUS - 1")) {
190 snd_printk(KERN_ERR
"gus: can't grab DMA1 %d\n", dma1
);
194 gus
->gf1
.dma1
= dma1
;
195 if (dma2
>= 0 && dma1
!= dma2
) {
196 if (request_dma(dma2
, "GUS - 2")) {
197 snd_printk(KERN_ERR
"gus: can't grab DMA2 %d\n", dma2
);
201 gus
->gf1
.dma2
= dma2
;
203 gus
->gf1
.dma2
= gus
->gf1
.dma1
;
206 gus
->timer_dev
= timer_dev
;
211 if (pcm_channels
< 0)
213 if (pcm_channels
> 8)
217 gus
->gf1
.effect
= effect
? 1 : 0;
218 gus
->gf1
.active_voices
= voices
;
219 gus
->gf1
.pcm_channels
= pcm_channels
;
220 gus
->gf1
.volume_ramp
= 25;
221 gus
->gf1
.smooth_pan
= 1;
222 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, gus
, &ops
)) < 0) {
231 * Memory detection routine for plain GF1 soundcards
234 static int snd_gus_detect_memory(struct snd_gus_card
* gus
)
239 snd_gf1_poke(gus
, 0L, 0xaa);
240 snd_gf1_poke(gus
, 1L, 0x55);
241 if (snd_gf1_peek(gus
, 0L) != 0xaa || snd_gf1_peek(gus
, 1L) != 0x55) {
242 snd_printk(KERN_ERR
"plain GF1 card at 0x%lx without onboard DRAM?\n", gus
->gf1
.port
);
245 for (idx
= 1, d
= 0xab; idx
< 4; idx
++, d
++) {
247 snd_gf1_poke(gus
, local
, d
);
248 snd_gf1_poke(gus
, local
+ 1, d
+ 1);
249 if (snd_gf1_peek(gus
, local
) != d
||
250 snd_gf1_peek(gus
, local
+ 1) != d
+ 1 ||
251 snd_gf1_peek(gus
, 0L) != 0xaa)
255 gus
->gf1
.memory
= idx
<< 18;
257 gus
->gf1
.memory
= 256 * 1024;
259 for (l
= 0, local
= gus
->gf1
.memory
; l
< 4; l
++, local
-= 256 * 1024) {
260 gus
->gf1
.mem_alloc
.banks_8
[l
].address
=
261 gus
->gf1
.mem_alloc
.banks_8
[l
].size
= 0;
262 gus
->gf1
.mem_alloc
.banks_16
[l
].address
= l
<< 18;
263 gus
->gf1
.mem_alloc
.banks_16
[l
].size
= local
> 0 ? 256 * 1024 : 0;
265 gus
->gf1
.mem_alloc
.banks_8
[0].size
= gus
->gf1
.memory
;
266 return 0; /* some memory were detected */
269 static int snd_gus_init_dma_irq(struct snd_gus_card
* gus
, int latches
)
271 struct snd_card
*card
;
274 static unsigned char irqs
[16] =
275 {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
276 static unsigned char dmas
[8] =
277 {6, 1, 0, 2, 0, 3, 4, 5};
279 if (snd_BUG_ON(!gus
))
282 if (snd_BUG_ON(!card
))
285 gus
->mix_cntrl_reg
&= 0xf8;
286 gus
->mix_cntrl_reg
|= 0x01; /* disable MIC, LINE IN, enable LINE OUT */
287 if (gus
->codec_flag
|| gus
->ess_flag
) {
288 gus
->mix_cntrl_reg
&= ~1; /* enable LINE IN */
289 gus
->mix_cntrl_reg
|= 4; /* enable MIC */
291 dma1
= gus
->gf1
.dma1
;
293 dma1
= dmas
[dma1
& 7];
294 dma2
= gus
->gf1
.dma2
;
296 dma2
= dmas
[dma2
& 7];
297 dma1
|= gus
->equal_dma
? 0x40 : (dma2
<< 3);
299 if ((dma1
& 7) == 0 || (dma2
& 7) == 0) {
300 snd_printk(KERN_ERR
"Error! DMA isn't defined.\n");
305 irq
= irqs
[irq
& 0x0f];
307 snd_printk(KERN_ERR
"Error! IRQ isn't defined.\n");
312 card
->mixer
.mix_ctrl_reg
|= 0x10;
315 spin_lock_irqsave(&gus
->reg_lock
, flags
);
316 outb(5, GUSP(gus
, REGCNTRLS
));
317 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
318 outb(0x00, GUSP(gus
, IRQDMACNTRLREG
));
319 outb(0, GUSP(gus
, REGCNTRLS
));
320 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
324 spin_lock_irqsave(&gus
->reg_lock
, flags
);
325 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
326 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
328 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
329 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
331 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
335 spin_lock_irqsave(&gus
->reg_lock
, flags
);
336 outb(0x00 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
337 outb(dma1
, GUSP(gus
, IRQDMACNTRLREG
));
339 outb(0x40 | gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
340 outb(irq
, GUSP(gus
, IRQDMACNTRLREG
));
342 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
347 gus
->mix_cntrl_reg
|= 0x08; /* enable latches */
349 gus
->mix_cntrl_reg
&= ~0x08; /* disable latches */
350 spin_lock_irqsave(&gus
->reg_lock
, flags
);
351 outb(gus
->mix_cntrl_reg
, GUSP(gus
, MIXCNTRLREG
));
352 outb(0, GUSP(gus
, GF1PAGE
));
353 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
358 static int snd_gus_check_version(struct snd_gus_card
* gus
)
361 unsigned char val
, rev
;
362 struct snd_card
*card
;
365 spin_lock_irqsave(&gus
->reg_lock
, flags
);
366 outb(0x20, GUSP(gus
, REGCNTRLS
));
367 val
= inb(GUSP(gus
, REGCNTRLS
));
368 rev
= inb(GUSP(gus
, BOARDVERSION
));
369 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
370 snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus
->gf1
.port
, val
, rev
);
371 strcpy(card
->driver
, "GUS");
372 strcpy(card
->longname
, "Gravis UltraSound Classic (2.4)");
373 if ((val
!= 255 && (val
& 0x06)) || (rev
>= 5 && rev
!= 255)) {
374 if (rev
>= 5 && rev
<= 9) {
377 gus
->ics_flipped
= 1;
378 card
->longname
[27] = '3';
379 card
->longname
[29] = rev
== 5 ? '5' : '7';
381 if (rev
>= 10 && rev
!= 255) {
382 if (rev
>= 10 && rev
<= 11) {
383 strcpy(card
->driver
, "GUS MAX");
384 strcpy(card
->longname
, "Gravis UltraSound MAX");
386 } else if (rev
== 0x30) {
387 strcpy(card
->driver
, "GUS ACE");
388 strcpy(card
->longname
, "Gravis UltraSound Ace");
390 } else if (rev
== 0x50) {
391 strcpy(card
->driver
, "GUS Extreme");
392 strcpy(card
->longname
, "Gravis UltraSound Extreme");
395 snd_printk(KERN_ERR
"unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus
->gf1
.port
, rev
, val
);
396 snd_printk(KERN_ERR
" please - report to <perex@perex.cz>\n");
400 strcpy(card
->shortname
, card
->longname
);
401 gus
->uart_enable
= 1; /* standard GUSes doesn't have midi uart trouble */
402 snd_gus_init_control(gus
);
406 int snd_gus_initialize(struct snd_gus_card
*gus
)
410 if (!gus
->interwave
) {
411 if ((err
= snd_gus_check_version(gus
)) < 0) {
412 snd_printk(KERN_ERR
"version check failed\n");
415 if ((err
= snd_gus_detect_memory(gus
)) < 0)
418 if ((err
= snd_gus_init_dma_irq(gus
, 1)) < 0)
421 gus
->initialized
= 1;
426 EXPORT_SYMBOL(snd_gf1_delay
);
427 EXPORT_SYMBOL(snd_gf1_write8
);
428 EXPORT_SYMBOL(snd_gf1_look8
);
429 EXPORT_SYMBOL(snd_gf1_write16
);
430 EXPORT_SYMBOL(snd_gf1_look16
);
431 EXPORT_SYMBOL(snd_gf1_i_write8
);
432 EXPORT_SYMBOL(snd_gf1_i_look8
);
433 EXPORT_SYMBOL(snd_gf1_i_look16
);
434 EXPORT_SYMBOL(snd_gf1_dram_addr
);
435 EXPORT_SYMBOL(snd_gf1_write_addr
);
436 EXPORT_SYMBOL(snd_gf1_poke
);
437 EXPORT_SYMBOL(snd_gf1_peek
);
439 EXPORT_SYMBOL(snd_gf1_alloc_voice
);
440 EXPORT_SYMBOL(snd_gf1_free_voice
);
441 EXPORT_SYMBOL(snd_gf1_ctrl_stop
);
442 EXPORT_SYMBOL(snd_gf1_stop_voice
);
444 EXPORT_SYMBOL(snd_gf1_new_mixer
);
446 EXPORT_SYMBOL(snd_gf1_pcm_new
);
448 EXPORT_SYMBOL(snd_gus_use_inc
);
449 EXPORT_SYMBOL(snd_gus_use_dec
);
450 EXPORT_SYMBOL(snd_gus_create
);
451 EXPORT_SYMBOL(snd_gus_initialize
);
453 EXPORT_SYMBOL(snd_gus_interrupt
);
455 EXPORT_SYMBOL(snd_gf1_rawmidi_new
);
457 EXPORT_SYMBOL(snd_gus_dram_write
);
458 EXPORT_SYMBOL(snd_gus_dram_read
);
460 EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw
);
461 EXPORT_SYMBOL(snd_gf1_translate_freq
);
463 EXPORT_SYMBOL(snd_gf1_mem_alloc
);
464 EXPORT_SYMBOL(snd_gf1_mem_xfree
);
465 EXPORT_SYMBOL(snd_gf1_mem_free
);
466 EXPORT_SYMBOL(snd_gf1_mem_lock
);
472 static int __init
alsa_gus_init(void)
477 static void __exit
alsa_gus_exit(void)
481 module_init(alsa_gus_init
)
482 module_exit(alsa_gus_exit
)