diff options
Diffstat (limited to 'sound/isa/gus/gusextreme.c')
-rw-r--r-- | sound/isa/gus/gusextreme.c | 116 |
1 files changed, 67 insertions, 49 deletions
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 9be59d501333..6fad9734a853 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -20,11 +20,13 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | #include <asm/dma.h> | ||
24 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/err.h> | ||
25 | #include <linux/platform_device.h> | ||
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
26 | #include <linux/time.h> | 27 | #include <linux/time.h> |
27 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <asm/dma.h> | ||
28 | #include <sound/core.h> | 30 | #include <sound/core.h> |
29 | #include <sound/gus.h> | 31 | #include <sound/gus.h> |
30 | #include <sound/es1688.h> | 32 | #include <sound/es1688.h> |
@@ -85,7 +87,6 @@ MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver."); | |||
85 | module_param_array(pcm_channels, int, NULL, 0444); | 87 | module_param_array(pcm_channels, int, NULL, 0444); |
86 | MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver."); | 88 | MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver."); |
87 | 89 | ||
88 | static struct snd_card *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
89 | 90 | ||
90 | #define PFX "gusextreme: " | 91 | #define PFX "gusextreme: " |
91 | 92 | ||
@@ -166,15 +167,15 @@ static int __init snd_gusextreme_mixer(struct snd_es1688 *chip) | |||
166 | return 0; | 167 | return 0; |
167 | } | 168 | } |
168 | 169 | ||
169 | static int __init snd_gusextreme_probe(int dev) | 170 | static int __init snd_gusextreme_probe(struct platform_device *pdev) |
170 | { | 171 | { |
172 | int dev = pdev->id; | ||
171 | static int possible_ess_irqs[] = {5, 9, 10, 7, -1}; | 173 | static int possible_ess_irqs[] = {5, 9, 10, 7, -1}; |
172 | static int possible_ess_dmas[] = {1, 3, 0, -1}; | 174 | static int possible_ess_dmas[] = {1, 3, 0, -1}; |
173 | static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; | 175 | static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; |
174 | static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1}; | 176 | static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1}; |
175 | int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma; | 177 | int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma; |
176 | struct snd_card *card; | 178 | struct snd_card *card; |
177 | struct snd_gusextreme *acard; | ||
178 | struct snd_gus_card *gus; | 179 | struct snd_gus_card *gus; |
179 | struct snd_es1688 *es1688; | 180 | struct snd_es1688 *es1688; |
180 | struct snd_opl3 *opl3; | 181 | struct snd_opl3 *opl3; |
@@ -183,7 +184,6 @@ static int __init snd_gusextreme_probe(int dev) | |||
183 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 184 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); |
184 | if (card == NULL) | 185 | if (card == NULL) |
185 | return -ENOMEM; | 186 | return -ENOMEM; |
186 | acard = (struct snd_gusextreme *)card->private_data; | ||
187 | 187 | ||
188 | xgf1_irq = gf1_irq[dev]; | 188 | xgf1_irq = gf1_irq[dev]; |
189 | if (xgf1_irq == SNDRV_AUTO_IRQ) { | 189 | if (xgf1_irq == SNDRV_AUTO_IRQ) { |
@@ -223,10 +223,29 @@ static int __init snd_gusextreme_probe(int dev) | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], | 226 | if (port[dev] != SNDRV_AUTO_PORT) { |
227 | xess_irq, xmpu_irq, xess_dma, | 227 | err = snd_es1688_create(card, port[dev], mpu_port[dev], |
228 | ES1688_HW_1688, &es1688)) < 0) | 228 | xess_irq, xmpu_irq, xess_dma, |
229 | ES1688_HW_1688, &es1688); | ||
230 | } else { | ||
231 | /* auto-probe legacy ports */ | ||
232 | static unsigned long possible_ports[] = {0x220, 0x240, 0x260}; | ||
233 | int i; | ||
234 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
235 | err = snd_es1688_create(card, | ||
236 | possible_ports[i], | ||
237 | mpu_port[dev], | ||
238 | xess_irq, xmpu_irq, xess_dma, | ||
239 | ES1688_HW_1688, &es1688); | ||
240 | if (err >= 0) { | ||
241 | port[dev] = possible_ports[i]; | ||
242 | break; | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | if (err < 0) | ||
229 | goto out; | 247 | goto out; |
248 | |||
230 | if (gf1_port[dev] < 0) | 249 | if (gf1_port[dev] < 0) |
231 | gf1_port[dev] = port[dev] + 0x20; | 250 | gf1_port[dev] = port[dev] + 0x20; |
232 | if ((err = snd_gus_create(card, | 251 | if ((err = snd_gus_create(card, |
@@ -287,13 +306,12 @@ static int __init snd_gusextreme_probe(int dev) | |||
287 | sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i", | 306 | sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i", |
288 | es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma); | 307 | es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma); |
289 | 308 | ||
290 | if ((err = snd_card_set_generic_dev(card)) < 0) | 309 | snd_card_set_dev(card, &pdev->dev); |
291 | goto out; | ||
292 | 310 | ||
293 | if ((err = snd_card_register(card)) < 0) | 311 | if ((err = snd_card_register(card)) < 0) |
294 | goto out; | 312 | goto out; |
295 | 313 | ||
296 | snd_gusextreme_cards[dev] = card; | 314 | platform_set_drvdata(pdev, card); |
297 | return 0; | 315 | return 0; |
298 | 316 | ||
299 | out: | 317 | out: |
@@ -301,60 +319,60 @@ static int __init snd_gusextreme_probe(int dev) | |||
301 | return err; | 319 | return err; |
302 | } | 320 | } |
303 | 321 | ||
304 | static int __init snd_gusextreme_legacy_auto_probe(unsigned long xport) | 322 | static int snd_gusextreme_remove(struct platform_device *devptr) |
305 | { | 323 | { |
306 | static int dev; | 324 | snd_card_free(platform_get_drvdata(devptr)); |
307 | int res; | 325 | platform_set_drvdata(devptr, NULL); |
308 | 326 | return 0; | |
309 | for ( ; dev < SNDRV_CARDS; dev++) { | ||
310 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | ||
311 | continue; | ||
312 | port[dev] = xport; | ||
313 | res = snd_gusextreme_probe(dev); | ||
314 | if (res < 0) | ||
315 | port[dev] = SNDRV_AUTO_PORT; | ||
316 | return res; | ||
317 | } | ||
318 | return -ENODEV; | ||
319 | } | 327 | } |
320 | 328 | ||
329 | #define GUSEXTREME_DRIVER "snd_gusextreme" | ||
330 | |||
331 | static struct platform_driver snd_gusextreme_driver = { | ||
332 | .probe = snd_gusextreme_probe, | ||
333 | .remove = snd_gusextreme_remove, | ||
334 | /* FIXME: suspend/resume */ | ||
335 | .driver = { | ||
336 | .name = GUSEXTREME_DRIVER | ||
337 | }, | ||
338 | }; | ||
339 | |||
321 | static int __init alsa_card_gusextreme_init(void) | 340 | static int __init alsa_card_gusextreme_init(void) |
322 | { | 341 | { |
323 | static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1}; | 342 | int i, cards, err; |
324 | int dev, cards, i; | 343 | |
325 | 344 | err = platform_driver_register(&snd_gusextreme_driver); | |
326 | for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) { | 345 | if (err < 0) |
327 | if (port[dev] == SNDRV_AUTO_PORT) | 346 | return err; |
328 | continue; | ||
329 | if (snd_gusextreme_probe(dev) >= 0) | ||
330 | cards++; | ||
331 | } | ||
332 | i = snd_legacy_auto_probe(possible_ports, snd_gusextreme_legacy_auto_probe); | ||
333 | if (i > 0) | ||
334 | cards += i; | ||
335 | 347 | ||
348 | cards = 0; | ||
349 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | ||
350 | struct platform_device *device; | ||
351 | device = platform_device_register_simple(GUSEXTREME_DRIVER, | ||
352 | i, NULL, 0); | ||
353 | if (IS_ERR(device)) { | ||
354 | err = PTR_ERR(device); | ||
355 | goto errout; | ||
356 | } | ||
357 | cards++; | ||
358 | } | ||
336 | if (!cards) { | 359 | if (!cards) { |
337 | #ifdef MODULE | 360 | #ifdef MODULE |
338 | printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n"); | 361 | printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n"); |
339 | #endif | 362 | #endif |
340 | return -ENODEV; | 363 | err = -ENODEV; |
364 | goto errout; | ||
341 | } | 365 | } |
342 | return 0; | 366 | return 0; |
367 | |||
368 | errout: | ||
369 | platform_driver_unregister(&snd_gusextreme_driver); | ||
370 | return err; | ||
343 | } | 371 | } |
344 | 372 | ||
345 | static void __exit alsa_card_gusextreme_exit(void) | 373 | static void __exit alsa_card_gusextreme_exit(void) |
346 | { | 374 | { |
347 | int idx; | 375 | platform_driver_unregister(&snd_gusextreme_driver); |
348 | struct snd_card *card; | ||
349 | struct snd_gusextreme *acard; | ||
350 | |||
351 | for (idx = 0; idx < SNDRV_CARDS; idx++) { | ||
352 | card = snd_gusextreme_cards[idx]; | ||
353 | if (card == NULL) | ||
354 | continue; | ||
355 | acard = (struct snd_gusextreme *)card->private_data; | ||
356 | snd_card_free(snd_gusextreme_cards[idx]); | ||
357 | } | ||
358 | } | 376 | } |
359 | 377 | ||
360 | module_init(alsa_card_gusextreme_init) | 378 | module_init(alsa_card_gusextreme_init) |