diff options
Diffstat (limited to 'sound/isa/gus/gusclassic.c')
-rw-r--r-- | sound/isa/gus/gusclassic.c | 116 |
1 files changed, 70 insertions, 46 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) |