X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fisa%2Fsb%2Fsb8.c;h=268ebd34703ec1fa821b5c31083b16e7bd6bb3a8;hb=refs%2Fheads%2Fvserver;hp=480e1c6b84eee9afcf65e821640c3b864c162ec1;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 480e1c6b8..268ebd347 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -21,22 +21,20 @@ #include #include +#include +#include #include #include +#include #include #include #include -#define SNDRV_LEGACY_AUTO_PROBE -#define SNDRV_GET_ID #include -#define chip_t sb_t - MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); MODULE_LICENSE("GPL"); -MODULE_CLASSES("{sound}"); -MODULE_DEVICES("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); +MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -45,34 +43,29 @@ static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3 */ -MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard."); -MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); -MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s"); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard."); -MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); -MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard."); -MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); -MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for SB8 driver."); -MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC); -MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for SB8 driver."); -MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC); -MODULE_PARM(dma8, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +module_param_array(dma8, int, NULL, 0444); MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver."); -MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC); + +static struct platform_device *devices[SNDRV_CARDS]; struct snd_sb8 { struct resource *fm_res; /* used to block FM i/o region for legacy cards */ + struct snd_sb *chip; }; -static snd_card_t *snd_sb8_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - -static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id) { - sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE); + struct snd_sb *chip = dev_id; if (chip->open & SB_OPEN_PCM) { return snd_sb8dsp_interrupt(chip); @@ -81,89 +74,104 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs } } -static void snd_sb8_free(snd_card_t *card) +static void snd_sb8_free(struct snd_card *card) { struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data; if (acard == NULL) return; - if (acard->fm_res) { - release_resource(acard->fm_res); - kfree_nocheck(acard->fm_res); - } + release_and_free_resource(acard->fm_res); } -static int __init snd_sb8_probe(int dev) +static int __init snd_sb8_probe(struct platform_device *pdev) { - sb_t *chip; - snd_card_t *card; + int dev = pdev->id; + struct snd_sb *chip; + struct snd_card *card; struct snd_sb8 *acard; - opl3_t *opl3; + struct snd_opl3 *opl3; int err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_sb8)); if (card == NULL) return -ENOMEM; - acard = (struct snd_sb8 *)card->private_data; + acard = card->private_data; card->private_free = snd_sb8_free; /* block the 0x388 port to avoid PnP conflicts */ acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); - if ((err = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip)) < 0) { - snd_card_free(card); - return err; + if (port[dev] != SNDRV_AUTO_PORT) { + if ((err = snd_sbdsp_create(card, port[dev], irq[dev], + snd_sb8_interrupt, + dma8[dev], + -1, + SB_HW_AUTO, + &chip)) < 0) + goto _err; + } else { + /* auto-probe legacy ports */ + static unsigned long possible_ports[] = { + 0x220, 0x240, 0x260, + }; + int i; + for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { + err = snd_sbdsp_create(card, possible_ports[i], + irq[dev], + snd_sb8_interrupt, + dma8[dev], + -1, + SB_HW_AUTO, + &chip); + if (err >= 0) { + port[dev] = possible_ports[i]; + break; + } + } + if (i >= ARRAY_SIZE(possible_ports)) + goto _err; } + acard->chip = chip; + if (chip->hardware >= SB_HW_16) { - snd_card_free(card); if (chip->hardware == SB_HW_ALS100) - snd_printdd("ALS100 chip detected at 0x%lx, try snd-als100 module\n", + snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n", port[dev]); else - snd_printdd("SB 16 chip detected at 0x%lx, try snd-sb16 module\n", - port[dev]); - return -ENODEV; + snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", + port[dev]); + err = -ENODEV; + goto _err; } - if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_sbmixer_new(chip)) < 0) { - snd_card_free(card); - return err; - } + if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) + goto _err; + + if ((err = snd_sbmixer_new(chip)) < 0) + goto _err; + if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) { if ((err = snd_opl3_create(card, chip->port + 8, 0, OPL3_HW_AUTO, 1, &opl3)) < 0) { - snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8); + snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); } } else { if ((err = snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_AUTO, 1, &opl3)) < 0) { - snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n", + snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", chip->port, chip->port + 2); } } if (err >= 0) { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } + if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) + goto _err; } - if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } + if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) + goto _err; strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); strcpy(card->shortname, chip->name); @@ -171,50 +179,105 @@ static int __init snd_sb8_probe(int dev) chip->name, chip->port, irq[dev], dma8[dev]); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - snd_sb8_cards[dev] = card; + + snd_card_set_dev(card, &pdev->dev); + + if ((err = snd_card_register(card)) < 0) + goto _err; + + platform_set_drvdata(pdev, card); + return 0; + + _err: + snd_card_free(card); + return err; +} + +static int snd_sb8_remove(struct platform_device *pdev) +{ + snd_card_free(platform_get_drvdata(pdev)); + platform_set_drvdata(pdev, NULL); + return 0; +} + +#ifdef CONFIG_PM +static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state) +{ + struct snd_card *card = platform_get_drvdata(dev); + struct snd_sb8 *acard = card->private_data; + struct snd_sb *chip = acard->chip; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + snd_pcm_suspend_all(chip->pcm); + snd_sbmixer_suspend(chip); return 0; } -static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport) +static int snd_sb8_resume(struct platform_device *dev) { - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) - continue; - port[dev] = xport; - res = snd_sb8_probe(dev); - if (res < 0) - port[dev] = SNDRV_AUTO_PORT; - return res; - } - return -ENODEV; + struct snd_card *card = platform_get_drvdata(dev); + struct snd_sb8 *acard = card->private_data; + struct snd_sb *chip = acard->chip; + + snd_sbdsp_reset(chip); + snd_sbmixer_resume(chip); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif + +#define SND_SB8_DRIVER "snd_sb8" + +static struct platform_driver snd_sb8_driver = { + .probe = snd_sb8_probe, + .remove = snd_sb8_remove, +#ifdef CONFIG_PM + .suspend = snd_sb8_suspend, + .resume = snd_sb8_resume, +#endif + .driver = { + .name = SND_SB8_DRIVER + }, +}; + +static void __init_or_module snd_sb8_unregister_all(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(devices); ++i) + platform_device_unregister(devices[i]); + platform_driver_unregister(&snd_sb8_driver); } static int __init alsa_card_sb8_init(void) { - static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1}; - int dev, cards, i; + int i, cards, err; - for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) { - if (port[dev] == SNDRV_AUTO_PORT) + err = platform_driver_register(&snd_sb8_driver); + if (err < 0) + return err; + + cards = 0; + for (i = 0; i < SNDRV_CARDS; i++) { + struct platform_device *device; + if (! enable[i]) + continue; + device = platform_device_register_simple(SND_SB8_DRIVER, + i, NULL, 0); + if (IS_ERR(device)) + continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); continue; - if (snd_sb8_probe(dev) >= 0) - cards++; + } + devices[i] = device; + cards++; } - i = snd_legacy_auto_probe(possible_ports, snd_card_sb8_legacy_auto_probe); - if (i > 0) - cards += i; - if (!cards) { #ifdef MODULE snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n"); #endif + snd_sb8_unregister_all(); return -ENODEV; } return 0; @@ -222,36 +285,8 @@ static int __init alsa_card_sb8_init(void) static void __exit alsa_card_sb8_exit(void) { - int idx; - - for (idx = 0; idx < SNDRV_CARDS; idx++) - snd_card_free(snd_sb8_cards[idx]); + snd_sb8_unregister_all(); } module_init(alsa_card_sb8_init) module_exit(alsa_card_sb8_exit) - -#ifndef MODULE - -/* format is: snd-sb8=enable,index,id, - port,irq,dma8 */ - -static int __init alsa_card_sb8_setup(char *str) -{ - static unsigned __initdata nr_dev = 0; - - if (nr_dev >= SNDRV_CARDS) - return 0; - (void)(get_option(&str,&enable[nr_dev]) == 2 && - get_option(&str,&index[nr_dev]) == 2 && - get_id(&str,&id[nr_dev]) == 2 && - get_option_long(&str,&port[nr_dev]) == 2 && - get_option(&str,&irq[nr_dev]) == 2 && - get_option(&str,&dma8[nr_dev]) == 2); - nr_dev++; - return 1; -} - -__setup("snd-sb8=", alsa_card_sb8_setup); - -#endif /* ifndef MODULE */