diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-11-17 11:13:43 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:28:36 -0500 |
commit | 654aa661779703d3b22ba04a83ddeb1a0dd7a09a (patch) | |
tree | a113eb172cef6883c46966adbd3bd3399b87f881 | |
parent | 2a571ed13c853d132433c7e81509351823a7c8c6 (diff) |
[ALSA] gus - Use platform_device
Rewrite the probe/remove with platform_device.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/isa/gus/gusclassic.c | 116 | ||||
-rw-r--r-- | sound/isa/gus/gusextreme.c | 116 | ||||
-rw-r--r-- | sound/isa/gus/gusmax.c | 117 | ||||
-rw-r--r-- | sound/isa/gus/interwave.c | 292 |
4 files changed, 367 insertions, 274 deletions
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 6db484f71367..57beb74f5b9d 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -20,14 +20,15 @@ | |||
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 | #define SNDRV_LEGACY_AUTO_PROBE | ||
31 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 32 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
32 | #define SNDRV_LEGACY_FIND_FREE_DMA | 33 | #define SNDRV_LEGACY_FIND_FREE_DMA |
33 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
@@ -70,7 +71,6 @@ MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver."); | |||
70 | module_param_array(pcm_channels, int, NULL, 0444); | 71 | module_param_array(pcm_channels, int, NULL, 0444); |
71 | MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver."); | 72 | MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver."); |
72 | 73 | ||
73 | static struct snd_card *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
74 | 74 | ||
75 | #define PFX "gusclassic: " | 75 | #define PFX "gusclassic: " |
76 | 76 | ||
@@ -101,20 +101,19 @@ static void __init snd_gusclassic_init(int dev, struct snd_gus_card * gus) | |||
101 | gus->joystick_dac = joystick_dac[dev]; | 101 | gus->joystick_dac = joystick_dac[dev]; |
102 | } | 102 | } |
103 | 103 | ||
104 | static int __init snd_gusclassic_probe(int dev) | 104 | static int __init snd_gusclassic_probe(struct platform_device *pdev) |
105 | { | 105 | { |
106 | int dev = pdev->id; | ||
106 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; | 107 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; |
107 | static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; | 108 | static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; |
108 | int xirq, xdma1, xdma2; | 109 | int xirq, xdma1, xdma2; |
109 | struct snd_card *card; | 110 | struct snd_card *card; |
110 | struct snd_gusclassic *guscard; | ||
111 | struct snd_gus_card *gus = NULL; | 111 | struct snd_gus_card *gus = NULL; |
112 | int err; | 112 | int err; |
113 | 113 | ||
114 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 114 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); |
115 | if (card == NULL) | 115 | if (card == NULL) |
116 | return -ENOMEM; | 116 | return -ENOMEM; |
117 | guscard = (struct snd_gusclassic *)card->private_data; | ||
118 | if (pcm_channels[dev] < 2) | 117 | if (pcm_channels[dev] < 2) |
119 | pcm_channels[dev] = 2; | 118 | pcm_channels[dev] = 2; |
120 | 119 | ||
@@ -143,12 +142,31 @@ static int __init snd_gusclassic_probe(int dev) | |||
143 | } | 142 | } |
144 | } | 143 | } |
145 | 144 | ||
146 | 145 | if (port[dev] != SNDRV_AUTO_PORT) { | |
147 | if ((err = snd_gus_create(card, | 146 | err = snd_gus_create(card, |
148 | port[dev], | 147 | port[dev], |
149 | xirq, xdma1, xdma2, | 148 | xirq, xdma1, xdma2, |
150 | 0, channels[dev], pcm_channels[dev], | 149 | 0, channels[dev], pcm_channels[dev], |
151 | 0, &gus)) < 0) | 150 | 0, &gus); |
151 | } else { | ||
152 | /* auto-probe legacy ports */ | ||
153 | static unsigned long possible_ports[] = { | ||
154 | 0x220, 0x230, 0x240, 0x250, 0x260, | ||
155 | }; | ||
156 | int i; | ||
157 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
158 | err = snd_gus_create(card, | ||
159 | possible_ports[i], | ||
160 | xirq, xdma1, xdma2, | ||
161 | 0, channels[dev], pcm_channels[dev], | ||
162 | 0, &gus); | ||
163 | if (err >= 0) { | ||
164 | port[dev] = possible_ports[i]; | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | if (err < 0) | ||
152 | goto _err; | 170 | goto _err; |
153 | 171 | ||
154 | if ((err = snd_gusclassic_detect(gus)) < 0) | 172 | if ((err = snd_gusclassic_detect(gus)) < 0) |
@@ -178,13 +196,12 @@ static int __init snd_gusclassic_probe(int dev) | |||
178 | if (dma2 >= 0) | 196 | if (dma2 >= 0) |
179 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); | 197 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); |
180 | 198 | ||
181 | if ((err = snd_card_set_generic_dev(card)) < 0) | 199 | snd_card_set_dev(card, &pdev->dev); |
182 | goto _err; | ||
183 | 200 | ||
184 | if ((err = snd_card_register(card)) < 0) | 201 | if ((err = snd_card_register(card)) < 0) |
185 | goto _err; | 202 | goto _err; |
186 | 203 | ||
187 | snd_gusclassic_cards[dev] = card; | 204 | platform_set_drvdata(pdev, card); |
188 | return 0; | 205 | return 0; |
189 | 206 | ||
190 | _err: | 207 | _err: |
@@ -192,53 +209,60 @@ static int __init snd_gusclassic_probe(int dev) | |||
192 | return err; | 209 | return err; |
193 | } | 210 | } |
194 | 211 | ||
195 | static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport) | 212 | static int snd_gusclassic_remove(struct platform_device *devptr) |
196 | { | 213 | { |
197 | static int dev; | 214 | snd_card_free(platform_get_drvdata(devptr)); |
198 | int res; | 215 | platform_set_drvdata(devptr, NULL); |
199 | 216 | return 0; | |
200 | for ( ; dev < SNDRV_CARDS; dev++) { | ||
201 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | ||
202 | continue; | ||
203 | port[dev] = xport; | ||
204 | res = snd_gusclassic_probe(dev); | ||
205 | if (res < 0) | ||
206 | port[dev] = SNDRV_AUTO_PORT; | ||
207 | return res; | ||
208 | } | ||
209 | return -ENODEV; | ||
210 | } | 217 | } |
211 | 218 | ||
219 | #define GUSCLASSIC_DRIVER "snd_gusclassic" | ||
220 | |||
221 | static struct platform_driver snd_gusclassic_driver = { | ||
222 | .probe = snd_gusclassic_probe, | ||
223 | .remove = snd_gusclassic_remove, | ||
224 | /* FIXME: suspend/resume */ | ||
225 | .driver = { | ||
226 | .name = GUSCLASSIC_DRIVER | ||
227 | }, | ||
228 | }; | ||
229 | |||
212 | static int __init alsa_card_gusclassic_init(void) | 230 | static int __init alsa_card_gusclassic_init(void) |
213 | { | 231 | { |
214 | static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1}; | 232 | int i, cards, err; |
215 | int dev, cards, i; | 233 | |
216 | 234 | err = platform_driver_register(&snd_gusclassic_driver); | |
217 | for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) { | 235 | if (err < 0) |
218 | if (port[dev] == SNDRV_AUTO_PORT) | 236 | return err; |
219 | continue; | ||
220 | if (snd_gusclassic_probe(dev) >= 0) | ||
221 | cards++; | ||
222 | } | ||
223 | i = snd_legacy_auto_probe(possible_ports, snd_gusclassic_legacy_auto_probe); | ||
224 | if (i > 0) | ||
225 | cards += i; | ||
226 | 237 | ||
238 | cards = 0; | ||
239 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | ||
240 | struct platform_device *device; | ||
241 | device = platform_device_register_simple(GUSCLASSIC_DRIVER, | ||
242 | i, NULL, 0); | ||
243 | if (IS_ERR(device)) { | ||
244 | err = PTR_ERR(device); | ||
245 | goto errout; | ||
246 | } | ||
247 | cards++; | ||
248 | } | ||
227 | if (!cards) { | 249 | if (!cards) { |
228 | #ifdef MODULE | 250 | #ifdef MODULE |
229 | printk(KERN_ERR "GUS Classic soundcard not found or device busy\n"); | 251 | printk(KERN_ERR "GUS Classic soundcard not found or device busy\n"); |
230 | #endif | 252 | #endif |
231 | return -ENODEV; | 253 | err = -ENODEV; |
254 | goto errout; | ||
232 | } | 255 | } |
233 | return 0; | 256 | return 0; |
257 | |||
258 | errout: | ||
259 | platform_driver_unregister(&snd_gusclassic_driver); | ||
260 | return err; | ||
234 | } | 261 | } |
235 | 262 | ||
236 | static void __exit alsa_card_gusclassic_exit(void) | 263 | static void __exit alsa_card_gusclassic_exit(void) |
237 | { | 264 | { |
238 | int idx; | 265 | platform_driver_unregister(&snd_gusclassic_driver); |
239 | |||
240 | for (idx = 0; idx < SNDRV_CARDS; idx++) | ||
241 | snd_card_free(snd_gusclassic_cards[idx]); | ||
242 | } | 266 | } |
243 | 267 | ||
244 | module_init(alsa_card_gusclassic_init) | 268 | module_init(alsa_card_gusclassic_init) |
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) |
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) |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index f2e9c5073548..67a5f7402453 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -23,19 +23,20 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <sound/driver.h> | 25 | #include <sound/driver.h> |
26 | #include <asm/dma.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/err.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/delay.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/pnp.h> | 31 | #include <linux/pnp.h> |
31 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
33 | #include <asm/dma.h> | ||
32 | #include <sound/core.h> | 34 | #include <sound/core.h> |
33 | #include <sound/gus.h> | 35 | #include <sound/gus.h> |
34 | #include <sound/cs4231.h> | 36 | #include <sound/cs4231.h> |
35 | #ifdef SNDRV_STB | 37 | #ifdef SNDRV_STB |
36 | #include <sound/tea6330t.h> | 38 | #include <sound/tea6330t.h> |
37 | #endif | 39 | #endif |
38 | #define SNDRV_LEGACY_AUTO_PROBE | ||
39 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 40 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
40 | #define SNDRV_LEGACY_FIND_FREE_DMA | 41 | #define SNDRV_LEGACY_FIND_FREE_DMA |
41 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
@@ -75,8 +76,12 @@ static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | |||
75 | 76 | ||
76 | #ifdef SNDRV_STB | 77 | #ifdef SNDRV_STB |
77 | #define PFX "interwave-stb: " | 78 | #define PFX "interwave-stb: " |
79 | #define INTERWAVE_DRIVER "snd_interwave_stb" | ||
80 | #define INTERWAVE_PNP_DRIVER "interwave-stb" | ||
78 | #else | 81 | #else |
79 | #define PFX "interwave: " | 82 | #define PFX "interwave: " |
83 | #define INTERWAVE_DRIVER "snd_interwave" | ||
84 | #define INTERWAVE_PNP_DRIVER "interwave" | ||
80 | #endif | 85 | #endif |
81 | 86 | ||
82 | module_param_array(index, int, NULL, 0444); | 87 | module_param_array(index, int, NULL, 0444); |
@@ -128,7 +133,6 @@ struct snd_interwave { | |||
128 | #endif | 133 | #endif |
129 | }; | 134 | }; |
130 | 135 | ||
131 | static struct snd_card *snd_interwave_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
132 | 136 | ||
133 | #ifdef CONFIG_PNP | 137 | #ifdef CONFIG_PNP |
134 | 138 | ||
@@ -633,7 +637,7 @@ static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, | |||
633 | 637 | ||
634 | static void snd_interwave_free(struct snd_card *card) | 638 | static void snd_interwave_free(struct snd_card *card) |
635 | { | 639 | { |
636 | struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data; | 640 | struct snd_interwave *iwcard = card->private_data; |
637 | 641 | ||
638 | if (iwcard == NULL) | 642 | if (iwcard == NULL) |
639 | return; | 643 | return; |
@@ -644,14 +648,26 @@ static void snd_interwave_free(struct snd_card *card) | |||
644 | free_irq(iwcard->irq, (void *)iwcard); | 648 | free_irq(iwcard->irq, (void *)iwcard); |
645 | } | 649 | } |
646 | 650 | ||
647 | static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | 651 | static struct snd_card *snd_interwave_card_new(int dev) |
648 | const struct pnp_card_device_id *pid) | ||
649 | { | 652 | { |
650 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; | ||
651 | static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; | ||
652 | int xirq, xdma1, xdma2; | ||
653 | struct snd_card *card; | 653 | struct snd_card *card; |
654 | struct snd_interwave *iwcard; | 654 | struct snd_interwave *iwcard; |
655 | |||
656 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
657 | sizeof(struct snd_interwave)); | ||
658 | if (card == NULL) | ||
659 | return NULL; | ||
660 | iwcard = card->private_data; | ||
661 | iwcard->card = card; | ||
662 | iwcard->irq = -1; | ||
663 | card->private_free = snd_interwave_free; | ||
664 | return card; | ||
665 | } | ||
666 | |||
667 | static int __devinit snd_interwave_probe(struct snd_card *card, int dev) | ||
668 | { | ||
669 | int xirq, xdma1, xdma2; | ||
670 | struct snd_interwave *iwcard = card->private_data; | ||
655 | struct snd_cs4231 *cs4231; | 671 | struct snd_cs4231 *cs4231; |
656 | struct snd_gus_card *gus; | 672 | struct snd_gus_card *gus; |
657 | #ifdef SNDRV_STB | 673 | #ifdef SNDRV_STB |
@@ -661,59 +677,23 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | |||
661 | char *str; | 677 | char *str; |
662 | int err; | 678 | int err; |
663 | 679 | ||
664 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
665 | sizeof(struct snd_interwave)); | ||
666 | if (card == NULL) | ||
667 | return -ENOMEM; | ||
668 | iwcard = (struct snd_interwave *)card->private_data; | ||
669 | iwcard->card = card; | ||
670 | iwcard->irq = -1; | ||
671 | card->private_free = snd_interwave_free; | ||
672 | #ifdef CONFIG_PNP | ||
673 | if (isapnp[dev]) { | ||
674 | if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0) | ||
675 | goto _err; | ||
676 | snd_card_set_dev(card, &pcard->card->dev); | ||
677 | } | ||
678 | #endif | ||
679 | xirq = irq[dev]; | 680 | xirq = irq[dev]; |
680 | if (xirq == SNDRV_AUTO_IRQ) { | ||
681 | if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { | ||
682 | snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); | ||
683 | err = -EBUSY; | ||
684 | goto _err; | ||
685 | } | ||
686 | } | ||
687 | xdma1 = dma1[dev]; | 681 | xdma1 = dma1[dev]; |
688 | if (xdma1 == SNDRV_AUTO_DMA) { | ||
689 | if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { | ||
690 | snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); | ||
691 | err = -EBUSY; | ||
692 | goto _err; | ||
693 | } | ||
694 | } | ||
695 | xdma2 = dma2[dev]; | 682 | xdma2 = dma2[dev]; |
696 | if (xdma2 == SNDRV_AUTO_DMA) { | ||
697 | if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { | ||
698 | snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); | ||
699 | err = -EBUSY; | ||
700 | goto _err; | ||
701 | } | ||
702 | } | ||
703 | 683 | ||
704 | if ((err = snd_gus_create(card, | 684 | if ((err = snd_gus_create(card, |
705 | port[dev], | 685 | port[dev], |
706 | -xirq, xdma1, xdma2, | 686 | -xirq, xdma1, xdma2, |
707 | 0, 32, | 687 | 0, 32, |
708 | pcm_channels[dev], effect[dev], &gus)) < 0) | 688 | pcm_channels[dev], effect[dev], &gus)) < 0) |
709 | goto _err; | 689 | return err; |
710 | 690 | ||
711 | if ((err = snd_interwave_detect(iwcard, gus, dev | 691 | if ((err = snd_interwave_detect(iwcard, gus, dev |
712 | #ifdef SNDRV_STB | 692 | #ifdef SNDRV_STB |
713 | , &i2c_bus | 693 | , &i2c_bus |
714 | #endif | 694 | #endif |
715 | )) < 0) | 695 | )) < 0) |
716 | goto _err; | 696 | return err; |
717 | 697 | ||
718 | iwcard->gus_status_reg = gus->gf1.reg_irqstat; | 698 | iwcard->gus_status_reg = gus->gf1.reg_irqstat; |
719 | iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; | 699 | iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; |
@@ -721,12 +701,12 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | |||
721 | snd_interwave_init(dev, gus); | 701 | snd_interwave_init(dev, gus); |
722 | snd_interwave_detect_memory(gus); | 702 | snd_interwave_detect_memory(gus); |
723 | if ((err = snd_gus_initialize(gus)) < 0) | 703 | if ((err = snd_gus_initialize(gus)) < 0) |
724 | goto _err; | 704 | return err; |
725 | 705 | ||
726 | if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) { | 706 | if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, |
707 | "InterWave", iwcard)) { | ||
727 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); | 708 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); |
728 | err = -EBUSY; | 709 | return -EBUSY; |
729 | goto _err; | ||
730 | } | 710 | } |
731 | iwcard->irq = xirq; | 711 | iwcard->irq = xirq; |
732 | 712 | ||
@@ -738,26 +718,26 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | |||
738 | CS4231_HWSHARE_DMA1 | | 718 | CS4231_HWSHARE_DMA1 | |
739 | CS4231_HWSHARE_DMA2, | 719 | CS4231_HWSHARE_DMA2, |
740 | &cs4231)) < 0) | 720 | &cs4231)) < 0) |
741 | goto _err; | 721 | return err; |
742 | 722 | ||
743 | if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) | 723 | if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) |
744 | goto _err; | 724 | return err; |
745 | 725 | ||
746 | sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); | 726 | sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); |
747 | strcat(pcm->name, " (codec)"); | 727 | strcat(pcm->name, " (codec)"); |
748 | 728 | ||
749 | if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) | 729 | if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) |
750 | goto _err; | 730 | return err; |
751 | 731 | ||
752 | if ((err = snd_cs4231_mixer(cs4231)) < 0) | 732 | if ((err = snd_cs4231_mixer(cs4231)) < 0) |
753 | goto _err; | 733 | return err; |
754 | 734 | ||
755 | if (pcm_channels[dev] > 0) { | 735 | if (pcm_channels[dev] > 0) { |
756 | if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) | 736 | if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) |
757 | goto _err; | 737 | return err; |
758 | } | 738 | } |
759 | if ((err = snd_interwave_mixer(cs4231)) < 0) | 739 | if ((err = snd_interwave_mixer(cs4231)) < 0) |
760 | goto _err; | 740 | return err; |
761 | 741 | ||
762 | #ifdef SNDRV_STB | 742 | #ifdef SNDRV_STB |
763 | { | 743 | { |
@@ -769,19 +749,19 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | |||
769 | strcpy(id2.name, id1.name); | 749 | strcpy(id2.name, id1.name); |
770 | id2.index = 1; | 750 | id2.index = 1; |
771 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) | 751 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) |
772 | goto _err; | 752 | return err; |
773 | strcpy(id1.name, "Master Playback Volume"); | 753 | strcpy(id1.name, "Master Playback Volume"); |
774 | strcpy(id2.name, id1.name); | 754 | strcpy(id2.name, id1.name); |
775 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) | 755 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) |
776 | goto _err; | 756 | return err; |
777 | if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) | 757 | if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) |
778 | goto _err; | 758 | return err; |
779 | } | 759 | } |
780 | #endif | 760 | #endif |
781 | 761 | ||
782 | gus->uart_enable = midi[dev]; | 762 | gus->uart_enable = midi[dev]; |
783 | if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) | 763 | if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) |
784 | goto _err; | 764 | return err; |
785 | 765 | ||
786 | #ifndef SNDRV_STB | 766 | #ifndef SNDRV_STB |
787 | str = "AMD InterWave"; | 767 | str = "AMD InterWave"; |
@@ -800,121 +780,171 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard, | |||
800 | if (xdma2 >= 0) | 780 | if (xdma2 >= 0) |
801 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); | 781 | sprintf(card->longname + strlen(card->longname), "&%d", xdma2); |
802 | 782 | ||
803 | if ((err = snd_card_set_generic_dev(card)) < 0) | ||
804 | goto _err; | ||
805 | |||
806 | if ((err = snd_card_register(card)) < 0) | 783 | if ((err = snd_card_register(card)) < 0) |
807 | goto _err; | 784 | return err; |
808 | 785 | ||
809 | iwcard->cs4231 = cs4231; | 786 | iwcard->cs4231 = cs4231; |
810 | iwcard->gus = gus; | 787 | iwcard->gus = gus; |
811 | if (pcard) | ||
812 | pnp_set_card_drvdata(pcard, card); | ||
813 | else | ||
814 | snd_interwave_legacy[dev++] = card; | ||
815 | return 0; | 788 | return 0; |
789 | } | ||
816 | 790 | ||
817 | _err: | 791 | static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) |
818 | snd_card_free(card); | 792 | { |
819 | return err; | 793 | struct snd_card *card; |
794 | int err; | ||
795 | |||
796 | card = snd_interwave_card_new(dev); | ||
797 | if (! card) | ||
798 | return -ENOMEM; | ||
799 | |||
800 | snd_card_set_dev(card, &devptr->dev); | ||
801 | if ((err = snd_interwave_probe(card, dev)) < 0) { | ||
802 | snd_card_free(card); | ||
803 | return err; | ||
804 | } | ||
805 | platform_set_drvdata(devptr, card); | ||
806 | return 0; | ||
820 | } | 807 | } |
821 | 808 | ||
822 | static int __devinit snd_interwave_probe_legacy_port(unsigned long xport) | 809 | static int __init snd_interwave_nonpnp_probe(struct platform_device *pdev) |
823 | { | 810 | { |
824 | static int dev; | 811 | int dev = pdev->id; |
825 | int res; | 812 | int err; |
813 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; | ||
814 | static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; | ||
826 | 815 | ||
827 | for ( ; dev < SNDRV_CARDS; dev++) { | 816 | if (irq[dev] == SNDRV_AUTO_IRQ) { |
828 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | 817 | if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { |
829 | continue; | 818 | snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); |
830 | #ifdef CONFIG_PNP | 819 | return -EBUSY; |
831 | if (isapnp[dev]) | 820 | } |
832 | continue; | 821 | } |
833 | #endif | 822 | if (dma1[dev] == SNDRV_AUTO_DMA) { |
834 | port[dev] = xport; | 823 | if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { |
835 | res = snd_interwave_probe(dev, NULL, NULL); | 824 | snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); |
836 | if (res < 0) | 825 | return -EBUSY; |
837 | port[dev] = SNDRV_AUTO_PORT; | 826 | } |
838 | return res; | 827 | } |
828 | if (dma2[dev] == SNDRV_AUTO_DMA) { | ||
829 | if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { | ||
830 | snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); | ||
831 | return -EBUSY; | ||
832 | } | ||
833 | } | ||
834 | |||
835 | if (port[dev] != SNDRV_AUTO_PORT) | ||
836 | return snd_interwave_nonpnp_probe1(dev, pdev); | ||
837 | else { | ||
838 | static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; | ||
839 | int i; | ||
840 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
841 | port[dev] = possible_ports[i]; | ||
842 | err = snd_interwave_nonpnp_probe1(dev, pdev); | ||
843 | if (! err) | ||
844 | return 0; | ||
845 | } | ||
846 | return err; | ||
839 | } | 847 | } |
840 | return -ENODEV; | ||
841 | } | 848 | } |
842 | 849 | ||
850 | static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr) | ||
851 | { | ||
852 | snd_card_free(platform_get_drvdata(devptr)); | ||
853 | platform_set_drvdata(devptr, NULL); | ||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static struct platform_driver snd_interwave_driver = { | ||
858 | .probe = snd_interwave_nonpnp_probe, | ||
859 | .remove = __devexit_p(snd_interwave_nonpnp_remove), | ||
860 | /* FIXME: suspend,resume */ | ||
861 | .driver = { | ||
862 | .name = INTERWAVE_DRIVER | ||
863 | }, | ||
864 | }; | ||
865 | |||
843 | #ifdef CONFIG_PNP | 866 | #ifdef CONFIG_PNP |
844 | 867 | ||
845 | static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *card, | 868 | static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, |
846 | const struct pnp_card_device_id *id) | 869 | const struct pnp_card_device_id *pid) |
847 | { | 870 | { |
848 | static int dev; | 871 | static int dev; |
872 | struct snd_card *card; | ||
849 | int res; | 873 | int res; |
850 | 874 | ||
851 | for ( ; dev < SNDRV_CARDS; dev++) { | 875 | for ( ; dev < SNDRV_CARDS; dev++) { |
852 | if (!enable[dev] || !isapnp[dev]) | 876 | if (enable[dev] && isapnp[dev]) |
853 | continue; | 877 | break; |
854 | res = snd_interwave_probe(dev, card, id); | 878 | } |
855 | if (res < 0) | 879 | if (dev >= SNDRV_CARDS) |
856 | return res; | 880 | return -ENODEV; |
857 | dev++; | 881 | |
858 | return 0; | 882 | card = snd_interwave_card_new(dev); |
859 | } | 883 | if (! card) |
860 | 884 | return -ENOMEM; | |
861 | return -ENODEV; | 885 | |
886 | if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { | ||
887 | snd_card_free(card); | ||
888 | return res; | ||
889 | } | ||
890 | snd_card_set_dev(card, &pcard->card->dev); | ||
891 | if ((res = snd_interwave_probe(card, dev)) < 0) { | ||
892 | snd_card_free(card); | ||
893 | return res; | ||
894 | } | ||
895 | pnp_set_card_drvdata(pcard, card); | ||
896 | dev++; | ||
897 | return 0; | ||
862 | } | 898 | } |
863 | 899 | ||
864 | static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard) | 900 | static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard) |
865 | { | 901 | { |
866 | struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard); | 902 | snd_card_free(pnp_get_card_drvdata(pcard)); |
867 | 903 | pnp_set_card_drvdata(pcard, NULL); | |
868 | snd_card_disconnect(card); | ||
869 | snd_card_free_in_thread(card); | ||
870 | } | 904 | } |
871 | 905 | ||
872 | static struct pnp_card_driver interwave_pnpc_driver = { | 906 | static struct pnp_card_driver interwave_pnpc_driver = { |
873 | .flags = PNP_DRIVER_RES_DISABLE, | 907 | .flags = PNP_DRIVER_RES_DISABLE, |
874 | .name = "interwave", | 908 | .name = INTERWAVE_PNP_DRIVER, |
875 | .id_table = snd_interwave_pnpids, | 909 | .id_table = snd_interwave_pnpids, |
876 | .probe = snd_interwave_pnp_detect, | 910 | .probe = snd_interwave_pnp_detect, |
877 | .remove = __devexit_p(snd_interwave_pnp_remove), | 911 | .remove = __devexit_p(snd_interwave_pnp_remove), |
912 | /* FIXME: suspend,resume */ | ||
878 | }; | 913 | }; |
879 | 914 | ||
880 | #endif /* CONFIG_PNP */ | 915 | #endif /* CONFIG_PNP */ |
881 | 916 | ||
882 | static int __init alsa_card_interwave_init(void) | 917 | static int __init alsa_card_interwave_init(void) |
883 | { | 918 | { |
884 | int cards = 0, i; | 919 | int i, err, cards = 0; |
885 | static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1}; | ||
886 | int dev; | ||
887 | 920 | ||
888 | for (dev = 0; dev < SNDRV_CARDS; dev++) { | 921 | if ((err = platform_driver_register(&snd_interwave_driver)) < 0) |
889 | if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT) | 922 | return err; |
890 | continue; | 923 | |
924 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | ||
925 | struct platform_device *device; | ||
891 | #ifdef CONFIG_PNP | 926 | #ifdef CONFIG_PNP |
892 | if (isapnp[dev]) | 927 | if (isapnp[i]) |
893 | continue; | 928 | continue; |
894 | #endif | 929 | #endif |
895 | if (!snd_interwave_probe(dev, NULL, NULL)) { | 930 | device = platform_device_register_simple(INTERWAVE_DRIVER, |
896 | cards++; | 931 | i, NULL, 0); |
897 | continue; | 932 | if (IS_ERR(device)) { |
933 | err = PTR_ERR(device); | ||
934 | platform_driver_unregister(&snd_interwave_driver); | ||
935 | return err; | ||
898 | } | 936 | } |
899 | #ifdef MODULE | 937 | cards++; |
900 | printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]); | ||
901 | #endif | ||
902 | } | 938 | } |
903 | /* legacy auto configured cards */ | 939 | |
904 | i = snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port); | ||
905 | if (i > 0) | ||
906 | cards += i; | ||
907 | #ifdef CONFIG_PNP | ||
908 | /* ISA PnP cards */ | 940 | /* ISA PnP cards */ |
909 | i = pnp_register_card_driver(&interwave_pnpc_driver); | 941 | i = pnp_register_card_driver(&interwave_pnpc_driver); |
910 | if (i > 0) | 942 | if (i > 0) |
911 | cards += i; | 943 | cards += i; |
912 | #endif | ||
913 | 944 | ||
914 | if (!cards) { | 945 | if (!cards) { |
915 | #ifdef CONFIG_PNP | ||
916 | pnp_unregister_card_driver(&interwave_pnpc_driver); | 946 | pnp_unregister_card_driver(&interwave_pnpc_driver); |
917 | #endif | 947 | platform_driver_unregister(&snd_interwave_driver); |
918 | #ifdef MODULE | 948 | #ifdef MODULE |
919 | printk(KERN_ERR "InterWave soundcard not found or device busy\n"); | 949 | printk(KERN_ERR "InterWave soundcard not found or device busy\n"); |
920 | #endif | 950 | #endif |
@@ -925,14 +955,8 @@ static int __init alsa_card_interwave_init(void) | |||
925 | 955 | ||
926 | static void __exit alsa_card_interwave_exit(void) | 956 | static void __exit alsa_card_interwave_exit(void) |
927 | { | 957 | { |
928 | int dev; | ||
929 | |||
930 | #ifdef CONFIG_PNP | ||
931 | /* PnP cards first */ | ||
932 | pnp_unregister_card_driver(&interwave_pnpc_driver); | 958 | pnp_unregister_card_driver(&interwave_pnpc_driver); |
933 | #endif | 959 | platform_driver_unregister(&snd_interwave_driver); |
934 | for (dev = 0; dev < SNDRV_CARDS; dev++) | ||
935 | snd_card_free(snd_interwave_legacy[dev]); | ||
936 | } | 960 | } |
937 | 961 | ||
938 | module_init(alsa_card_interwave_init) | 962 | module_init(alsa_card_interwave_init) |