X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fisa%2Fgus%2Finterwave.c;h=4298d339e786fff55ccd1c090476b0bcf17d9441;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=b2c3544bf77b24c7cf7e22013d433bb33b2cfb55;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index b2c3544bf..4298d339e 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -23,36 +23,36 @@ */ #include -#include -#include #include +#include +#include +#include #include #include #include +#include #include #include #include #ifdef SNDRV_STB #include #endif -#define SNDRV_LEGACY_AUTO_PROBE #define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_DMA #include MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_CLASSES("{sound}"); MODULE_LICENSE("GPL"); #ifndef SNDRV_STB MODULE_DESCRIPTION("AMD InterWave"); -MODULE_DEVICES("{{Gravis,UltraSound Plug & Play}," +MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play}," "{STB,SoundRage32}," "{MED,MED3210}," "{Dynasonix,Dynasonix Pro}," "{Panasonic,PCA761AW}}"); #else MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T"); -MODULE_DEVICES("{{AMD,InterWave STB with TEA6330T}}"); +MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}"); #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ @@ -73,57 +73,56 @@ static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +#ifdef SNDRV_STB +#define PFX "interwave-stb: " +#define INTERWAVE_DRIVER "snd_interwave_stb" +#define INTERWAVE_PNP_DRIVER "interwave-stb" +#else +#define PFX "interwave: " +#define INTERWAVE_DRIVER "snd_interwave" +#define INTERWAVE_PNP_DRIVER "interwave" +#endif + +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for InterWave soundcard."); -MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for InterWave soundcard."); -MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable InterWave soundcard."); -MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); #ifdef CONFIG_PNP -module_param_array(isapnp, bool, boot_devs, 0444); +module_param_array(isapnp, bool, NULL, 0444); MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC); #endif -module_param_array(port, long, boot_devs, 0444); +module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for InterWave driver."); -MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list"); #ifdef SNDRV_STB -module_param_array(port_tc, long, boot_devs, 0444); +module_param_array(port_tc, long, NULL, 0444); MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver."); -MODULE_PARM_SYNTAX(port_tc, SNDRV_ENABLED ",allows:{{0x350,0x380,0x10}},dialog:list"); #endif -module_param_array(irq, int, boot_devs, 0444); +module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for InterWave driver."); -MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list"); -module_param_array(dma1, int, boot_devs, 0444); +module_param_array(dma1, int, NULL, 0444); MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver."); -MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC); -module_param_array(dma2, int, boot_devs, 0444); +module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver."); -MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC); -module_param_array(joystick_dac, int, boot_devs, 0444); +module_param_array(joystick_dac, int, NULL, 0444); MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver."); -MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}"); -module_param_array(midi, int, boot_devs, 0444); +module_param_array(midi, int, NULL, 0444); MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver."); -MODULE_PARM_SYNTAX(midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC); -module_param_array(pcm_channels, int, boot_devs, 0444); +module_param_array(pcm_channels, int, NULL, 0444); MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver."); -MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}"); -module_param_array(effect, int, boot_devs, 0444); +module_param_array(effect, int, NULL, 0444); MODULE_PARM_DESC(effect, "Effects enable for InterWave driver."); -MODULE_PARM_SYNTAX(effect, SNDRV_ENABLED "," SNDRV_ENABLE_DESC); + +static struct platform_device *platform_devices[SNDRV_CARDS]; +static int pnp_registered; struct snd_interwave { int irq; - snd_card_t *card; - snd_gus_card_t *gus; - cs4231_t *cs4231; + struct snd_card *card; + struct snd_gus_card *gus; + struct snd_cs4231 *cs4231; #ifdef SNDRV_STB struct resource *i2c_res; #endif @@ -137,7 +136,6 @@ struct snd_interwave { #endif }; -static snd_card_t *snd_interwave_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; #ifdef CONFIG_PNP @@ -169,7 +167,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_interwave_pnpids); #ifdef SNDRV_STB -static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data) +static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int data) { unsigned long port = bus->private_value; @@ -180,7 +178,7 @@ static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data) udelay(10); } -static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus) +static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) { unsigned long port = bus->private_value; unsigned char res; @@ -192,7 +190,7 @@ static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus) return res; } -static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack) +static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) { unsigned long port = bus->private_value; unsigned char res; @@ -206,19 +204,19 @@ static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack) return res; } -static snd_i2c_bit_ops_t snd_interwave_i2c_bit_ops = { +static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = { .setlines = snd_interwave_i2c_setlines, .getclock = snd_interwave_i2c_getclockline, .getdata = snd_interwave_i2c_getdataline, }; static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard, - snd_gus_card_t * gus, int dev, - snd_i2c_bus_t **rbus) + struct snd_gus_card * gus, int dev, + struct snd_i2c_bus **rbus) { unsigned long port; - snd_i2c_bus_t *bus; - snd_card_t *card = iwcard->card; + struct snd_i2c_bus *bus; + struct snd_card *card = iwcard->card; char name[32]; int err; @@ -255,47 +253,29 @@ static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard, #endif static int __devinit snd_interwave_detect(struct snd_interwave *iwcard, - snd_gus_card_t * gus, + struct snd_gus_card * gus, int dev #ifdef SNDRV_STB - , snd_i2c_bus_t **rbus + , struct snd_i2c_bus **rbus #endif ) { unsigned long flags; unsigned char rev1, rev2; + int d; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ -#ifdef CONFIG_SND_DEBUG_DETECT - { - int d; - - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - } -#else - if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0) + if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { + snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; -#endif + } udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160); -#ifdef CONFIG_SND_DEBUG_DETECT - { - int d; - - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - } -#else - if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1) + if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { + snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; -#endif - + } spin_lock_irqsave(&gus->reg_lock, flags); rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1); @@ -341,7 +321,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs return IRQ_RETVAL(handled); } -static void __devinit snd_interwave_reset(snd_gus_card_t * gus) +static void __devinit snd_interwave_reset(struct snd_gus_card * gus) { snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00); udelay(160); @@ -349,7 +329,7 @@ static void __devinit snd_interwave_reset(snd_gus_card_t * gus) udelay(160); } -static void __devinit snd_interwave_bank_sizes(snd_gus_card_t * gus, int *sizes) +static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes) { unsigned int idx; unsigned int local; @@ -398,7 +378,7 @@ struct rom_hdr { /* 511 */ unsigned char csum; }; -static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) +static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) { static unsigned int lmc[13] = { @@ -411,8 +391,8 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) int bank_pos, pages; unsigned int i, lmct; int psizes[4]; + unsigned char iwave[8]; unsigned char csum; - struct rom_hdr romh; snd_interwave_reset(gus); snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); /* enhanced mode */ @@ -434,7 +414,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) #if 0 printk("lmct = 0x%08x\n", lmct); #endif - for (i = 0; i < sizeof(lmc) / sizeof(unsigned int); i++) + for (i = 0; i < ARRAY_SIZE(lmc); i++) if (lmct == lmc[i]) { #if 0 printk("found !!! %i\n", i); @@ -443,7 +423,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) snd_interwave_bank_sizes(gus, psizes); break; } - if (i >= sizeof(lmc) / sizeof(unsigned int) && !gus->gf1.enh_mode) + if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode) snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2); for (i = 0; i < 4; i++) { gus->gf1.mem_alloc.banks_8[i].address = @@ -461,33 +441,29 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) gus->gf1.rom_banks = 0; gus->gf1.rom_memory = 0; for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) { - for (i = 0; i < sizeof(struct rom_hdr); i++) - *(((unsigned char *) &romh) + i) = snd_gf1_peek(gus, i + bank_pos); + for (i = 0; i < 8; ++i) + iwave[i] = snd_gf1_peek(gus, bank_pos + i); #ifdef CONFIG_SND_DEBUG_ROM - printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, - romh.iwave[0], romh.iwave[1], romh.iwave[2], romh.iwave[3], - romh.iwave[4], romh.iwave[5], romh.iwave[6], romh.iwave[7]); + printk(KERN_DEBUG "ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, + iwave[0], iwave[1], iwave[2], iwave[3], + iwave[4], iwave[5], iwave[6], iwave[7]); #endif - if (strncmp(romh.iwave, "INTRWAVE", 8)) + if (strncmp(iwave, "INTRWAVE", 8)) continue; /* first check */ csum = 0; - for (i = 0; i < sizeof(struct rom_hdr) - 1; i++) - csum += *(((unsigned char *) &romh) + i); + for (i = 0; i < sizeof(struct rom_hdr); i++) + csum += snd_gf1_peek(gus, bank_pos + i); #ifdef CONFIG_SND_DEBUG_ROM - printk("ROM checksum = 0x%x == 0x%x (computed)\n", romh.csum, (unsigned char) (256 - csum)); + printk(KERN_DEBUG "ROM checksum = 0x%x (computed)\n", csum); #endif - if (256 - csum != romh.csum) + if (csum != 0) continue; /* not valid rom */ gus->gf1.rom_banks++; gus->gf1.rom_present |= 1 << (bank_pos >> 22); -#ifdef SNDRV_LITTLE_ENDIAN - gus->gf1.rom_memory = romh.rom_size; -#else - gus->gf1.rom_memory = ((romh.rom_size >> 24) & 0x000000ff) | - ((romh.rom_size >> 8) & 0x0000ff00) | - ((romh.rom_size << 8) & 0x00ff0000) | - ((romh.rom_size << 24) & 0xff000000); -#endif + gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) | + (snd_gf1_peek(gus, bank_pos + 41) << 8) | + (snd_gf1_peek(gus, bank_pos + 42) << 16) | + (snd_gf1_peek(gus, bank_pos + 43) << 24); } #if 0 if (gus->gf1.rom_memory > 0) { @@ -501,7 +477,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) snd_interwave_reset(gus); } -static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus) +static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus) { unsigned long flags; @@ -523,19 +499,17 @@ static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus) } -#define INTERWAVE_CONTROLS (sizeof(snd_interwave_controls)/sizeof(snd_kcontrol_new_t)) - -static snd_kcontrol_new_t snd_interwave_controls[] = { +static struct snd_kcontrol_new snd_interwave_controls[] = { CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) }; -static int __devinit snd_interwave_mixer(cs4231_t *chip) +static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip) { - snd_card_t *card = chip->card; - snd_ctl_elem_id_t id1, id2; + struct snd_card *card = chip->card; + struct snd_ctl_elem_id id1, id2; unsigned int idx; int err; @@ -552,7 +526,7 @@ static int __devinit snd_interwave_mixer(cs4231_t *chip) return err; #endif /* add new master and mic controls */ - for (idx = 0; idx < INTERWAVE_CONTROLS; idx++) + for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) return err; snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); @@ -664,110 +638,77 @@ static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, } #endif /* CONFIG_PNP */ -static void snd_interwave_free(snd_card_t *card) +static void snd_interwave_free(struct snd_card *card) { - struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data; + struct snd_interwave *iwcard = card->private_data; if (iwcard == NULL) return; #ifdef SNDRV_STB - if (iwcard->i2c_res) { - release_resource(iwcard->i2c_res); - kfree_nocheck(iwcard->i2c_res); - } + release_and_free_resource(iwcard->i2c_res); #endif if (iwcard->irq >= 0) free_irq(iwcard->irq, (void *)iwcard); } -static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) +static struct snd_card *snd_interwave_card_new(int dev) { - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; - int xirq, xdma1, xdma2; - snd_card_t *card; + struct snd_card *card; struct snd_interwave *iwcard; - cs4231_t *cs4231; - snd_gus_card_t *gus; -#ifdef SNDRV_STB - snd_i2c_bus_t *i2c_bus; -#endif - snd_pcm_t *pcm; - char *str; - int err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_interwave)); if (card == NULL) - return -ENOMEM; - iwcard = (struct snd_interwave *)card->private_data; + return NULL; + iwcard = card->private_data; iwcard->card = card; iwcard->irq = -1; card->private_free = snd_interwave_free; -#ifdef CONFIG_PNP - if (isapnp[dev]) { - if (snd_interwave_pnp(dev, iwcard, pcard, pid)) { - snd_card_free(card); - return -ENODEV; - } - snd_card_set_dev(card, &pcard->card->dev); - } + return card; +} + +static int __devinit snd_interwave_probe(struct snd_card *card, int dev) +{ + int xirq, xdma1, xdma2; + struct snd_interwave *iwcard = card->private_data; + struct snd_cs4231 *cs4231; + struct snd_gus_card *gus; +#ifdef SNDRV_STB + struct snd_i2c_bus *i2c_bus; #endif + struct snd_pcm *pcm; + char *str; + int err; + xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_card_free(card); - snd_printk("unable to find a free IRQ\n"); - return -EBUSY; - } - } xdma1 = dma1[dev]; - if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_card_free(card); - snd_printk("unable to find a free DMA1\n"); - return -EBUSY; - } - } xdma2 = dma2[dev]; - if (xdma2 == SNDRV_AUTO_DMA) { - if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_card_free(card); - snd_printk("unable to find a free DMA2\n"); - return -EBUSY; - } - } if ((err = snd_gus_create(card, port[dev], -xirq, xdma1, xdma2, 0, 32, - pcm_channels[dev], effect[dev], &gus)) < 0) { - snd_card_free(card); + pcm_channels[dev], effect[dev], &gus)) < 0) return err; - } + if ((err = snd_interwave_detect(iwcard, gus, dev #ifdef SNDRV_STB , &i2c_bus #endif - )) < 0) { - snd_card_free(card); + )) < 0) return err; - } + iwcard->gus_status_reg = gus->gf1.reg_irqstat; iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; snd_interwave_init(dev, gus); snd_interwave_detect_memory(gus); - if ((err = snd_gus_initialize(gus)) < 0) { - snd_card_free(card); + if ((err = snd_gus_initialize(gus)) < 0) return err; - } - if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) { - snd_card_free(card); - snd_printk("unable to grab IRQ %d\n", xirq); + if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, + "InterWave", iwcard)) { + snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); return -EBUSY; } iwcard->irq = xirq; @@ -779,65 +720,51 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, CS4231_HWSHARE_IRQ | CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2, - &cs4231)) < 0) { - snd_card_free(card); + &cs4231)) < 0) return err; - } - if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) { - snd_card_free(card); + + if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) return err; - } + sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); strcat(pcm->name, " (codec)"); - if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) { - snd_card_free(card); + + if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) return err; - } - if ((err = snd_cs4231_mixer(cs4231)) < 0) { - snd_card_free(card); + + if ((err = snd_cs4231_mixer(cs4231)) < 0) return err; - } + if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) { - snd_card_free(card); + if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) return err; - } } - if ((err = snd_interwave_mixer(cs4231)) < 0) { - snd_card_free(card); + if ((err = snd_interwave_mixer(cs4231)) < 0) return err; - } + #ifdef SNDRV_STB { - snd_ctl_elem_id_t id1, id2; + struct snd_ctl_elem_id id1, id2; memset(&id1, 0, sizeof(id1)); memset(&id2, 0, sizeof(id2)); id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; strcpy(id1.name, "Master Playback Switch"); strcpy(id2.name, id1.name); id2.index = 1; - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_card_free(card); + if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) return err; - } strcpy(id1.name, "Master Playback Volume"); strcpy(id2.name, id1.name); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_card_free(card); + if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) return err; - } - if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) { - snd_card_free(card); + if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) return err; - } } #endif gus->uart_enable = midi[dev]; - if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) { - snd_card_free(card); + if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) return err; - } #ifndef SNDRV_STB str = "AMD InterWave"; @@ -856,119 +783,192 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); + if ((err = snd_card_register(card)) < 0) return err; - } iwcard->cs4231 = cs4231; iwcard->gus = gus; - if (pcard) - pnp_set_card_drvdata(pcard, card); - else - snd_interwave_legacy[dev++] = card; return 0; } -static int __devinit snd_interwave_probe_legacy_port(unsigned long xport) +static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) { - static int dev; - int res; + struct snd_card *card; + int err; - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) - continue; -#ifdef CONFIG_PNP - if (isapnp[dev]) - continue; -#endif - port[dev] = xport; - res = snd_interwave_probe(dev, NULL, NULL); - if (res < 0) - port[dev] = SNDRV_AUTO_PORT; - return res; + card = snd_interwave_card_new(dev); + if (! card) + return -ENOMEM; + + snd_card_set_dev(card, &devptr->dev); + if ((err = snd_interwave_probe(card, dev)) < 0) { + snd_card_free(card); + return err; } - return -ENODEV; + platform_set_drvdata(devptr, card); + return 0; +} + +static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) +{ + int dev = pdev->id; + int err; + static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; + static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; + + if (irq[dev] == SNDRV_AUTO_IRQ) { + if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { + snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + return -EBUSY; + } + } + if (dma1[dev] == SNDRV_AUTO_DMA) { + if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); + return -EBUSY; + } + } + if (dma2[dev] == SNDRV_AUTO_DMA) { + if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); + return -EBUSY; + } + } + + if (port[dev] != SNDRV_AUTO_PORT) + return snd_interwave_nonpnp_probe1(dev, pdev); + else { + static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; + int i; + for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { + port[dev] = possible_ports[i]; + err = snd_interwave_nonpnp_probe1(dev, pdev); + if (! err) + return 0; + } + return err; + } +} + +static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr) +{ + snd_card_free(platform_get_drvdata(devptr)); + platform_set_drvdata(devptr, NULL); + return 0; } +static struct platform_driver snd_interwave_driver = { + .probe = snd_interwave_nonpnp_probe, + .remove = __devexit_p(snd_interwave_nonpnp_remove), + /* FIXME: suspend,resume */ + .driver = { + .name = INTERWAVE_DRIVER + }, +}; + #ifdef CONFIG_PNP +static unsigned int __devinitdata interwave_pnp_devices; -static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) +static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, + const struct pnp_card_device_id *pid) { static int dev; + struct snd_card *card; int res; for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || !isapnp[dev]) - continue; - res = snd_interwave_probe(dev, card, id); - if (res < 0) - return res; - dev++; - return 0; - } - - return -ENODEV; + if (enable[dev] && isapnp[dev]) + break; + } + if (dev >= SNDRV_CARDS) + return -ENODEV; + + card = snd_interwave_card_new(dev); + if (! card) + return -ENOMEM; + + if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { + snd_card_free(card); + return res; + } + snd_card_set_dev(card, &pcard->card->dev); + if ((res = snd_interwave_probe(card, dev)) < 0) { + snd_card_free(card); + return res; + } + pnp_set_card_drvdata(pcard, card); + dev++; + interwave_pnp_devices++; + return 0; } static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard) { - snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard); - - snd_card_disconnect(card); - snd_card_free_in_thread(card); + snd_card_free(pnp_get_card_drvdata(pcard)); + pnp_set_card_drvdata(pcard, NULL); } static struct pnp_card_driver interwave_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, - .name = "interwave", + .name = INTERWAVE_PNP_DRIVER, .id_table = snd_interwave_pnpids, .probe = snd_interwave_pnp_detect, .remove = __devexit_p(snd_interwave_pnp_remove), + /* FIXME: suspend,resume */ }; #endif /* CONFIG_PNP */ +static void __init_or_module snd_interwave_unregister_all(void) +{ + int i; + + if (pnp_registered) + pnp_unregister_card_driver(&interwave_pnpc_driver); + for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) + platform_device_unregister(platform_devices[i]); + platform_driver_unregister(&snd_interwave_driver); +} + static int __init alsa_card_interwave_init(void) { - int cards = 0, i; - static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1}; - int dev; + int i, err, cards = 0; - for (dev = 0; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT) + if ((err = platform_driver_register(&snd_interwave_driver)) < 0) + return err; + + for (i = 0; i < SNDRV_CARDS; i++) { + struct platform_device *device; + if (! enable[i]) continue; #ifdef CONFIG_PNP - if (isapnp[dev]) + if (isapnp[i]) continue; #endif - if (!snd_interwave_probe(dev, NULL, NULL)) { - cards++; + device = platform_device_register_simple(INTERWAVE_DRIVER, + i, NULL, 0); + if (IS_ERR(device)) + continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); continue; } -#ifdef MODULE - printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]); -#endif + platform_devices[i] = device; + cards++; } - /* legacy auto configured cards */ - i = snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port); - if (i > 0) - cards += i; -#ifdef CONFIG_PNP + /* ISA PnP cards */ - i = pnp_register_card_driver(&interwave_pnpc_driver); - if (i > 0) - cards += i; -#endif + err = pnp_register_card_driver(&interwave_pnpc_driver); + if (!err) { + pnp_registered = 1; + cards += interwave_pnp_devices;; + } if (!cards) { -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&interwave_pnpc_driver); -#endif #ifdef MODULE printk(KERN_ERR "InterWave soundcard not found or device busy\n"); #endif + snd_interwave_unregister_all(); return -ENODEV; } return 0; @@ -976,14 +976,7 @@ static int __init alsa_card_interwave_init(void) static void __exit alsa_card_interwave_exit(void) { - int dev; - -#ifdef CONFIG_PNP - /* PnP cards first */ - pnp_unregister_card_driver(&interwave_pnpc_driver); -#endif - for (dev = 0; dev < SNDRV_CARDS; dev++) - snd_card_free(snd_interwave_legacy[dev]); + snd_interwave_unregister_all(); } module_init(alsa_card_interwave_init)