1 /* 2 * Routines for Gravis UltraSound soundcards 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 4 * 5 * 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. 10 * 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. 15 * 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 19 * 20 */ 21 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> 31 32 #include <asm/dma.h> 33 34 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 35 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); 36 MODULE_LICENSE("GPL"); 37 38 static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches); 39 40 int snd_gus_use_inc(snd_gus_card_t * gus) 41 { 42 if (!try_module_get(gus->card->module)) 43 return 0; 44 return 1; 45 } 46 47 void snd_gus_use_dec(snd_gus_card_t * gus) 48 { 49 module_put(gus->card->module); 50 } 51 52 static int snd_gus_joystick_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 53 { 54 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 55 uinfo->count = 1; 56 uinfo->value.integer.min = 0; 57 uinfo->value.integer.max = 31; 58 return 0; 59 } 60 61 static int snd_gus_joystick_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 62 { 63 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol); 64 65 ucontrol->value.integer.value[0] = gus->joystick_dac & 31; 66 return 0; 67 } 68 69 static int snd_gus_joystick_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 70 { 71 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol); 72 unsigned long flags; 73 int change; 74 unsigned char nval; 75 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); 82 return change; 83 } 84 85 static snd_kcontrol_new_t 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 91 }; 92 93 static void snd_gus_init_control(snd_gus_card_t *gus) 94 { 95 if (!gus->ace_flag) 96 snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus)); 97 } 98 99 /* 100 * 101 */ 102 103 static int snd_gus_free(snd_gus_card_t *gus) 104 { 105 if (gus->gf1.res_port2 == NULL) 106 goto __hw_end; 107 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) 108 if (gus->seq_dev) { 109 snd_device_free(gus->card, gus->seq_dev); 110 gus->seq_dev = NULL; 111 } 112 #endif 113 snd_gf1_stop(gus); 114 snd_gus_init_dma_irq(gus, 0); 115 __hw_end: 116 if (gus->gf1.res_port1) { 117 release_resource(gus->gf1.res_port1); 118 kfree_nocheck(gus->gf1.res_port1); 119 } 120 if (gus->gf1.res_port2) { 121 release_resource(gus->gf1.res_port2); 122 kfree_nocheck(gus->gf1.res_port2); 123 } 124 if (gus->gf1.irq >= 0) 125 free_irq(gus->gf1.irq, (void *) gus); 126 if (gus->gf1.dma1 >= 0) { 127 disable_dma(gus->gf1.dma1); 128 free_dma(gus->gf1.dma1); 129 } 130 if (!gus->equal_dma && gus->gf1.dma2 >= 0) { 131 disable_dma(gus->gf1.dma2); 132 free_dma(gus->gf1.dma2); 133 } 134 kfree(gus); 135 return 0; 136 } 137 138 static int snd_gus_dev_free(snd_device_t *device) 139 { 140 snd_gus_card_t *gus = device->device_data; 141 return snd_gus_free(gus); 142 } 143 144 int snd_gus_create(snd_card_t * card, 145 unsigned long port, 146 int irq, int dma1, int dma2, 147 int timer_dev, 148 int voices, 149 int pcm_channels, 150 int effect, 151 snd_gus_card_t **rgus) 152 { 153 snd_gus_card_t *gus; 154 int err; 155 static snd_device_ops_t ops = { 156 .dev_free = snd_gus_dev_free, 157 }; 158 159 *rgus = NULL; 160 gus = kcalloc(1, sizeof(*gus), GFP_KERNEL); 161 if (gus == NULL) 162 return -ENOMEM; 163 gus->gf1.irq = -1; 164 gus->gf1.dma1 = -1; 165 gus->gf1.dma2 = -1; 166 gus->card = card; 167 gus->gf1.port = port; 168 /* fill register variables for speedup */ 169 gus->gf1.reg_page = GUSP(gus, GF1PAGE); 170 gus->gf1.reg_regsel = GUSP(gus, GF1REGSEL); 171 gus->gf1.reg_data8 = GUSP(gus, GF1DATAHIGH); 172 gus->gf1.reg_data16 = GUSP(gus, GF1DATALOW); 173 gus->gf1.reg_irqstat = GUSP(gus, IRQSTAT); 174 gus->gf1.reg_dram = GUSP(gus, DRAM); 175 gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL); 176 gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA); 177 /* allocate resources */ 178 if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) { 179 snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); 180 snd_gus_free(gus); 181 return -EBUSY; 182 } 183 if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) { 184 snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); 185 snd_gus_free(gus); 186 return -EBUSY; 187 } 188 if (irq >= 0 && request_irq(irq, snd_gus_interrupt, SA_INTERRUPT, "GUS GF1", (void *) gus)) { 189 snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); 190 snd_gus_free(gus); 191 return -EBUSY; 192 } 193 gus->gf1.irq = irq; 194 if (request_dma(dma1, "GUS - 1")) { 195 snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1); 196 snd_gus_free(gus); 197 return -EBUSY; 198 } 199 gus->gf1.dma1 = dma1; 200 if (dma2 >= 0 && dma1 != dma2) { 201 if (request_dma(dma2, "GUS - 2")) { 202 snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2); 203 snd_gus_free(gus); 204 return -EBUSY; 205 } 206 gus->gf1.dma2 = dma2; 207 } else { 208 gus->gf1.dma2 = gus->gf1.dma1; 209 gus->equal_dma = 1; 210 } 211 gus->timer_dev = timer_dev; 212 if (voices < 14) 213 voices = 14; 214 if (voices > 32) 215 voices = 32; 216 if (pcm_channels < 0) 217 pcm_channels = 0; 218 if (pcm_channels > 8) 219 pcm_channels = 8; 220 pcm_channels++; 221 pcm_channels &= ~1; 222 gus->gf1.effect = effect ? 1 : 0; 223 gus->gf1.active_voices = voices; 224 gus->gf1.pcm_channels = pcm_channels; 225 gus->gf1.volume_ramp = 25; 226 gus->gf1.smooth_pan = 1; 227 spin_lock_init(&gus->reg_lock); 228 spin_lock_init(&gus->voice_alloc); 229 spin_lock_init(&gus->active_voice_lock); 230 spin_lock_init(&gus->event_lock); 231 spin_lock_init(&gus->dma_lock); 232 spin_lock_init(&gus->pcm_volume_level_lock); 233 spin_lock_init(&gus->uart_cmd_lock); 234 init_MUTEX(&gus->dma_mutex); 235 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { 236 snd_gus_free(gus); 237 return err; 238 } 239 *rgus = gus; 240 return 0; 241 } 242 243 /* 244 * Memory detection routine for plain GF1 soundcards 245 */ 246 247 static int snd_gus_detect_memory(snd_gus_card_t * gus) 248 { 249 int l, idx, local; 250 unsigned char d; 251 252 snd_gf1_poke(gus, 0L, 0xaa); 253 snd_gf1_poke(gus, 1L, 0x55); 254 if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) { 255 snd_printk("plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); 256 return -ENOMEM; 257 } 258 for (idx = 1, d = 0xab; idx < 4; idx++, d++) { 259 local = idx << 18; 260 snd_gf1_poke(gus, local, d); 261 snd_gf1_poke(gus, local + 1, d + 1); 262 if (snd_gf1_peek(gus, local) != d || 263 snd_gf1_peek(gus, local + 1) != d + 1 || 264 snd_gf1_peek(gus, 0L) != 0xaa) 265 break; 266 } 267 #if 1 268 gus->gf1.memory = idx << 18; 269 #else 270 gus->gf1.memory = 256 * 1024; 271 #endif 272 for (l = 0, local = gus->gf1.memory; l < 4; l++, local -= 256 * 1024) { 273 gus->gf1.mem_alloc.banks_8[l].address = 274 gus->gf1.mem_alloc.banks_8[l].size = 0; 275 gus->gf1.mem_alloc.banks_16[l].address = l << 18; 276 gus->gf1.mem_alloc.banks_16[l].size = local > 0 ? 256 * 1024 : 0; 277 } 278 gus->gf1.mem_alloc.banks_8[0].size = gus->gf1.memory; 279 return 0; /* some memory were detected */ 280 } 281 282 static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches) 283 { 284 snd_card_t *card; 285 unsigned long flags; 286 int irq, dma1, dma2; 287 static unsigned char irqs[16] = 288 {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; 289 static unsigned char dmas[8] = 290 {6, 1, 0, 2, 0, 3, 4, 5}; 291 292 snd_assert(gus != NULL, return -EINVAL); 293 card = gus->card; 294 snd_assert(card != NULL, return -EINVAL); 295 296 gus->mix_cntrl_reg &= 0xf8; 297 gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */ 298 if (gus->codec_flag || gus->ess_flag) { 299 gus->mix_cntrl_reg &= ~1; /* enable LINE IN */ 300 gus->mix_cntrl_reg |= 4; /* enable MIC */ 301 } 302 dma1 = gus->gf1.dma1; 303 dma1 = dma1 < 0 ? -dma1 : dma1; 304 dma1 = dmas[dma1 & 7]; 305 dma2 = gus->gf1.dma2; 306 dma2 = dma2 < 0 ? -dma2 : dma2; 307 dma2 = dmas[dma2 & 7]; 308 #if 0 309 printk("dma1 = %i, dma2 = %i\n", gus->gf1.dma1, gus->gf1.dma2); 310 #endif 311 dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); 312 313 if ((dma1 & 7) == 0 || (dma2 & 7) == 0) { 314 snd_printk("Error! DMA isn't defined.\n"); 315 return -EINVAL; 316 } 317 irq = gus->gf1.irq; 318 irq = irq < 0 ? -irq : irq; 319 irq = irqs[irq & 0x0f]; 320 if (irq == 0) { 321 snd_printk("Error! IRQ isn't defined.\n"); 322 return -EINVAL; 323 } 324 irq |= 0x40; 325 #if 0 326 card->mixer.mix_ctrl_reg |= 0x10; 327 #endif 328 329 spin_lock_irqsave(&gus->reg_lock, flags); 330 outb(5, GUSP(gus, REGCNTRLS)); 331 outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 332 outb(0x00, GUSP(gus, IRQDMACNTRLREG)); 333 outb(0, GUSP(gus, REGCNTRLS)); 334 spin_unlock_irqrestore(&gus->reg_lock, flags); 335 336 udelay(100); 337 338 spin_lock_irqsave(&gus->reg_lock, flags); 339 outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 340 outb(dma1, GUSP(gus, IRQDMACNTRLREG)); 341 if (latches) { 342 outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 343 outb(irq, GUSP(gus, IRQDMACNTRLREG)); 344 } 345 spin_unlock_irqrestore(&gus->reg_lock, flags); 346 347 udelay(100); 348 349 spin_lock_irqsave(&gus->reg_lock, flags); 350 outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 351 outb(dma1, GUSP(gus, IRQDMACNTRLREG)); 352 if (latches) { 353 outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 354 outb(irq, GUSP(gus, IRQDMACNTRLREG)); 355 } 356 spin_unlock_irqrestore(&gus->reg_lock, flags); 357 358 snd_gf1_delay(gus); 359 360 if (latches) 361 gus->mix_cntrl_reg |= 0x08; /* enable latches */ 362 else 363 gus->mix_cntrl_reg &= ~0x08; /* disable latches */ 364 spin_lock_irqsave(&gus->reg_lock, flags); 365 outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); 366 outb(0, GUSP(gus, GF1PAGE)); 367 spin_unlock_irqrestore(&gus->reg_lock, flags); 368 369 return 0; 370 } 371 372 static int snd_gus_check_version(snd_gus_card_t * gus) 373 { 374 unsigned long flags; 375 unsigned char val, rev; 376 snd_card_t *card; 377 378 card = gus->card; 379 spin_lock_irqsave(&gus->reg_lock, flags); 380 outb(0x20, GUSP(gus, REGCNTRLS)); 381 val = inb(GUSP(gus, REGCNTRLS)); 382 rev = inb(GUSP(gus, BOARDVERSION)); 383 spin_unlock_irqrestore(&gus->reg_lock, flags); 384 snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); 385 strcpy(card->driver, "GUS"); 386 strcpy(card->longname, "Gravis UltraSound Classic (2.4)"); 387 if ((val != 255 && (val & 0x06)) || (rev >= 5 && rev != 255)) { 388 if (rev >= 5 && rev <= 9) { 389 gus->ics_flag = 1; 390 if (rev == 5) 391 gus->ics_flipped = 1; 392 card->longname[27] = '3'; 393 card->longname[29] = rev == 5 ? '5' : '7'; 394 } 395 if (rev >= 10 && rev != 255) { 396 if (rev >= 10 && rev <= 11) { 397 strcpy(card->driver, "GUS MAX"); 398 strcpy(card->longname, "Gravis UltraSound MAX"); 399 gus->max_flag = 1; 400 } else if (rev == 0x30) { 401 strcpy(card->driver, "GUS ACE"); 402 strcpy(card->longname, "Gravis UltraSound Ace"); 403 gus->ace_flag = 1; 404 } else if (rev == 0x50) { 405 strcpy(card->driver, "GUS Extreme"); 406 strcpy(card->longname, "Gravis UltraSound Extreme"); 407 gus->ess_flag = 1; 408 } else { 409 snd_printk("unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); 410 snd_printk(" please - report to <perex@suse.cz>\n"); 411 } 412 } 413 } 414 strcpy(card->shortname, card->longname); 415 gus->uart_enable = 1; /* standard GUSes doesn't have midi uart trouble */ 416 snd_gus_init_control(gus); 417 return 0; 418 } 419 420 static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev) 421 { 422 snd_gus_card_t *gus = seq_dev->private_data; 423 gus->seq_dev = NULL; 424 } 425 426 int snd_gus_initialize(snd_gus_card_t *gus) 427 { 428 int err; 429 430 if (!gus->interwave) { 431 if ((err = snd_gus_check_version(gus)) < 0) { 432 snd_printk("version check failed\n"); 433 return err; 434 } 435 if ((err = snd_gus_detect_memory(gus)) < 0) 436 return err; 437 } 438 if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) 439 return err; 440 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) 441 if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS, 442 sizeof(snd_gus_card_t*), &gus->seq_dev) >= 0) { 443 strcpy(gus->seq_dev->name, "GUS"); 444 *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus; 445 gus->seq_dev->private_data = gus; 446 gus->seq_dev->private_free = snd_gus_seq_dev_free; 447 } 448 #endif 449 snd_gf1_start(gus); 450 gus->initialized = 1; 451 return 0; 452 } 453 454 /* gus_io.c */ 455 EXPORT_SYMBOL(snd_gf1_delay); 456 EXPORT_SYMBOL(snd_gf1_write8); 457 EXPORT_SYMBOL(snd_gf1_look8); 458 EXPORT_SYMBOL(snd_gf1_write16); 459 EXPORT_SYMBOL(snd_gf1_look16); 460 EXPORT_SYMBOL(snd_gf1_i_write8); 461 EXPORT_SYMBOL(snd_gf1_i_look8); 462 EXPORT_SYMBOL(snd_gf1_i_write16); 463 EXPORT_SYMBOL(snd_gf1_i_look16); 464 EXPORT_SYMBOL(snd_gf1_dram_addr); 465 EXPORT_SYMBOL(snd_gf1_write_addr); 466 EXPORT_SYMBOL(snd_gf1_poke); 467 EXPORT_SYMBOL(snd_gf1_peek); 468 /* gus_reset.c */ 469 EXPORT_SYMBOL(snd_gf1_alloc_voice); 470 EXPORT_SYMBOL(snd_gf1_free_voice); 471 EXPORT_SYMBOL(snd_gf1_ctrl_stop); 472 EXPORT_SYMBOL(snd_gf1_stop_voice); 473 EXPORT_SYMBOL(snd_gf1_start); 474 EXPORT_SYMBOL(snd_gf1_stop); 475 /* gus_mixer.c */ 476 EXPORT_SYMBOL(snd_gf1_new_mixer); 477 /* gus_pcm.c */ 478 EXPORT_SYMBOL(snd_gf1_pcm_new); 479 /* gus.c */ 480 EXPORT_SYMBOL(snd_gus_use_inc); 481 EXPORT_SYMBOL(snd_gus_use_dec); 482 EXPORT_SYMBOL(snd_gus_create); 483 EXPORT_SYMBOL(snd_gus_initialize); 484 /* gus_irq.c */ 485 EXPORT_SYMBOL(snd_gus_interrupt); 486 /* gus_uart.c */ 487 EXPORT_SYMBOL(snd_gf1_rawmidi_new); 488 /* gus_dram.c */ 489 EXPORT_SYMBOL(snd_gus_dram_write); 490 EXPORT_SYMBOL(snd_gus_dram_read); 491 /* gus_volume.c */ 492 EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw); 493 EXPORT_SYMBOL(snd_gf1_translate_freq); 494 /* gus_mem.c */ 495 EXPORT_SYMBOL(snd_gf1_mem_alloc); 496 EXPORT_SYMBOL(snd_gf1_mem_xfree); 497 EXPORT_SYMBOL(snd_gf1_mem_free); 498 EXPORT_SYMBOL(snd_gf1_mem_lock); 499 500 /* 501 * INIT part 502 */ 503 504 static int __init alsa_gus_init(void) 505 { 506 return 0; 507 } 508 509 static void __exit alsa_gus_exit(void) 510 { 511 } 512 513 module_init(alsa_gus_init) 514 module_exit(alsa_gus_exit) 515