ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / pci / au88x0 / au88x0.c
1 /*
2  * ALSA driver for the Aureal Vortex family of soundprocessors.
3  * Author: Manuel Jander (mjander@embedded.cl)
4  *
5  *   This driver is the result of the OpenVortex Project from Savannah
6  * (savannah.nongnu.org/projects/openvortex). I would like to thank
7  * the developers of OpenVortex, Jeff Muizelar and Kester Maddock, from
8  * whom i got plenty of help, and their codebase was invaluable.
9  *   Thanks to the ALSA developers, they helped a lot working out
10  * the ALSA part.
11  *   Thanks also to Sourceforge for maintaining the old binary drivers,
12  * and the forum, where developers could comunicate.
13  *
14  * Now at least i can play Legacy DOOM with MIDI music :-)
15  */
16
17 #include "au88x0.h"
18 #include <linux/init.h>
19 #include <linux/pci.h>
20 #include <linux/slab.h>
21 #include <linux/interrupt.h>
22 #define SNDRV_GET_ID
23 #include <sound/initval.h>
24
25 // module parameters (see "Module Parameters")
26 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
27 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
28 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
29 static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 };
30
31 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
32 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
33 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
34 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
35 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
36 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
37 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
38 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
39 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
40 MODULE_PARM(pcifix, "1-255i");
41 MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
42 MODULE_PARM_SYNTAX(pcifix,
43                    SNDRV_ENABLED
44                    ",allows:{{0,Disabled},{1,Latency},{2,Bridge},{3,Both},{255,Auto}},default:4,dialog:check");
45
46 MODULE_DESCRIPTION("Aureal vortex");
47 MODULE_CLASSES("{sound}");
48 MODULE_LICENSE("GPL");
49 MODULE_DEVICES("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
50
51 #ifndef MODULE
52 /* format is: snd-mychip=enable,index,id */
53 static int __init alsa_card_vortex_setup(char *str)
54 {
55         static unsigned __initdata nr_dev = 0;
56
57         if (nr_dev >= SNDRV_CARDS)
58                 return 0;
59         (void)(get_option(&str, &enable[nr_dev]) == 2 &&
60                get_option(&str, &index[nr_dev]) == 2 &&
61                get_id(&str, &id[nr_dev]) == 2);
62         nr_dev++;
63         return 1;
64 }
65
66 __setup("snd-au88x0=", alsa_card_vortex_setup);
67 #endif                          /* ifndef MODULE */
68
69 MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
70
71 static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
72 {
73         struct pci_dev *via = NULL;
74         int rc;
75
76         /* autodetect if workarounds are required */
77         while ((via = pci_find_device(PCI_VENDOR_ID_VIA,
78                                       PCI_DEVICE_ID_VIA_8365_1, via))) {
79                 if (fix == 255) {
80                         printk(KERN_INFO CARD_NAME
81                                ": detected VIA KT133/KM133. activating workaround...\n");
82                         fix = 3;        // do latency and via bridge workaround
83                 }
84                 break;
85         }
86
87         /* do not do anything if autodetection was enabled and found no VIA */
88         if (fix == 255)
89                 return;
90
91         /* fix vortex latency */
92         if (fix & 0x01) {
93                 if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
94                         printk(KERN_INFO CARD_NAME
95                                ": vortex latency is 0xff\n");
96                 } else {
97                         printk(KERN_WARNING CARD_NAME
98                                ": could not set vortex latency: pci error 0x%x\n",
99                                rc);
100                 }
101         }
102
103         /* fix via agp bridge */
104         if (via && (fix & 0x02)) {
105                 u8 value;
106
107                 /*
108                  * only set the bit (Extend PCI#2 Internal Master for
109                  * Efficient Handling of Dummy Requests) if the can
110                  * read the config and it is not already set
111                  */
112
113                 if (!(rc = pci_read_config_byte(via, 0x42, &value))
114                     && ((value & 0x10)
115                         || !(rc =
116                              pci_write_config_byte(via, 0x42, value | 0x10)))) {
117
118                         printk(KERN_INFO CARD_NAME
119                                ": bridge config is 0x%x\n", value | 0x10);
120                 } else {
121                         printk(KERN_WARNING CARD_NAME
122                                ": could not set vortex latency: pci error 0x%x\n",
123                                rc);
124                 }
125         }
126 }
127
128 // component-destructor
129 // (see "Management of Cards and Components")
130 static int snd_vortex_dev_free(snd_device_t * device)
131 {
132         vortex_t *vortex = snd_magic_cast(vortex_t, device->device_data,
133                                           return -ENXIO);
134
135         vortex_gameport_unregister(vortex);
136         vortex_core_shutdown(vortex);
137         // Take down PCI interface.
138         synchronize_irq(vortex->irq);
139         free_irq(vortex->irq, vortex);
140         pci_release_regions(vortex->pci_dev);
141         pci_disable_device(vortex->pci_dev);
142         snd_magic_kfree(vortex);
143
144         return 0;
145 }
146
147 // chip-specific constructor
148 // (see "Management of Cards and Components")
149 static int __devinit
150 snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
151 {
152         vortex_t *chip;
153         int err;
154         static snd_device_ops_t ops = {
155                 .dev_free = snd_vortex_dev_free,
156         };
157
158         *rchip = NULL;
159
160         // check PCI availability (DMA).
161         if ((err = pci_enable_device(pci)) < 0)
162                 return err;
163         if (!pci_dma_supported(pci, VORTEX_DMA_MASK)) {
164                 printk(KERN_ERR "error to set DMA mask\n");
165                 return -ENXIO;
166         }
167         pci_set_dma_mask(pci, VORTEX_DMA_MASK);
168
169         chip = snd_magic_kcalloc(vortex_t, 0, GFP_KERNEL);
170         if (chip == NULL)
171                 return -ENOMEM;
172
173         chip->card = card;
174
175         // initialize the stuff
176         chip->pci_dev = pci;
177         chip->io = pci_resource_start(pci, 0);
178         chip->vendor = pci->vendor;
179         chip->device = pci->device;
180         chip->card = card;
181         chip->irq = -1;
182
183         // (1) PCI resource allocation
184         // Get MMIO area
185         //
186         if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0)
187                 goto regions_out;
188
189         chip->mmio =
190             ioremap_nocache(pci_resource_start(pci, 0),
191                             pci_resource_len(pci, 0));
192         if (!chip->mmio) {
193                 printk(KERN_ERR "MMIO area remap failed.\n");
194                 err = -ENOMEM;
195                 goto ioremap_out;
196         }
197
198         /* Init audio core.
199          * This must be done before we do request_irq otherwise we can get spurious
200          * interupts that we do not handle properly and make a mess of things */
201         if ((err = vortex_core_init(chip)) != 0) {
202                 printk(KERN_ERR "hw core init failed\n");
203                 goto core_out;
204         }
205
206         if ((err =
207              request_irq(pci->irq, vortex_interrupt,
208                          SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT,
209                          (void *)chip)) != 0) {
210                 printk(KERN_ERR "cannot grab irq\n");
211                 goto irq_out;
212         }
213         chip->irq = pci->irq;
214
215         pci_set_master(pci);
216         // End of PCI setup.
217
218         // Register alsa root device.
219         if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
220                 goto alloc_out;
221         }
222
223         *rchip = chip;
224
225         return 0;
226
227       alloc_out:
228         synchronize_irq(chip->irq);
229         free_irq(chip->irq, chip);
230       irq_out:
231         vortex_core_shutdown(chip);
232       core_out:
233         //FIXME: the type of chip->mmio might need to be changed??
234         iounmap((void *)chip->mmio);
235       ioremap_out:
236         pci_release_regions(chip->pci_dev);
237       regions_out:
238         pci_disable_device(chip->pci_dev);
239         //FIXME: this not the right place to unregister the gameport
240         vortex_gameport_unregister(chip);
241         return err;
242 }
243
244 // constructor -- see "Constructor" sub-section
245 static int __devinit
246 snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
247 {
248         static int dev;
249         snd_card_t *card;
250         vortex_t *chip;
251         int err;
252
253         // (1)
254         if (dev >= SNDRV_CARDS)
255                 return -ENODEV;
256         if (!enable[dev]) {
257                 dev++;
258                 return -ENOENT;
259         }
260         // (2)
261         card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
262         if (card == NULL)
263                 return -ENOMEM;
264
265         // (3)
266         if ((err = snd_vortex_create(card, pci, &chip)) < 0) {
267                 snd_card_free(card);
268                 return err;
269         }
270         snd_vortex_workaround(pci, pcifix[dev]);
271         // (4) Alloc components.
272         // ADB pcm.
273         if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
274                 snd_card_free(card);
275                 return err;
276         }
277 #ifndef CHIP_AU8820
278         // ADB SPDIF
279         if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) {
280                 snd_card_free(card);
281                 return err;
282         }
283         // A3D
284         if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) {
285                 snd_card_free(card);
286                 return err;
287         }
288 #endif
289         /*
290            // ADB I2S
291            if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
292            snd_card_free(card);
293            return err;
294            }
295          */
296 #ifndef CHIP_AU8810
297         // WT pcm.
298         if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) {
299                 snd_card_free(card);
300                 return err;
301         }
302 #endif
303         // snd_ac97_mixer and Vortex mixer.
304         if ((err = snd_vortex_mixer(chip)) < 0) {
305                 snd_card_free(card);
306                 return err;
307         }
308         if ((err = snd_vortex_midi(chip)) < 0) {
309                 snd_card_free(card);
310                 return err;
311         }
312         if ((err = vortex_gameport_register(chip)) < 0) {
313                 snd_card_free(card);
314                 return err;
315         }
316 #if 0
317         if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
318                                sizeof(snd_vortex_synth_arg_t), &wave) < 0
319             || wave == NULL) {
320                 snd_printk("Can't initialize Aureal wavetable synth\n");
321         } else {
322                 snd_vortex_synth_arg_t *arg;
323
324                 arg = SNDRV_SEQ_DEVICE_ARGPTR(wave);
325                 strcpy(wave->name, "Aureal Synth");
326                 arg->hwptr = vortex;
327                 arg->index = 1;
328                 arg->seq_ports = seq_ports[dev];
329                 arg->max_voices = max_synth_voices[dev];
330         }
331 #endif
332
333         // (5)
334         strcpy(card->driver, "Aureal Vortex");
335         strcpy(card->shortname, CARD_NAME_SHORT);
336         sprintf(card->longname, "%s at 0x%lx irq %i",
337                 card->shortname, chip->io, chip->irq);
338
339         if ((err = pci_read_config_word(pci, PCI_DEVICE_ID,
340                                   &(chip->device))) < 0) {
341                 snd_card_free(card);
342                 return err;
343         }       
344         if ((err = pci_read_config_word(pci, PCI_VENDOR_ID,
345                                   &(chip->vendor))) < 0) {
346                 snd_card_free(card);
347                 return err;
348         }
349         if ((err = pci_read_config_byte(pci, PCI_REVISION_ID,
350                                   &(chip->rev))) < 0) {
351                 snd_card_free(card);
352                 return err;
353         }
354 #ifdef CHIP_AU8830
355         if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
356                 printk(KERN_ALERT
357                        "vortex: The revision (%x) of your card has not been seen before.\n",
358                        chip->rev);
359                 printk(KERN_ALERT
360                        "vortex: Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
361                 snd_card_free(card);
362                 err = -ENODEV;
363                 return err;
364         }
365 #endif
366
367         // (6)
368         if ((err = snd_card_register(card)) < 0) {
369                 snd_card_free(card);
370                 return err;
371         }
372         // (7)
373         pci_set_drvdata(pci, chip);
374         dev++;
375         vortex_connect_default(chip, 1);
376         vortex_enable_int(chip);
377         return 0;
378 }
379
380 // destructor -- see "Destructor" sub-section
381 static void __devexit snd_vortex_remove(struct pci_dev *pci)
382 {
383         vortex_t *vortex = snd_magic_cast(vortex_t,
384                                           pci_get_drvdata(pci), return);
385
386         if (vortex) {
387                 // Release ALSA stuff.
388                 snd_card_free(vortex->card);
389                 // Free Vortex struct.
390                 pci_set_drvdata(pci, NULL);
391         } else
392                 printk("snd_vortex_remove called more than one time!\n");
393 }
394
395 // pci_driver definition
396 static struct pci_driver driver = {
397         .name = CARD_NAME_SHORT,
398         .id_table = snd_vortex_ids,
399         .probe = snd_vortex_probe,
400         .remove = __devexit_p(snd_vortex_remove),
401 };
402
403 // initialization of the module
404 static int __init alsa_card_vortex_init(void)
405 {
406         int err;
407
408         if ((err = pci_module_init(&driver)) < 0) {
409 #ifdef MODULE
410                 printk(KERN_ERR "Aureal soundcard not found "
411                        "or device busy\n");
412 #endif
413                 return err;
414         }
415         return 0;
416 }
417
418 // clean up the module
419 static void __exit alsa_card_vortex_exit(void)
420 {
421         pci_unregister_driver(&driver);
422 }
423
424 module_init(alsa_card_vortex_init)
425 module_exit(alsa_card_vortex_exit)