0001
0002
0003
0004
0005
0006
0007 #include <linux/init.h>
0008 #include <linux/err.h>
0009 #include <linux/isa.h>
0010 #include <linux/ioport.h>
0011 #include <linux/module.h>
0012 #include <sound/core.h>
0013 #include <sound/sb.h>
0014 #include <sound/opl3.h>
0015 #include <sound/initval.h>
0016
0017 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0018 MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro");
0019 MODULE_LICENSE("GPL");
0020
0021 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0022 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0023 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
0024 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0025 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0026 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0027
0028 module_param_array(index, int, NULL, 0444);
0029 MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard.");
0030 module_param_array(id, charp, NULL, 0444);
0031 MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard.");
0032 module_param_array(enable, bool, NULL, 0444);
0033 MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard.");
0034 module_param_hw_array(port, long, ioport, NULL, 0444);
0035 MODULE_PARM_DESC(port, "Port # for SB8 driver.");
0036 module_param_hw_array(irq, int, irq, NULL, 0444);
0037 MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
0038 module_param_hw_array(dma8, int, dma, NULL, 0444);
0039 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
0040
0041 struct snd_sb8 {
0042 struct resource *fm_res;
0043 struct snd_sb *chip;
0044 };
0045
0046 static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
0047 {
0048 struct snd_sb *chip = dev_id;
0049
0050 if (chip->open & SB_OPEN_PCM) {
0051 return snd_sb8dsp_interrupt(chip);
0052 } else {
0053 return snd_sb8dsp_midi_interrupt(chip);
0054 }
0055 }
0056
0057 static int snd_sb8_match(struct device *pdev, unsigned int dev)
0058 {
0059 if (!enable[dev])
0060 return 0;
0061 if (irq[dev] == SNDRV_AUTO_IRQ) {
0062 dev_err(pdev, "please specify irq\n");
0063 return 0;
0064 }
0065 if (dma8[dev] == SNDRV_AUTO_DMA) {
0066 dev_err(pdev, "please specify dma8\n");
0067 return 0;
0068 }
0069 return 1;
0070 }
0071
0072 static int snd_sb8_probe(struct device *pdev, unsigned int dev)
0073 {
0074 struct snd_sb *chip;
0075 struct snd_card *card;
0076 struct snd_sb8 *acard;
0077 struct snd_opl3 *opl3;
0078 int err;
0079
0080 err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
0081 sizeof(struct snd_sb8), &card);
0082 if (err < 0)
0083 return err;
0084 acard = card->private_data;
0085
0086
0087
0088
0089
0090
0091 acard->fm_res = devm_request_region(card->dev, 0x388, 4,
0092 "SoundBlaster FM");
0093
0094 if (port[dev] != SNDRV_AUTO_PORT) {
0095 err = snd_sbdsp_create(card, port[dev], irq[dev],
0096 snd_sb8_interrupt, dma8[dev],
0097 -1, SB_HW_AUTO, &chip);
0098 if (err < 0)
0099 return err;
0100 } else {
0101
0102 static const unsigned long possible_ports[] = {
0103 0x220, 0x240, 0x260,
0104 };
0105 int i;
0106 for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
0107 err = snd_sbdsp_create(card, possible_ports[i],
0108 irq[dev],
0109 snd_sb8_interrupt,
0110 dma8[dev],
0111 -1,
0112 SB_HW_AUTO,
0113 &chip);
0114 if (err >= 0) {
0115 port[dev] = possible_ports[i];
0116 break;
0117 }
0118 }
0119 if (i >= ARRAY_SIZE(possible_ports))
0120 return -EINVAL;
0121 }
0122 acard->chip = chip;
0123
0124 if (chip->hardware >= SB_HW_16) {
0125 if (chip->hardware == SB_HW_ALS100)
0126 snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n",
0127 port[dev]);
0128 else
0129 snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
0130 port[dev]);
0131 return -ENODEV;
0132 }
0133
0134 err = snd_sb8dsp_pcm(chip, 0);
0135 if (err < 0)
0136 return err;
0137
0138 err = snd_sbmixer_new(chip);
0139 if (err < 0)
0140 return err;
0141
0142 if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
0143 err = snd_opl3_create(card, chip->port + 8, 0,
0144 OPL3_HW_AUTO, 1, &opl3);
0145 if (err < 0)
0146 snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8);
0147 } else {
0148 err = snd_opl3_create(card, chip->port, chip->port + 2,
0149 OPL3_HW_AUTO, 1, &opl3);
0150 if (err < 0) {
0151 snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n",
0152 chip->port, chip->port + 2);
0153 }
0154 }
0155 if (err >= 0) {
0156 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0157 if (err < 0)
0158 return err;
0159 }
0160
0161 err = snd_sb8dsp_midi(chip, 0);
0162 if (err < 0)
0163 return err;
0164
0165 strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
0166 strcpy(card->shortname, chip->name);
0167 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
0168 chip->name,
0169 chip->port,
0170 irq[dev], dma8[dev]);
0171
0172 err = snd_card_register(card);
0173 if (err < 0)
0174 return err;
0175
0176 dev_set_drvdata(pdev, card);
0177 return 0;
0178 }
0179
0180 #ifdef CONFIG_PM
0181 static int snd_sb8_suspend(struct device *dev, unsigned int n,
0182 pm_message_t state)
0183 {
0184 struct snd_card *card = dev_get_drvdata(dev);
0185 struct snd_sb8 *acard = card->private_data;
0186 struct snd_sb *chip = acard->chip;
0187
0188 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
0189 snd_sbmixer_suspend(chip);
0190 return 0;
0191 }
0192
0193 static int snd_sb8_resume(struct device *dev, unsigned int n)
0194 {
0195 struct snd_card *card = dev_get_drvdata(dev);
0196 struct snd_sb8 *acard = card->private_data;
0197 struct snd_sb *chip = acard->chip;
0198
0199 snd_sbdsp_reset(chip);
0200 snd_sbmixer_resume(chip);
0201 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
0202 return 0;
0203 }
0204 #endif
0205
0206 #define DEV_NAME "sb8"
0207
0208 static struct isa_driver snd_sb8_driver = {
0209 .match = snd_sb8_match,
0210 .probe = snd_sb8_probe,
0211 #ifdef CONFIG_PM
0212 .suspend = snd_sb8_suspend,
0213 .resume = snd_sb8_resume,
0214 #endif
0215 .driver = {
0216 .name = DEV_NAME
0217 },
0218 };
0219
0220 module_isa_driver(snd_sb8_driver, SNDRV_CARDS);