📄 interwave.c
字号:
static void snd_interwave_free(snd_card_t *card){ struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data; if (iwcard == NULL) return;#ifdef __ISAPNP__ snd_interwave_deactivate(iwcard);#endif#ifdef SNDRV_STB if (iwcard->i2c_res) { release_resource(iwcard->i2c_res); kfree_nocheck(iwcard->i2c_res); }#endif if (iwcard->irq >= 0) free_irq(iwcard->irq, (void *)iwcard);}static int __init snd_interwave_probe(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 irq, dma1, dma2; snd_card_t *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(snd_index[dev], snd_id[dev], THIS_MODULE, sizeof(struct snd_interwave)); if (card == NULL) return -ENOMEM; iwcard = (struct snd_interwave *)card->private_data; iwcard->card = card; iwcard->irq = -1; card->private_free = snd_interwave_free;#ifdef __ISAPNP__ if (snd_isapnp[dev] && snd_interwave_isapnp(dev, iwcard)) { snd_card_free(card); return -ENODEV; }#endif irq = snd_irq[dev]; if (irq == SNDRV_AUTO_IRQ) { if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { snd_card_free(card); snd_printk("unable to find a free IRQ\n"); return -EBUSY; } } dma1 = snd_dma1[dev]; if (dma1 == SNDRV_AUTO_DMA) { if ((dma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_card_free(card); snd_printk("unable to find a free DMA1\n"); return -EBUSY; } } dma2 = snd_dma2[dev]; if (dma2 == SNDRV_AUTO_DMA) { if ((dma2 = 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, snd_port[dev], -irq, dma1, dma2, 0, 32, snd_pcm_channels[dev], snd_effect[dev], &gus)) < 0) { snd_card_free(card); return err; } if ((err = snd_interwave_detect(iwcard, gus, dev#ifdef SNDRV_STB , &i2c_bus#endif )) < 0) { snd_card_free(card); 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); return err; } if (request_irq(irq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) { snd_card_free(card); snd_printk("unable to grab IRQ %d\n", irq); return -EBUSY; } iwcard->irq = irq; if ((err = snd_cs4231_create(card, gus->gf1.port + 0x10c, -1, irq, dma2 < 0 ? dma1 : dma2, dma1, CS4231_HW_INTERWAVE, CS4231_HWSHARE_IRQ | CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2, &cs4231)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) { snd_card_free(card); return err; } sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); strcat(pcm->name, " (chip)"); if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs4231_mixer(cs4231)) < 0) { snd_card_free(card); return err; } if (snd_pcm_channels[dev] > 0) { if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) { snd_card_free(card); return err; } } if ((err = snd_interwave_mixer(cs4231)) < 0) { snd_card_free(card); return err; }#ifdef SNDRV_STB { snd_ctl_elem_id_t 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); 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); return err; } if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) { snd_card_free(card); return err; } }#endif gus->uart_enable = snd_midi[dev]; if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) { snd_card_free(card); return err; }#ifndef SNDRV_STB str = "AMD InterWave"; if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8) str = "Dynasonic 3-D";#else str = "InterWave STB";#endif strcpy(card->driver, str); strcpy(card->shortname, str); sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d", str, gus->gf1.port, irq, dma1); if (dma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", dma2); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } iwcard->cs4231 = cs4231; iwcard->gus = gus; snd_interwave_cards[dev++] = card; return 0;}static int __init snd_interwave_probe_legacy_port(unsigned long port){ static int dev; int res; for ( ; dev < SNDRV_CARDS; dev++) { if (!snd_enable[dev] || snd_port[dev] != SNDRV_AUTO_PORT) continue;#ifdef __ISAPNP__ if (snd_isapnp[dev]) continue;#endif snd_port[dev] = port; res = snd_interwave_probe(dev); if (res < 0) snd_port[dev] = SNDRV_AUTO_PORT; return res; } return -ENODEV;}#ifdef __ISAPNP__static int __init snd_interwave_isapnp_detect(struct isapnp_card *card, const struct isapnp_card_id *id){ static int dev; int res; for ( ; dev < SNDRV_CARDS; dev++) { if (!snd_enable[dev] || !snd_isapnp[dev]) continue; snd_interwave_isapnp_cards[dev] = card; snd_interwave_isapnp_id[dev] = id; res = snd_interwave_probe(dev); if (res < 0) return res; dev++; return 0; } return -ENODEV;}#endif /* __ISAPNP__ */static int __init alsa_card_interwave_init(void){ int cards = 0; static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1}; int dev; for (dev = 0; dev < SNDRV_CARDS; dev++) { if (!snd_enable[dev] || snd_port[dev] == SNDRV_AUTO_PORT) continue;#ifdef __ISAPNP__ if (snd_isapnp[dev]) continue;#endif if (!snd_interwave_probe(dev)) { cards++; continue; }#ifdef MODULE printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);#endif } /* legacy auto configured cards */ cards += snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port);#ifdef __ISAPNP__ /* ISA PnP cards */ cards += isapnp_probe_cards(snd_interwave_pnpids, snd_interwave_isapnp_detect);#endif if (!cards) {#ifdef MODULE printk(KERN_ERR "InterWave soundcard not found or device busy\n");#endif return -ENODEV; } return 0;}static void __exit alsa_card_interwave_exit(void){ int dev; for (dev = 0; dev < SNDRV_CARDS; dev++) snd_card_free(snd_interwave_cards[dev]);}module_init(alsa_card_interwave_init)module_exit(alsa_card_interwave_exit)#ifndef MODULE/* format is: snd-interwave=snd_enable,snd_index,snd_id,snd_isapnp, snd_port[,snd_port_tc],snd_irq, snd_dma1,snd_dma2, snd_joystick_dac,snd_midi, snd_pcm_channels,snd_effect */static int __init alsa_card_interwave_setup(char *str){ static unsigned __initdata nr_dev = 0; int __attribute__ ((__unused__)) pnp = INT_MAX; if (nr_dev >= SNDRV_CARDS) return 0; (void)(get_option(&str,&snd_enable[nr_dev]) == 2 && get_option(&str,&snd_index[nr_dev]) == 2 && get_id(&str,&snd_id[nr_dev]) == 2 && get_option(&str,&pnp) == 2 && get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&#ifdef SNDRV_STB get_option(&str,(int *)&snd_port_tc[nr_dev]) == 2 &&#endif get_option(&str,&snd_irq[nr_dev]) == 2 && get_option(&str,&snd_dma1[nr_dev]) == 2 && get_option(&str,&snd_dma2[nr_dev]) == 2 && get_option(&str,&snd_joystick_dac[nr_dev]) == 2 && get_option(&str,&snd_midi[nr_dev]) == 2 && get_option(&str,&snd_pcm_channels[nr_dev]) == 2 && get_option(&str,&snd_effect[nr_dev]) == 2);#ifdef __ISAPNP__ if (pnp != INT_MAX) snd_isapnp[nr_dev] = pnp;#endif nr_dev++; return 1;}#ifndef SNDRV_STB__setup("snd-interwave=", alsa_card_interwave_setup);#else__setup("snd-interwave-stb=", alsa_card_interwave_setup);#endif#endif /* ifndef MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -