aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/gus/gusmax.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/gus/gusmax.c')
-rw-r--r--sound/isa/gus/gusmax.c153
1 files changed, 96 insertions, 57 deletions
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 0bb44b519340..d4d2b2a517d5 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>
@@ -71,20 +72,20 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
71module_param_array(pcm_channels, int, NULL, 0444); 72module_param_array(pcm_channels, int, NULL, 0444);
72MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver."); 73MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
73 74
75static struct platform_device *devices[SNDRV_CARDS];
76
74struct snd_gusmax { 77struct snd_gusmax {
75 int irq; 78 int irq;
76 snd_card_t *card; 79 struct snd_card *card;
77 snd_gus_card_t *gus; 80 struct snd_gus_card *gus;
78 cs4231_t *cs4231; 81 struct snd_cs4231 *cs4231;
79 unsigned short gus_status_reg; 82 unsigned short gus_status_reg;
80 unsigned short pcm_status_reg; 83 unsigned short pcm_status_reg;
81}; 84};
82 85
83static snd_card_t *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
84
85#define PFX "gusmax: " 86#define PFX "gusmax: "
86 87
87static int __init snd_gusmax_detect(snd_gus_card_t * gus) 88static int __init snd_gusmax_detect(struct snd_gus_card * gus)
88{ 89{
89 unsigned char d; 90 unsigned char d;
90 91
@@ -126,7 +127,7 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id, struct pt_regs *r
126 return IRQ_RETVAL(handled); 127 return IRQ_RETVAL(handled);
127} 128}
128 129
129static void __init snd_gusmax_init(int dev, snd_card_t * card, snd_gus_card_t * gus) 130static void __init snd_gusmax_init(int dev, struct snd_card *card, struct snd_gus_card * gus)
130{ 131{
131 gus->equal_irq = 1; 132 gus->equal_irq = 1;
132 gus->codec_flag = 1; 133 gus->codec_flag = 1;
@@ -144,10 +145,10 @@ static void __init snd_gusmax_init(int dev, snd_card_t * card, snd_gus_card_t *
144#define CS4231_PRIVATE( left, right, shift, mute ) \ 145#define CS4231_PRIVATE( left, right, shift, mute ) \
145 ((left << 24)|(right << 16)|(shift<<8)|mute) 146 ((left << 24)|(right << 16)|(shift<<8)|mute)
146 147
147static int __init snd_gusmax_mixer(cs4231_t *chip) 148static int __init snd_gusmax_mixer(struct snd_cs4231 *chip)
148{ 149{
149 snd_card_t *card = chip->card; 150 struct snd_card *card = chip->card;
150 snd_ctl_elem_id_t id1, id2; 151 struct snd_ctl_elem_id id1, id2;
151 int err; 152 int err;
152 153
153 memset(&id1, 0, sizeof(id1)); 154 memset(&id1, 0, sizeof(id1));
@@ -193,7 +194,7 @@ static int __init snd_gusmax_mixer(cs4231_t *chip)
193 return 0; 194 return 0;
194} 195}
195 196
196static void snd_gusmax_free(snd_card_t *card) 197static void snd_gusmax_free(struct snd_card *card)
197{ 198{
198 struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data; 199 struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data;
199 200
@@ -203,14 +204,15 @@ static void snd_gusmax_free(snd_card_t *card)
203 free_irq(maxcard->irq, (void *)maxcard); 204 free_irq(maxcard->irq, (void *)maxcard);
204} 205}
205 206
206static int __init snd_gusmax_probe(int dev) 207static int __init snd_gusmax_probe(struct platform_device *pdev)
207{ 208{
209 int dev = pdev->id;
208 static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; 210 static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
209 static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; 211 static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
210 int xirq, xdma1, xdma2, err; 212 int xirq, xdma1, xdma2, err;
211 snd_card_t *card; 213 struct snd_card *card;
212 snd_gus_card_t *gus = NULL; 214 struct snd_gus_card *gus = NULL;
213 cs4231_t *cs4231; 215 struct snd_cs4231 *cs4231;
214 struct snd_gusmax *maxcard; 216 struct snd_gusmax *maxcard;
215 217
216 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 218 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
@@ -247,12 +249,32 @@ static int __init snd_gusmax_probe(int dev)
247 } 249 }
248 } 250 }
249 251
250 if ((err = snd_gus_create(card, 252 if (port[dev] != SNDRV_AUTO_PORT) {
251 port[dev], 253 err = snd_gus_create(card,
252 -xirq, xdma1, xdma2, 254 port[dev],
253 0, channels[dev], 255 -xirq, xdma1, xdma2,
254 pcm_channels[dev], 256 0, channels[dev],
255 0, &gus)) < 0) 257 pcm_channels[dev],
258 0, &gus);
259 } else {
260 static unsigned long possible_ports[] = {
261 0x220, 0x230, 0x240, 0x250, 0x260
262 };
263 int i;
264 for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
265 err = snd_gus_create(card,
266 possible_ports[i],
267 -xirq, xdma1, xdma2,
268 0, channels[dev],
269 pcm_channels[dev],
270 0, &gus);
271 if (err >= 0) {
272 port[dev] = possible_ports[i];
273 break;
274 }
275 }
276 }
277 if (err < 0)
256 goto _err; 278 goto _err;
257 279
258 if ((err = snd_gusmax_detect(gus)) < 0) 280 if ((err = snd_gusmax_detect(gus)) < 0)
@@ -310,15 +332,15 @@ static int __init snd_gusmax_probe(int dev)
310 if (xdma2 >= 0) 332 if (xdma2 >= 0)
311 sprintf(card->longname + strlen(card->longname), "&%i", xdma2); 333 sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
312 334
313 if ((err = snd_card_set_generic_dev(card)) < 0) 335 snd_card_set_dev(card, &pdev->dev);
314 goto _err;
315 336
316 if ((err = snd_card_register(card)) < 0) 337 if ((err = snd_card_register(card)) < 0)
317 goto _err; 338 goto _err;
318 339
319 maxcard->gus = gus; 340 maxcard->gus = gus;
320 maxcard->cs4231 = cs4231; 341 maxcard->cs4231 = cs4231;
321 snd_gusmax_cards[dev] = card; 342
343 platform_set_drvdata(pdev, card);
322 return 0; 344 return 0;
323 345
324 _err: 346 _err:
@@ -326,53 +348,70 @@ static int __init snd_gusmax_probe(int dev)
326 return err; 348 return err;
327} 349}
328 350
329static int __init snd_gusmax_legacy_auto_probe(unsigned long xport) 351static int snd_gusmax_remove(struct platform_device *devptr)
330{ 352{
331 static int dev; 353 snd_card_free(platform_get_drvdata(devptr));
332 int res; 354 platform_set_drvdata(devptr, NULL);
333 355 return 0;
334 for ( ; dev < SNDRV_CARDS; dev++) { 356}
335 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) 357
336 continue; 358#define GUSMAX_DRIVER "snd_gusmax"
337 port[dev] = xport; 359
338 res = snd_gusmax_probe(dev); 360static struct platform_driver snd_gusmax_driver = {
339 if (res < 0) 361 .probe = snd_gusmax_probe,
340 port[dev] = SNDRV_AUTO_PORT; 362 .remove = snd_gusmax_remove,
341 return res; 363 /* FIXME: suspend/resume */
342 } 364 .driver = {
343 return -ENODEV; 365 .name = GUSMAX_DRIVER
366 },
367};
368
369static void __init_or_module snd_gusmax_unregister_all(void)
370{
371 int i;
372
373 for (i = 0; i < ARRAY_SIZE(devices); ++i)
374 platform_device_unregister(devices[i]);
375 platform_driver_unregister(&snd_gusmax_driver);
344} 376}
345 377
346static int __init alsa_card_gusmax_init(void) 378static int __init alsa_card_gusmax_init(void)
347{ 379{
348 static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1}; 380 int i, cards, err;
349 int dev, cards, i;
350
351 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) {
352 if (port[dev] == SNDRV_AUTO_PORT)
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 381
382 err = platform_driver_register(&snd_gusmax_driver);
383 if (err < 0)
384 return err;
385
386 cards = 0;
387 for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
388 struct platform_device *device;
389 device = platform_device_register_simple(GUSMAX_DRIVER,
390 i, NULL, 0);
391 if (IS_ERR(device)) {
392 err = PTR_ERR(device);
393 goto errout;
394 }
395 devices[i] = device;
396 cards++;
397 }
361 if (!cards) { 398 if (!cards) {
362#ifdef MODULE 399#ifdef MODULE
363 printk(KERN_ERR "GUS MAX soundcard not found or device busy\n"); 400 printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
364#endif 401#endif
365 return -ENODEV; 402 err = -ENODEV;
403 goto errout;
366 } 404 }
367 return 0; 405 return 0;
406
407 errout:
408 snd_gusmax_unregister_all();
409 return err;
368} 410}
369 411
370static void __exit alsa_card_gusmax_exit(void) 412static void __exit alsa_card_gusmax_exit(void)
371{ 413{
372 int idx; 414 snd_gusmax_unregister_all();
373
374 for (idx = 0; idx < SNDRV_CARDS; idx++)
375 snd_card_free(snd_gusmax_cards[idx]);
376} 415}
377 416
378module_init(alsa_card_gusmax_init) 417module_init(alsa_card_gusmax_init)