diff options
Diffstat (limited to 'sound/isa/gus/gusmax.c')
-rw-r--r-- | sound/isa/gus/gusmax.c | 117 |
1 files changed, 72 insertions, 45 deletions
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 63311cdb4a1a..d1b70ee9b039 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -20,15 +20,16 @@ | |||
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/cs4231.h> | 32 | #include <sound/cs4231.h> |
31 | #define SNDRV_LEGACY_AUTO_PROBE | ||
32 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 33 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
33 | #define SNDRV_LEGACY_FIND_FREE_DMA | 34 | #define SNDRV_LEGACY_FIND_FREE_DMA |
34 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
@@ -80,8 +81,6 @@ struct snd_gusmax { | |||
80 | unsigned short pcm_status_reg; | 81 | unsigned short pcm_status_reg; |
81 | }; | 82 | }; |
82 | 83 | ||
83 | static struct snd_card *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
84 | |||
85 | #define PFX "gusmax: " | 84 | #define PFX "gusmax: " |
86 | 85 | ||
87 | static int __init snd_gusmax_detect(struct snd_gus_card * gus) | 86 | static int __init snd_gusmax_detect(struct snd_gus_card * gus) |
@@ -203,8 +202,9 @@ static void snd_gusmax_free(struct snd_card *card) | |||
203 | free_irq(maxcard->irq, (void *)maxcard); | 202 | free_irq(maxcard->irq, (void *)maxcard); |
204 | } | 203 | } |
205 | 204 | ||
206 | static int __init snd_gusmax_probe(int dev) | 205 | static int __init snd_gusmax_probe(struct platform_device *pdev) |
207 | { | 206 | { |
207 | int dev = pdev->id; | ||
208 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; | 208 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; |
209 | static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; | 209 | static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; |
210 | int xirq, xdma1, xdma2, err; | 210 | int xirq, xdma1, xdma2, err; |
@@ -247,12 +247,32 @@ static int __init snd_gusmax_probe(int dev) | |||
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | if ((err = snd_gus_create(card, | 250 | if (port[dev] != SNDRV_AUTO_PORT) { |
251 | port[dev], | 251 | err = snd_gus_create(card, |
252 | -xirq, xdma1, xdma2, | 252 | port[dev], |
253 | 0, channels[dev], | 253 | -xirq, xdma1, xdma2, |
254 | pcm_channels[dev], | 254 | 0, channels[dev], |
255 | 0, &gus)) < 0) | 255 | pcm_channels[dev], |
256 | 0, &gus); | ||
257 | } else { | ||
258 | static unsigned long possible_ports[] = { | ||
259 | 0x220, 0x230, 0x240, 0x250, 0x260 | ||
260 | }; | ||
261 | int i; | ||
262 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
263 | err = snd_gus_create(card, | ||
264 | possible_ports[i], | ||
265 | -xirq, xdma1, xdma2, | ||
266 | 0, channels[dev], | ||
267 | pcm_channels[dev], | ||
268 | 0, &gus); | ||
269 | if (err >= 0) { | ||
270 | port[dev] = possible_ports[i]; | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | if (err < 0) | ||
256 | goto _err; | 276 | goto _err; |
257 | 277 | ||
258 | if ((err = snd_gusmax_detect(gus)) < 0) | 278 | if ((err = snd_gusmax_detect(gus)) < 0) |
@@ -310,15 +330,15 @@ static int __init snd_gusmax_probe(int dev) | |||
310 | if (xdma2 >= 0) | 330 | if (xdma2 >= 0) |
311 | sprintf(card->longname + strlen(card->longname), "&%i", xdma2); | 331 | sprintf(card->longname + strlen(card->longname), "&%i", xdma2); |
312 | 332 | ||
313 | if ((err = snd_card_set_generic_dev(card)) < 0) | 333 | snd_card_set_dev(card, &pdev->dev); |
314 | goto _err; | ||
315 | 334 | ||
316 | if ((err = snd_card_register(card)) < 0) | 335 | if ((err = snd_card_register(card)) < 0) |
317 | goto _err; | 336 | goto _err; |
318 | 337 | ||
319 | maxcard->gus = gus; | 338 | maxcard->gus = gus; |
320 | maxcard->cs4231 = cs4231; | 339 | maxcard->cs4231 = cs4231; |
321 | snd_gusmax_cards[dev] = card; | 340 | |
341 | platform_set_drvdata(pdev, card); | ||
322 | return 0; | 342 | return 0; |
323 | 343 | ||
324 | _err: | 344 | _err: |
@@ -326,53 +346,60 @@ static int __init snd_gusmax_probe(int dev) | |||
326 | return err; | 346 | return err; |
327 | } | 347 | } |
328 | 348 | ||
329 | static int __init snd_gusmax_legacy_auto_probe(unsigned long xport) | 349 | static int snd_gusmax_remove(struct platform_device *devptr) |
330 | { | 350 | { |
331 | static int dev; | 351 | snd_card_free(platform_get_drvdata(devptr)); |
332 | int res; | 352 | platform_set_drvdata(devptr, NULL); |
333 | 353 | return 0; | |
334 | for ( ; dev < SNDRV_CARDS; dev++) { | ||
335 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | ||
336 | continue; | ||
337 | port[dev] = xport; | ||
338 | res = snd_gusmax_probe(dev); | ||
339 | if (res < 0) | ||
340 | port[dev] = SNDRV_AUTO_PORT; | ||
341 | return res; | ||
342 | } | ||
343 | return -ENODEV; | ||
344 | } | 354 | } |
345 | 355 | ||
356 | #define GUSMAX_DRIVER "snd_gusmax" | ||
357 | |||
358 | static struct platform_driver snd_gusmax_driver = { | ||
359 | .probe = snd_gusmax_probe, | ||
360 | .remove = snd_gusmax_remove, | ||
361 | /* FIXME: suspend/resume */ | ||
362 | .driver = { | ||
363 | .name = GUSMAX_DRIVER | ||
364 | }, | ||
365 | }; | ||
366 | |||
346 | static int __init alsa_card_gusmax_init(void) | 367 | static int __init alsa_card_gusmax_init(void) |
347 | { | 368 | { |
348 | static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1}; | 369 | int i, cards, err; |
349 | int dev, cards, i; | 370 | |
350 | 371 | err = platform_driver_register(&snd_gusmax_driver); | |
351 | for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) { | 372 | if (err < 0) |
352 | if (port[dev] == SNDRV_AUTO_PORT) | 373 | return err; |
353 | continue; | ||
354 | if (snd_gusmax_probe(dev) >= 0) | ||
355 | cards++; | ||
356 | } | ||
357 | i = snd_legacy_auto_probe(possible_ports, snd_gusmax_legacy_auto_probe); | ||
358 | if (i > 0) | ||
359 | cards += i; | ||
360 | 374 | ||
375 | cards = 0; | ||
376 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | ||
377 | struct platform_device *device; | ||
378 | device = platform_device_register_simple(GUSMAX_DRIVER, | ||
379 | i, NULL, 0); | ||
380 | if (IS_ERR(device)) { | ||
381 | err = PTR_ERR(device); | ||
382 | goto errout; | ||
383 | } | ||
384 | cards++; | ||
385 | } | ||
361 | if (!cards) { | 386 | if (!cards) { |
362 | #ifdef MODULE | 387 | #ifdef MODULE |
363 | printk(KERN_ERR "GUS MAX soundcard not found or device busy\n"); | 388 | printk(KERN_ERR "GUS MAX soundcard not found or device busy\n"); |
364 | #endif | 389 | #endif |
365 | return -ENODEV; | 390 | err = -ENODEV; |
391 | goto errout; | ||
366 | } | 392 | } |
367 | return 0; | 393 | return 0; |
394 | |||
395 | errout: | ||
396 | platform_driver_unregister(&snd_gusmax_driver); | ||
397 | return err; | ||
368 | } | 398 | } |
369 | 399 | ||
370 | static void __exit alsa_card_gusmax_exit(void) | 400 | static void __exit alsa_card_gusmax_exit(void) |
371 | { | 401 | { |
372 | int idx; | 402 | platform_driver_unregister(&snd_gusmax_driver); |
373 | |||
374 | for (idx = 0; idx < SNDRV_CARDS; idx++) | ||
375 | snd_card_free(snd_gusmax_cards[idx]); | ||
376 | } | 403 | } |
377 | 404 | ||
378 | module_init(alsa_card_gusmax_init) | 405 | module_init(alsa_card_gusmax_init) |