1 /* 2 * Driver for Gallant SC-6000 soundcard. This card is also known as 3 * Audio Excel DSP 16 or Zoltrix AV302. 4 * These cards use CompuMedia ASC-9308 chip + AD1848 codec. 5 * SC-6600 and SC-7000 cards are also supported. They are based on 6 * CompuMedia ASC-9408 chip and CS4231 codec. 7 * 8 * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> 9 * 10 * I don't have documentation for this card. I used the driver 11 * for OSS/Free included in the kernel source as reference. 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 28 #include <linux/module.h> 29 #include <linux/delay.h> 30 #include <linux/isa.h> 31 #include <linux/io.h> 32 #include <asm/dma.h> 33 #include <sound/core.h> 34 #include <sound/wss.h> 35 #include <sound/opl3.h> 36 #include <sound/mpu401.h> 37 #include <sound/control.h> 38 #define SNDRV_LEGACY_FIND_FREE_IRQ 39 #define SNDRV_LEGACY_FIND_FREE_DMA 40 #include <sound/initval.h> 41 42 MODULE_AUTHOR("Krzysztof Helt"); 43 MODULE_DESCRIPTION("Gallant SC-6000"); 44 MODULE_LICENSE("GPL"); 45 MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000}," 46 "{AudioExcel, Audio Excel DSP 16}," 47 "{Zoltrix, AV302}}"); 48 49 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 50 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 51 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 52 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */ 53 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */ 54 static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */ 55 static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; 56 /* 0x300, 0x310, 0x320, 0x330 */ 57 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ 58 static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ 59 60 module_param_array(index, int, NULL, 0444); 61 MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); 62 module_param_array(id, charp, NULL, 0444); 63 MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard."); 64 module_param_array(enable, bool, NULL, 0444); 65 MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard."); 66 module_param_array(port, long, NULL, 0444); 67 MODULE_PARM_DESC(port, "Port # for sc-6000 driver."); 68 module_param_array(mss_port, long, NULL, 0444); 69 MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver."); 70 module_param_array(mpu_port, long, NULL, 0444); 71 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver."); 72 module_param_array(irq, int, NULL, 0444); 73 MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver."); 74 module_param_array(mpu_irq, int, NULL, 0444); 75 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); 76 module_param_array(dma, int, NULL, 0444); 77 MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); 78 79 /* 80 * Commands of SC6000's DSP (SBPRO+special). 81 * Some of them are COMMAND_xx, in the future they may change. 82 */ 83 #define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ 84 #define COMMAND_52 0x52 /* */ 85 #define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ 86 #define COMMAND_5C 0x5c /* */ 87 #define COMMAND_60 0x60 /* */ 88 #define COMMAND_66 0x66 /* */ 89 #define COMMAND_6C 0x6c /* */ 90 #define COMMAND_6E 0x6e /* */ 91 #define COMMAND_88 0x88 /* Unknown command */ 92 #define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ 93 #define COMMAND_C5 0xc5 /* */ 94 #define GET_DSP_VERSION 0xe1 /* Get DSP Version */ 95 #define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ 96 97 /* 98 * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port 99 * to have the actual I/O port. 100 * Register permissions are: 101 * (wo) == Write Only 102 * (ro) == Read Only 103 * (w-) == Write 104 * (r-) == Read 105 */ 106 #define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ 107 #define DSP_READ 0x0a /* offset of DSP READ (ro) */ 108 #define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ 109 #define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ 110 #define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ 111 #define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ 112 113 #define PFX "sc6000: " 114 #define DRV_NAME "SC-6000" 115 116 /* hardware dependent functions */ 117 118 /* 119 * sc6000_irq_to_softcfg - Decode irq number into cfg code. 120 */ 121 static __devinit unsigned char sc6000_irq_to_softcfg(int irq) 122 { 123 unsigned char val = 0; 124 125 switch (irq) { 126 case 5: 127 val = 0x28; 128 break; 129 case 7: 130 val = 0x8; 131 break; 132 case 9: 133 val = 0x10; 134 break; 135 case 10: 136 val = 0x18; 137 break; 138 case 11: 139 val = 0x20; 140 break; 141 default: 142 break; 143 } 144 return val; 145 } 146 147 /* 148 * sc6000_dma_to_softcfg - Decode dma number into cfg code. 149 */ 150 static __devinit unsigned char sc6000_dma_to_softcfg(int dma) 151 { 152 unsigned char val = 0; 153 154 switch (dma) { 155 case 0: 156 val = 1; 157 break; 158 case 1: 159 val = 2; 160 break; 161 case 3: 162 val = 3; 163 break; 164 default: 165 break; 166 } 167 return val; 168 } 169 170 /* 171 * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code. 172 */ 173 static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) 174 { 175 unsigned char val = 0; 176 177 switch (mpu_irq) { 178 case 5: 179 val = 4; 180 break; 181 case 7: 182 val = 0x44; 183 break; 184 case 9: 185 val = 0x84; 186 break; 187 case 10: 188 val = 0xc4; 189 break; 190 default: 191 break; 192 } 193 return val; 194 } 195 196 static int sc6000_wait_data(char __iomem *vport) 197 { 198 int loop = 1000; 199 unsigned char val = 0; 200 201 do { 202 val = ioread8(vport + DSP_DATAVAIL); 203 if (val & 0x80) 204 return 0; 205 cpu_relax(); 206 } while (loop--); 207 208 return -EAGAIN; 209 } 210 211 static int sc6000_read(char __iomem *vport) 212 { 213 if (sc6000_wait_data(vport)) 214 return -EBUSY; 215 216 return ioread8(vport + DSP_READ); 217 218 } 219 220 static int sc6000_write(char __iomem *vport, int cmd) 221 { 222 unsigned char val; 223 int loop = 500000; 224 225 do { 226 val = ioread8(vport + DSP_STATUS); 227 /* 228 * DSP ready to receive data if bit 7 of val == 0 229 */ 230 if (!(val & 0x80)) { 231 iowrite8(cmd, vport + DSP_COMMAND); 232 return 0; 233 } 234 cpu_relax(); 235 } while (loop--); 236 237 snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); 238 239 return -EIO; 240 } 241 242 static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command, 243 char *data, int data_len) 244 { 245 int len = 0; 246 247 if (sc6000_write(vport, command)) { 248 snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); 249 return -EIO; 250 } 251 252 do { 253 int val = sc6000_read(vport); 254 255 if (val < 0) 256 break; 257 258 data[len++] = val; 259 260 } while (len < data_len); 261 262 /* 263 * If no more data available, return to the caller, no error if len>0. 264 * We have no other way to know when the string is finished. 265 */ 266 return len ? len : -EIO; 267 } 268 269 static int __devinit sc6000_dsp_reset(char __iomem *vport) 270 { 271 iowrite8(1, vport + DSP_RESET); 272 udelay(10); 273 iowrite8(0, vport + DSP_RESET); 274 udelay(20); 275 if (sc6000_read(vport) == 0xaa) 276 return 0; 277 return -ENODEV; 278 } 279 280 /* detection and initialization */ 281 static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg) 282 { 283 if (sc6000_write(vport, COMMAND_6C) < 0) { 284 snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C); 285 return -EIO; 286 } 287 if (sc6000_write(vport, COMMAND_5C) < 0) { 288 snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C); 289 return -EIO; 290 } 291 if (sc6000_write(vport, cfg[0]) < 0) { 292 snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]); 293 return -EIO; 294 } 295 if (sc6000_write(vport, cfg[1]) < 0) { 296 snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]); 297 return -EIO; 298 } 299 if (sc6000_write(vport, COMMAND_C5) < 0) { 300 snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5); 301 return -EIO; 302 } 303 304 return 0; 305 } 306 307 static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg) 308 { 309 310 if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { 311 snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); 312 return -EIO; 313 } 314 if (sc6000_write(vport, softcfg)) { 315 snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); 316 return -EIO; 317 } 318 return 0; 319 } 320 321 static int sc6000_setup_board(char __iomem *vport, int config) 322 { 323 int loop = 10; 324 325 do { 326 if (sc6000_write(vport, COMMAND_88)) { 327 snd_printk(KERN_ERR "CMD 0x%x: failed!\n", 328 COMMAND_88); 329 return -EIO; 330 } 331 } while ((sc6000_wait_data(vport) < 0) && loop--); 332 333 if (sc6000_read(vport) < 0) { 334 snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", 335 COMMAND_88); 336 return -EIO; 337 } 338 339 if (sc6000_cfg_write(vport, config)) 340 return -ENODEV; 341 342 return 0; 343 } 344 345 static int __devinit sc6000_init_mss(char __iomem *vport, int config, 346 char __iomem *vmss_port, int mss_config) 347 { 348 if (sc6000_write(vport, DSP_INIT_MSS)) { 349 snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", 350 DSP_INIT_MSS); 351 return -EIO; 352 } 353 354 msleep(10); 355 356 if (sc6000_cfg_write(vport, config)) 357 return -EIO; 358 359 iowrite8(mss_config, vmss_port); 360 361 return 0; 362 } 363 364 static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, 365 long xport, long xmpu, 366 long xmss_port) 367 { 368 cfg[0] = 0; 369 cfg[1] = 0; 370 if (xport == 0x240) 371 cfg[0] |= 1; 372 if (xmpu != SNDRV_AUTO_PORT) { 373 cfg[0] |= (xmpu & 0x30) >> 2; 374 cfg[1] |= 0x20; 375 } 376 if (xmss_port == 0xe80) 377 cfg[0] |= 0x10; 378 cfg[0] |= 0x40; /* always set */ 379 cfg[1] |= 0x80; /* enable WSS system */ 380 cfg[1] &= ~0x40; /* disable IDE */ 381 snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); 382 } 383 384 static int __devinit sc6000_init_board(char __iomem *vport, 385 char __iomem *vmss_port, int dev) 386 { 387 char answer[15]; 388 char version[2]; 389 int mss_config = sc6000_irq_to_softcfg(irq[dev]) | 390 sc6000_dma_to_softcfg(dma[dev]); 391 int config = mss_config | 392 sc6000_mpu_irq_to_softcfg(mpu_irq[dev]); 393 int err; 394 int cfg[2]; 395 int old = 0; 396 397 err = sc6000_dsp_reset(vport); 398 if (err < 0) { 399 snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); 400 return err; 401 } 402 403 memset(answer, 0, sizeof(answer)); 404 err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); 405 if (err <= 0) { 406 snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); 407 return -ENODEV; 408 } 409 /* 410 * My SC-6000 card return "SC-6000" in DSPCopyright, so 411 * if we have something different, we have to be warned. 412 */ 413 if (strncmp("SC-6000", answer, 7)) 414 snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); 415 416 if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { 417 snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); 418 return -ENODEV; 419 } 420 printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", 421 answer, version[0], version[1]); 422 423 /* set configuration */ 424 sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], 425 mss_port[dev]); 426 if (sc6000_hw_cfg_write(vport, cfg) < 0) { 427 snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); 428 return -EIO; 429 } 430 err = sc6000_setup_board(vport, config); 431 if (err < 0) { 432 snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); 433 return -ENODEV; 434 } 435 436 sc6000_dsp_reset(vport); 437 sc6000_write(vport, COMMAND_5C); 438 if (sc6000_read(vport) < 0) 439 old = 1; 440 sc6000_dsp_reset(vport); 441 442 if (!old) { 443 sc6000_write(vport, COMMAND_60); 444 sc6000_write(vport, 0x02); 445 sc6000_dsp_reset(vport); 446 } 447 448 err = sc6000_setup_board(vport, config); 449 if (err < 0) { 450 snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); 451 return -ENODEV; 452 } 453 err = sc6000_init_mss(vport, config, vmss_port, mss_config); 454 if (err < 0) { 455 snd_printk(KERN_ERR "Cannot initialize " 456 "Microsoft Sound System mode.\n"); 457 return -ENODEV; 458 } 459 460 return 0; 461 } 462 463 static int __devinit snd_sc6000_mixer(struct snd_wss *chip) 464 { 465 struct snd_card *card = chip->card; 466 struct snd_ctl_elem_id id1, id2; 467 int err; 468 469 memset(&id1, 0, sizeof(id1)); 470 memset(&id2, 0, sizeof(id2)); 471 id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 472 id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 473 /* reassign AUX0 to FM */ 474 strcpy(id1.name, "Aux Playback Switch"); 475 strcpy(id2.name, "FM Playback Switch"); 476 err = snd_ctl_rename_id(card, &id1, &id2); 477 if (err < 0) 478 return err; 479 strcpy(id1.name, "Aux Playback Volume"); 480 strcpy(id2.name, "FM Playback Volume"); 481 err = snd_ctl_rename_id(card, &id1, &id2); 482 if (err < 0) 483 return err; 484 /* reassign AUX1 to CD */ 485 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; 486 strcpy(id2.name, "CD Playback Switch"); 487 err = snd_ctl_rename_id(card, &id1, &id2); 488 if (err < 0) 489 return err; 490 strcpy(id1.name, "Aux Playback Volume"); 491 strcpy(id2.name, "CD Playback Volume"); 492 err = snd_ctl_rename_id(card, &id1, &id2); 493 if (err < 0) 494 return err; 495 return 0; 496 } 497 498 static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev) 499 { 500 if (!enable[dev]) 501 return 0; 502 if (port[dev] == SNDRV_AUTO_PORT) { 503 printk(KERN_ERR PFX "specify IO port\n"); 504 return 0; 505 } 506 if (mss_port[dev] == SNDRV_AUTO_PORT) { 507 printk(KERN_ERR PFX "specify MSS port\n"); 508 return 0; 509 } 510 if (port[dev] != 0x220 && port[dev] != 0x240) { 511 printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); 512 return 0; 513 } 514 if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { 515 printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); 516 return 0; 517 } 518 if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { 519 printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); 520 return 0; 521 } 522 if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { 523 printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); 524 return 0; 525 } 526 if (mpu_port[dev] != SNDRV_AUTO_PORT && 527 (mpu_port[dev] & ~0x30L) != 0x300) { 528 printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", 529 mpu_port[dev]); 530 return 0; 531 } 532 if (mpu_port[dev] != SNDRV_AUTO_PORT && 533 mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && 534 !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { 535 printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); 536 return 0; 537 } 538 return 1; 539 } 540 541 static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) 542 { 543 static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 }; 544 static int possible_dmas[] = { 1, 3, 0, -1 }; 545 int err; 546 int xirq = irq[dev]; 547 int xdma = dma[dev]; 548 struct snd_card *card; 549 struct snd_wss *chip; 550 struct snd_opl3 *opl3; 551 char __iomem **vport; 552 char __iomem *vmss_port; 553 554 555 err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport), 556 &card); 557 if (err < 0) 558 return err; 559 560 vport = card->private_data; 561 if (xirq == SNDRV_AUTO_IRQ) { 562 xirq = snd_legacy_find_free_irq(possible_irqs); 563 if (xirq < 0) { 564 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); 565 err = -EBUSY; 566 goto err_exit; 567 } 568 } 569 570 if (xdma == SNDRV_AUTO_DMA) { 571 xdma = snd_legacy_find_free_dma(possible_dmas); 572 if (xdma < 0) { 573 snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); 574 err = -EBUSY; 575 goto err_exit; 576 } 577 } 578 579 if (!request_region(port[dev], 0x10, DRV_NAME)) { 580 snd_printk(KERN_ERR PFX 581 "I/O port region is already in use.\n"); 582 err = -EBUSY; 583 goto err_exit; 584 } 585 *vport = devm_ioport_map(devptr, port[dev], 0x10); 586 if (*vport == NULL) { 587 snd_printk(KERN_ERR PFX 588 "I/O port cannot be iomaped.\n"); 589 err = -EBUSY; 590 goto err_unmap1; 591 } 592 593 /* to make it marked as used */ 594 if (!request_region(mss_port[dev], 4, DRV_NAME)) { 595 snd_printk(KERN_ERR PFX 596 "SC-6000 port I/O port region is already in use.\n"); 597 err = -EBUSY; 598 goto err_unmap1; 599 } 600 vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); 601 if (!vmss_port) { 602 snd_printk(KERN_ERR PFX 603 "MSS port I/O cannot be iomaped.\n"); 604 err = -EBUSY; 605 goto err_unmap2; 606 } 607 608 snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", 609 port[dev], xirq, xdma, 610 mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); 611 612 err = sc6000_init_board(*vport, vmss_port, dev); 613 if (err < 0) 614 goto err_unmap2; 615 616 err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1, 617 WSS_HW_DETECT, 0, &chip); 618 if (err < 0) 619 goto err_unmap2; 620 621 err = snd_wss_pcm(chip, 0, NULL); 622 if (err < 0) { 623 snd_printk(KERN_ERR PFX 624 "error creating new WSS PCM device\n"); 625 goto err_unmap2; 626 } 627 err = snd_wss_mixer(chip); 628 if (err < 0) { 629 snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); 630 goto err_unmap2; 631 } 632 err = snd_sc6000_mixer(chip); 633 if (err < 0) { 634 snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); 635 goto err_unmap2; 636 } 637 if (snd_opl3_create(card, 638 0x388, 0x388 + 2, 639 OPL3_HW_AUTO, 0, &opl3) < 0) { 640 snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", 641 0x388, 0x388 + 2); 642 } else { 643 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); 644 if (err < 0) 645 goto err_unmap2; 646 } 647 648 if (mpu_port[dev] != SNDRV_AUTO_PORT) { 649 if (mpu_irq[dev] == SNDRV_AUTO_IRQ) 650 mpu_irq[dev] = -1; 651 if (snd_mpu401_uart_new(card, 0, 652 MPU401_HW_MPU401, 653 mpu_port[dev], 0, 654 mpu_irq[dev], IRQF_DISABLED, 655 NULL) < 0) 656 snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", 657 mpu_port[dev]); 658 } 659 660 strcpy(card->driver, DRV_NAME); 661 strcpy(card->shortname, "SC-6000"); 662 sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", 663 mss_port[dev], xirq, xdma); 664 665 snd_card_set_dev(card, devptr); 666 667 err = snd_card_register(card); 668 if (err < 0) 669 goto err_unmap2; 670 671 dev_set_drvdata(devptr, card); 672 return 0; 673 674 err_unmap2: 675 sc6000_setup_board(*vport, 0); 676 release_region(mss_port[dev], 4); 677 err_unmap1: 678 release_region(port[dev], 0x10); 679 err_exit: 680 snd_card_free(card); 681 return err; 682 } 683 684 static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) 685 { 686 struct snd_card *card = dev_get_drvdata(devptr); 687 char __iomem **vport = card->private_data; 688 689 if (sc6000_setup_board(*vport, 0) < 0) 690 snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n"); 691 692 release_region(port[dev], 0x10); 693 release_region(mss_port[dev], 4); 694 695 dev_set_drvdata(devptr, NULL); 696 snd_card_free(card); 697 return 0; 698 } 699 700 static struct isa_driver snd_sc6000_driver = { 701 .match = snd_sc6000_match, 702 .probe = snd_sc6000_probe, 703 .remove = __devexit_p(snd_sc6000_remove), 704 /* FIXME: suspend/resume */ 705 .driver = { 706 .name = DRV_NAME, 707 }, 708 }; 709 710 711 static int __init alsa_card_sc6000_init(void) 712 { 713 return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS); 714 } 715 716 static void __exit alsa_card_sc6000_exit(void) 717 { 718 isa_unregister_driver(&snd_sc6000_driver); 719 } 720 721 module_init(alsa_card_sc6000_init) 722 module_exit(alsa_card_sc6000_exit) 723