diff options
Diffstat (limited to 'sound/isa/es1688/es1688.c')
-rw-r--r-- | sound/isa/es1688/es1688.c | 130 |
1 files changed, 84 insertions, 46 deletions
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 26a7d335ed8e..50d23cf3d7cc 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -20,16 +20,17 @@ | |||
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/time.h> | 26 | #include <linux/time.h> |
26 | #include <linux/wait.h> | 27 | #include <linux/wait.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/es1688.h> | 31 | #include <sound/es1688.h> |
30 | #include <sound/mpu401.h> | 32 | #include <sound/mpu401.h> |
31 | #include <sound/opl3.h> | 33 | #include <sound/opl3.h> |
32 | #define SNDRV_LEGACY_AUTO_PROBE | ||
33 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 34 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
34 | #define SNDRV_LEGACY_FIND_FREE_DMA | 35 | #define SNDRV_LEGACY_FIND_FREE_DMA |
35 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
@@ -68,19 +69,20 @@ MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver."); | |||
68 | module_param_array(dma8, int, NULL, 0444); | 69 | module_param_array(dma8, int, NULL, 0444); |
69 | MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver."); | 70 | MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver."); |
70 | 71 | ||
71 | static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | 72 | static struct platform_device *devices[SNDRV_CARDS]; |
72 | 73 | ||
73 | #define PFX "es1688: " | 74 | #define PFX "es1688: " |
74 | 75 | ||
75 | static int __init snd_audiodrive_probe(int dev) | 76 | static int __init snd_es1688_probe(struct platform_device *pdev) |
76 | { | 77 | { |
78 | int dev = pdev->id; | ||
77 | static int possible_irqs[] = {5, 9, 10, 7, -1}; | 79 | static int possible_irqs[] = {5, 9, 10, 7, -1}; |
78 | static int possible_dmas[] = {1, 3, 0, -1}; | 80 | static int possible_dmas[] = {1, 3, 0, -1}; |
79 | int xirq, xdma, xmpu_irq; | 81 | int xirq, xdma, xmpu_irq; |
80 | snd_card_t *card; | 82 | struct snd_card *card; |
81 | es1688_t *chip; | 83 | struct snd_es1688 *chip; |
82 | opl3_t *opl3; | 84 | struct snd_opl3 *opl3; |
83 | snd_pcm_t *pcm; | 85 | struct snd_pcm *pcm; |
84 | int err; | 86 | int err; |
85 | 87 | ||
86 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 88 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); |
@@ -105,10 +107,30 @@ static int __init snd_audiodrive_probe(int dev) | |||
105 | } | 107 | } |
106 | } | 108 | } |
107 | 109 | ||
108 | if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], | 110 | if (port[dev] != SNDRV_AUTO_PORT) { |
109 | xirq, xmpu_irq, xdma, | 111 | if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], |
110 | ES1688_HW_AUTO, &chip)) < 0) | 112 | xirq, xmpu_irq, xdma, |
111 | goto _err; | 113 | ES1688_HW_AUTO, &chip)) < 0) |
114 | goto _err; | ||
115 | } else { | ||
116 | /* auto-probe legacy ports */ | ||
117 | static unsigned long possible_ports[] = { | ||
118 | 0x220, 0x240, 0x260, | ||
119 | }; | ||
120 | int i; | ||
121 | for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { | ||
122 | err = snd_es1688_create(card, possible_ports[i], | ||
123 | mpu_port[dev], | ||
124 | xirq, xmpu_irq, xdma, | ||
125 | ES1688_HW_AUTO, &chip); | ||
126 | if (err >= 0) { | ||
127 | port[dev] = possible_ports[i]; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | if (i >= ARRAY_SIZE(possible_ports)) | ||
132 | goto _err; | ||
133 | } | ||
112 | 134 | ||
113 | if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) | 135 | if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) |
114 | goto _err; | 136 | goto _err; |
@@ -136,13 +158,12 @@ static int __init snd_audiodrive_probe(int dev) | |||
136 | goto _err; | 158 | goto _err; |
137 | } | 159 | } |
138 | 160 | ||
139 | if ((err = snd_card_set_generic_dev(card)) < 0) | 161 | snd_card_set_dev(card, &pdev->dev); |
140 | goto _err; | ||
141 | 162 | ||
142 | if ((err = snd_card_register(card)) < 0) | 163 | if ((err = snd_card_register(card)) < 0) |
143 | goto _err; | 164 | goto _err; |
144 | 165 | ||
145 | snd_audiodrive_cards[dev] = card; | 166 | platform_set_drvdata(pdev, card); |
146 | return 0; | 167 | return 0; |
147 | 168 | ||
148 | _err: | 169 | _err: |
@@ -150,53 +171,70 @@ static int __init snd_audiodrive_probe(int dev) | |||
150 | return err; | 171 | return err; |
151 | } | 172 | } |
152 | 173 | ||
153 | static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport) | 174 | static int snd_es1688_remove(struct platform_device *devptr) |
154 | { | 175 | { |
155 | static int dev; | 176 | snd_card_free(platform_get_drvdata(devptr)); |
156 | int res; | 177 | platform_set_drvdata(devptr, NULL); |
157 | 178 | return 0; | |
158 | for ( ; dev < SNDRV_CARDS; dev++) { | 179 | } |
159 | if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) | 180 | |
160 | continue; | 181 | #define ES1688_DRIVER "snd_es1688" |
161 | port[dev] = xport; | 182 | |
162 | res = snd_audiodrive_probe(dev); | 183 | static struct platform_driver snd_es1688_driver = { |
163 | if (res < 0) | 184 | .probe = snd_es1688_probe, |
164 | port[dev] = SNDRV_AUTO_PORT; | 185 | .remove = snd_es1688_remove, |
165 | return res; | 186 | /* FIXME: suspend/resume */ |
166 | } | 187 | .driver = { |
167 | return -ENODEV; | 188 | .name = ES1688_DRIVER |
189 | }, | ||
190 | }; | ||
191 | |||
192 | static void __init_or_module snd_es1688_unregister_all(void) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | for (i = 0; i < ARRAY_SIZE(devices); ++i) | ||
197 | platform_device_unregister(devices[i]); | ||
198 | platform_driver_unregister(&snd_es1688_driver); | ||
168 | } | 199 | } |
169 | 200 | ||
170 | static int __init alsa_card_es1688_init(void) | 201 | static int __init alsa_card_es1688_init(void) |
171 | { | 202 | { |
172 | static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1}; | 203 | int i, cards, err; |
173 | int dev, cards = 0, i; | 204 | |
174 | 205 | err = platform_driver_register(&snd_es1688_driver); | |
175 | for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) { | 206 | if (err < 0) |
176 | if (port[dev] == SNDRV_AUTO_PORT) | 207 | return err; |
177 | continue; | 208 | |
178 | if (snd_audiodrive_probe(dev) >= 0) | 209 | cards = 0; |
179 | cards++; | 210 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { |
211 | struct platform_device *device; | ||
212 | device = platform_device_register_simple(ES1688_DRIVER, | ||
213 | i, NULL, 0); | ||
214 | if (IS_ERR(device)) { | ||
215 | err = PTR_ERR(device); | ||
216 | goto errout; | ||
217 | } | ||
218 | devices[i] = device; | ||
219 | cards++; | ||
180 | } | 220 | } |
181 | i = snd_legacy_auto_probe(possible_ports, snd_audiodrive_legacy_auto_probe); | ||
182 | if (i > 0) | ||
183 | cards += i; | ||
184 | |||
185 | if (!cards) { | 221 | if (!cards) { |
186 | #ifdef MODULE | 222 | #ifdef MODULE |
187 | printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n"); | 223 | printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n"); |
188 | #endif | 224 | #endif |
189 | return -ENODEV; | 225 | err = -ENODEV; |
226 | goto errout; | ||
190 | } | 227 | } |
191 | return 0; | 228 | return 0; |
229 | |||
230 | errout: | ||
231 | snd_es1688_unregister_all(); | ||
232 | return err; | ||
192 | } | 233 | } |
193 | 234 | ||
194 | static void __exit alsa_card_es1688_exit(void) | 235 | static void __exit alsa_card_es1688_exit(void) |
195 | { | 236 | { |
196 | int idx; | 237 | snd_es1688_unregister_all(); |
197 | |||
198 | for (idx = 0; idx < SNDRV_CARDS; idx++) | ||
199 | snd_card_free(snd_audiodrive_cards[idx]); | ||
200 | } | 238 | } |
201 | 239 | ||
202 | module_init(alsa_card_es1688_init) | 240 | module_init(alsa_card_es1688_init) |