0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <linux/delay.h>
0031 #include <linux/module.h>
0032 #include <linux/pci.h>
0033 #include <linux/slab.h>
0034 #include <sound/core.h>
0035 #include <sound/sb.h>
0036 #include <sound/initval.h>
0037
0038 MODULE_AUTHOR("Ash Willis");
0039 MODULE_DESCRIPTION("CS5530 Audio");
0040 MODULE_LICENSE("GPL");
0041
0042 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0043 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0044 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
0045
0046 module_param_array(index, int, NULL, 0444);
0047 MODULE_PARM_DESC(index, "Index value for CS5530 Audio driver.");
0048 module_param_array(id, charp, NULL, 0444);
0049 MODULE_PARM_DESC(id, "ID string for CS5530 Audio driver.");
0050 module_param_array(enable, bool, NULL, 0444);
0051 MODULE_PARM_DESC(enable, "Enable CS5530 Audio driver.");
0052
0053 struct snd_cs5530 {
0054 struct snd_card *card;
0055 struct pci_dev *pci;
0056 struct snd_sb *sb;
0057 unsigned long pci_base;
0058 };
0059
0060 static const struct pci_device_id snd_cs5530_ids[] = {
0061 {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID,
0062 PCI_ANY_ID, 0, 0},
0063 {0,}
0064 };
0065
0066 MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
0067
0068 static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
0069 {
0070 outb(reg, io + 4);
0071 udelay(20);
0072 reg = inb(io + 5);
0073 udelay(20);
0074 return reg;
0075 }
0076
0077 static int snd_cs5530_create(struct snd_card *card,
0078 struct pci_dev *pci)
0079 {
0080 struct snd_cs5530 *chip = card->private_data;
0081 unsigned long sb_base;
0082 u8 irq, dma8, dma16 = 0;
0083 u16 map;
0084 void __iomem *mem;
0085 int err;
0086
0087 err = pcim_enable_device(pci);
0088 if (err < 0)
0089 return err;
0090
0091 chip->card = card;
0092 chip->pci = pci;
0093
0094 err = pcim_iomap_regions(pci, 1 << 0, "CS5530");
0095 if (err < 0)
0096 return err;
0097 chip->pci_base = pci_resource_start(pci, 0);
0098 mem = pcim_iomap_table(pci)[0];
0099 map = readw(mem + 0x18);
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 sb_base = 0x220 + 0x20 * (map & 3);
0111
0112 if (map & (1<<2))
0113 dev_info(card->dev, "XpressAudio at 0x%lx\n", sb_base);
0114 else {
0115 dev_err(card->dev, "Could not find XpressAudio!\n");
0116 return -ENODEV;
0117 }
0118
0119 if (map & (1<<5))
0120 dev_info(card->dev, "MPU at 0x300\n");
0121 else if (map & (1<<6))
0122 dev_info(card->dev, "MPU at 0x330\n");
0123
0124 irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F;
0125 dma8 = snd_cs5530_mixer_read(sb_base, 0x81);
0126
0127 if (dma8 & 0x20)
0128 dma16 = 5;
0129 else if (dma8 & 0x40)
0130 dma16 = 6;
0131 else if (dma8 & 0x80)
0132 dma16 = 7;
0133 else {
0134 dev_err(card->dev, "No 16bit DMA enabled\n");
0135 return -ENODEV;
0136 }
0137
0138 if (dma8 & 0x01)
0139 dma8 = 0;
0140 else if (dma8 & 02)
0141 dma8 = 1;
0142 else if (dma8 & 0x08)
0143 dma8 = 3;
0144 else {
0145 dev_err(card->dev, "No 8bit DMA enabled\n");
0146 return -ENODEV;
0147 }
0148
0149 if (irq & 1)
0150 irq = 9;
0151 else if (irq & 2)
0152 irq = 5;
0153 else if (irq & 4)
0154 irq = 7;
0155 else if (irq & 8)
0156 irq = 10;
0157 else {
0158 dev_err(card->dev, "SoundBlaster IRQ not set\n");
0159 return -ENODEV;
0160 }
0161
0162 dev_info(card->dev, "IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, dma16);
0163
0164 err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8,
0165 dma16, SB_HW_CS5530, &chip->sb);
0166 if (err < 0) {
0167 dev_err(card->dev, "Could not create SoundBlaster\n");
0168 return err;
0169 }
0170
0171 err = snd_sb16dsp_pcm(chip->sb, 0);
0172 if (err < 0) {
0173 dev_err(card->dev, "Could not create PCM\n");
0174 return err;
0175 }
0176
0177 err = snd_sbmixer_new(chip->sb);
0178 if (err < 0) {
0179 dev_err(card->dev, "Could not create Mixer\n");
0180 return err;
0181 }
0182
0183 return 0;
0184 }
0185
0186 static int snd_cs5530_probe(struct pci_dev *pci,
0187 const struct pci_device_id *pci_id)
0188 {
0189 static int dev;
0190 struct snd_card *card;
0191 struct snd_cs5530 *chip;
0192 int err;
0193
0194 if (dev >= SNDRV_CARDS)
0195 return -ENODEV;
0196 if (!enable[dev]) {
0197 dev++;
0198 return -ENOENT;
0199 }
0200
0201 err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
0202 sizeof(*chip), &card);
0203 if (err < 0)
0204 return err;
0205 chip = card->private_data;
0206
0207 err = snd_cs5530_create(card, pci);
0208 if (err < 0)
0209 return err;
0210
0211 strcpy(card->driver, "CS5530");
0212 strcpy(card->shortname, "CS5530 Audio");
0213 sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
0214
0215 err = snd_card_register(card);
0216 if (err < 0)
0217 return err;
0218 pci_set_drvdata(pci, card);
0219 dev++;
0220 return 0;
0221 }
0222
0223 static struct pci_driver cs5530_driver = {
0224 .name = KBUILD_MODNAME,
0225 .id_table = snd_cs5530_ids,
0226 .probe = snd_cs5530_probe,
0227 };
0228
0229 module_pci_driver(cs5530_driver);