0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/delay.h>
0010 #include <linux/init.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/slab.h>
0013 #include <linux/ioport.h>
0014 #include <linux/module.h>
0015 #include <linux/io.h>
0016 #include <sound/core.h>
0017 #include <sound/sb.h>
0018 #include <sound/initval.h>
0019
0020 #include <asm/dma.h>
0021
0022 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0023 MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
0024 MODULE_LICENSE("GPL");
0025
0026 #define BUSY_LOOPS 100000
0027
0028 #undef IO_DEBUG
0029
0030 int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
0031 {
0032 int i;
0033 #ifdef IO_DEBUG
0034 snd_printk(KERN_DEBUG "command 0x%x\n", val);
0035 #endif
0036 for (i = BUSY_LOOPS; i; i--)
0037 if ((inb(SBP(chip, STATUS)) & 0x80) == 0) {
0038 outb(val, SBP(chip, COMMAND));
0039 return 1;
0040 }
0041 snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val);
0042 return 0;
0043 }
0044
0045 int snd_sbdsp_get_byte(struct snd_sb *chip)
0046 {
0047 int val;
0048 int i;
0049 for (i = BUSY_LOOPS; i; i--) {
0050 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
0051 val = inb(SBP(chip, READ));
0052 #ifdef IO_DEBUG
0053 snd_printk(KERN_DEBUG "get_byte 0x%x\n", val);
0054 #endif
0055 return val;
0056 }
0057 }
0058 snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port);
0059 return -ENODEV;
0060 }
0061
0062 int snd_sbdsp_reset(struct snd_sb *chip)
0063 {
0064 int i;
0065
0066 outb(1, SBP(chip, RESET));
0067 udelay(10);
0068 outb(0, SBP(chip, RESET));
0069 udelay(30);
0070 for (i = BUSY_LOOPS; i; i--)
0071 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
0072 if (inb(SBP(chip, READ)) == 0xaa)
0073 return 0;
0074 else
0075 break;
0076 }
0077 snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port);
0078 return -ENODEV;
0079 }
0080
0081 static int snd_sbdsp_version(struct snd_sb * chip)
0082 {
0083 unsigned int result;
0084
0085 snd_sbdsp_command(chip, SB_DSP_GET_VERSION);
0086 result = (short) snd_sbdsp_get_byte(chip) << 8;
0087 result |= (short) snd_sbdsp_get_byte(chip);
0088 return result;
0089 }
0090
0091 static int snd_sbdsp_probe(struct snd_sb * chip)
0092 {
0093 int version;
0094 int major, minor;
0095 char *str;
0096 unsigned long flags;
0097
0098
0099
0100
0101
0102 spin_lock_irqsave(&chip->reg_lock, flags);
0103 if (snd_sbdsp_reset(chip) < 0) {
0104 spin_unlock_irqrestore(&chip->reg_lock, flags);
0105 return -ENODEV;
0106 }
0107 version = snd_sbdsp_version(chip);
0108 if (version < 0) {
0109 spin_unlock_irqrestore(&chip->reg_lock, flags);
0110 return -ENODEV;
0111 }
0112 spin_unlock_irqrestore(&chip->reg_lock, flags);
0113 major = version >> 8;
0114 minor = version & 0xff;
0115 snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n",
0116 chip->port, major, minor);
0117
0118 switch (chip->hardware) {
0119 case SB_HW_AUTO:
0120 switch (major) {
0121 case 1:
0122 chip->hardware = SB_HW_10;
0123 str = "1.0";
0124 break;
0125 case 2:
0126 if (minor) {
0127 chip->hardware = SB_HW_201;
0128 str = "2.01+";
0129 } else {
0130 chip->hardware = SB_HW_20;
0131 str = "2.0";
0132 }
0133 break;
0134 case 3:
0135 chip->hardware = SB_HW_PRO;
0136 str = "Pro";
0137 break;
0138 case 4:
0139 chip->hardware = SB_HW_16;
0140 str = "16";
0141 break;
0142 default:
0143 snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n",
0144 chip->port, major, minor);
0145 return -ENODEV;
0146 }
0147 break;
0148 case SB_HW_ALS100:
0149 str = "16 (ALS-100)";
0150 break;
0151 case SB_HW_ALS4000:
0152 str = "16 (ALS-4000)";
0153 break;
0154 case SB_HW_DT019X:
0155 str = "(DT019X/ALS007)";
0156 break;
0157 case SB_HW_CS5530:
0158 str = "16 (CS5530)";
0159 break;
0160 case SB_HW_JAZZ16:
0161 str = "Pro (Jazz16)";
0162 break;
0163 default:
0164 return -ENODEV;
0165 }
0166 sprintf(chip->name, "Sound Blaster %s", str);
0167 chip->version = (major << 8) | minor;
0168 return 0;
0169 }
0170
0171 int snd_sbdsp_create(struct snd_card *card,
0172 unsigned long port,
0173 int irq,
0174 irq_handler_t irq_handler,
0175 int dma8,
0176 int dma16,
0177 unsigned short hardware,
0178 struct snd_sb **r_chip)
0179 {
0180 struct snd_sb *chip;
0181 int err;
0182
0183 if (snd_BUG_ON(!r_chip))
0184 return -EINVAL;
0185 *r_chip = NULL;
0186 chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
0187 if (!chip)
0188 return -ENOMEM;
0189 spin_lock_init(&chip->reg_lock);
0190 spin_lock_init(&chip->open_lock);
0191 spin_lock_init(&chip->midi_input_lock);
0192 spin_lock_init(&chip->mixer_lock);
0193 chip->irq = -1;
0194 chip->dma8 = -1;
0195 chip->dma16 = -1;
0196 chip->port = port;
0197
0198 if (devm_request_irq(card->dev, irq, irq_handler,
0199 (hardware == SB_HW_ALS4000 ||
0200 hardware == SB_HW_CS5530) ?
0201 IRQF_SHARED : 0,
0202 "SoundBlaster", (void *) chip)) {
0203 snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
0204 return -EBUSY;
0205 }
0206 chip->irq = irq;
0207 card->sync_irq = chip->irq;
0208
0209 if (hardware == SB_HW_ALS4000)
0210 goto __skip_allocation;
0211
0212 chip->res_port = devm_request_region(card->dev, port, 16,
0213 "SoundBlaster");
0214 if (!chip->res_port) {
0215 snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port);
0216 return -EBUSY;
0217 }
0218
0219 #ifdef CONFIG_ISA
0220 if (dma8 >= 0 && snd_devm_request_dma(card->dev, dma8,
0221 "SoundBlaster - 8bit")) {
0222 snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8);
0223 return -EBUSY;
0224 }
0225 chip->dma8 = dma8;
0226 if (dma16 >= 0) {
0227 if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) {
0228
0229 dma16 = -1;
0230 } else if (snd_devm_request_dma(card->dev, dma16,
0231 "SoundBlaster - 16bit")) {
0232 snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16);
0233 return -EBUSY;
0234 }
0235 }
0236 chip->dma16 = dma16;
0237 #endif
0238
0239 __skip_allocation:
0240 chip->card = card;
0241 chip->hardware = hardware;
0242 err = snd_sbdsp_probe(chip);
0243 if (err < 0)
0244 return err;
0245 *r_chip = chip;
0246 return 0;
0247 }
0248
0249 EXPORT_SYMBOL(snd_sbdsp_command);
0250 EXPORT_SYMBOL(snd_sbdsp_get_byte);
0251 EXPORT_SYMBOL(snd_sbdsp_reset);
0252 EXPORT_SYMBOL(snd_sbdsp_create);
0253
0254 EXPORT_SYMBOL(snd_sbmixer_write);
0255 EXPORT_SYMBOL(snd_sbmixer_read);
0256 EXPORT_SYMBOL(snd_sbmixer_new);
0257 EXPORT_SYMBOL(snd_sbmixer_add_ctl);
0258 #ifdef CONFIG_PM
0259 EXPORT_SYMBOL(snd_sbmixer_suspend);
0260 EXPORT_SYMBOL(snd_sbmixer_resume);
0261 #endif