aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt21
-rw-r--r--include/sound/es1688.h1
-rw-r--r--sound/isa/Kconfig16
-rw-r--r--sound/isa/es1688/es1688.c205
-rw-r--r--sound/isa/es1688/es1688_lib.c3
-rw-r--r--sound/isa/sb/Makefile2
-rw-r--r--sound/isa/sb/es968.c248
7 files changed, 190 insertions, 306 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index dc681badca67..2075bbb8b3e2 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -632,28 +632,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
632 632
633 The power-management is supported. 633 The power-management is supported.
634 634
635 Module snd-es968
636 ----------------
637
638 Module for sound cards based on ESS ES968 chip (PnP only).
639
640 This module supports multiple cards, PnP and autoprobe.
641
642 The power-management is supported.
643
644 Module snd-es1688 635 Module snd-es1688
645 ----------------- 636 -----------------
646 637
647 Module for ESS AudioDrive ES-1688 and ES-688 sound cards. 638 Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
648 639
649 port - port # for ES-1688 chip (0x220,0x240,0x260) 640 isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
650 fm_port - port # for OPL3 (option; share the same port as default)
651 mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) 641 mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
652 irq - IRQ # for ES-1688 chip (5,7,9,10)
653 mpu_irq - IRQ # for MPU-401 port (5,7,9,10) 642 mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
643 fm_port - port # for OPL3 (option; share the same port as default)
644
645 with isapnp=0, the following additional options are available:
646 port - port # for ES-1688 chip (0x220,0x240,0x260)
647 irq - IRQ # for ES-1688 chip (5,7,9,10)
654 dma8 - DMA # for ES-1688 chip (0,1,3) 648 dma8 - DMA # for ES-1688 chip (0,1,3)
655 649
656 This module supports multiple cards and autoprobe (without MPU-401 port). 650 This module supports multiple cards and autoprobe (without MPU-401 port)
651 and PnP with the ES968 chip.
657 652
658 Module snd-es18xx 653 Module snd-es18xx
659 ----------------- 654 -----------------
diff --git a/include/sound/es1688.h b/include/sound/es1688.h
index 4c29572effb2..3ec7ecbe2502 100644
--- a/include/sound/es1688.h
+++ b/include/sound/es1688.h
@@ -117,5 +117,6 @@ int snd_es1688_create(struct snd_card *card,
117int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device, 117int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device,
118 struct snd_pcm **rpcm); 118 struct snd_pcm **rpcm);
119int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip); 119int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip);
120int snd_es1688_reset(struct snd_es1688 *chip);
120 121
121#endif /* __SOUND_ES1688_H */ 122#endif /* __SOUND_ES1688_H */
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 755a0a5f0e3f..c6990c680796 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -128,26 +128,14 @@ config SND_CS4236
128 To compile this driver as a module, choose M here: the module 128 To compile this driver as a module, choose M here: the module
129 will be called snd-cs4236. 129 will be called snd-cs4236.
130 130
131config SND_ES968
132 tristate "Generic ESS ES968 driver"
133 depends on PNP
134 select ISAPNP
135 select SND_MPU401_UART
136 select SND_SB8_DSP
137 help
138 Say Y here to include support for ESS AudioDrive ES968 chips.
139
140 To compile this driver as a module, choose M here: the module
141 will be called snd-es968.
142
143config SND_ES1688 131config SND_ES1688
144 tristate "Generic ESS ES688/ES1688 driver" 132 tristate "Generic ESS ES688/ES1688 and ES968 PnP driver"
145 select SND_OPL3_LIB 133 select SND_OPL3_LIB
146 select SND_MPU401_UART 134 select SND_MPU401_UART
147 select SND_PCM 135 select SND_PCM
148 help 136 help
149 Say Y here to include support for ESS AudioDrive ES688 or 137 Say Y here to include support for ESS AudioDrive ES688 or
150 ES1688 chips. 138 ES1688 chips. Also, this module support cards with ES968 PnP chip.
151 139
152 To compile this driver as a module, choose M here: the module 140 To compile this driver as a module, choose M here: the module
153 will be called snd-es1688. 141 will be called snd-es1688.
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 281679493fb4..fdcce311f80a 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -22,6 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/err.h> 23#include <linux/err.h>
24#include <linux/isa.h> 24#include <linux/isa.h>
25#include <linux/isapnp.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>
@@ -45,8 +46,13 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
45 "{ESS,ES688 AudioDrive,pnp:ESS6881}," 46 "{ESS,ES688 AudioDrive,pnp:ESS6881},"
46 "{ESS,ES1688 AudioDrive,pnp:ESS1681}}"); 47 "{ESS,ES1688 AudioDrive,pnp:ESS1681}}");
47 48
49MODULE_ALIAS("snd_es968");
50
48static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 51static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
49static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 52static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
53#ifdef CONFIG_PNP
54static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
55#endif
50static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 56static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
51static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ 57static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
52static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */ 58static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */
@@ -60,6 +66,10 @@ MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
60module_param_array(id, charp, NULL, 0444); 66module_param_array(id, charp, NULL, 0444);
61MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); 67MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
62module_param_array(enable, bool, NULL, 0444); 68module_param_array(enable, bool, NULL, 0444);
69#ifdef CONFIG_PNP
70module_param_array(isapnp, bool, NULL, 0444);
71MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
72#endif
63MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); 73MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
64module_param_array(port, long, NULL, 0444); 74module_param_array(port, long, NULL, 0444);
65MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); 75MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
@@ -74,14 +84,21 @@ MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
74module_param_array(dma8, int, NULL, 0444); 84module_param_array(dma8, int, NULL, 0444);
75MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); 85MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
76 86
87#ifdef CONFIG_PNP
88#define is_isapnp_selected(dev) isapnp[dev]
89#else
90#define is_isapnp_selected(dev) 0
91#endif
92
77static int __devinit snd_es1688_match(struct device *dev, unsigned int n) 93static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
78{ 94{
79 return enable[n]; 95 return enable[n] && !is_isapnp_selected(n);
80} 96}
81 97
82static int __devinit snd_es1688_legacy_create(struct snd_card *card, 98static int __devinit snd_es1688_legacy_create(struct snd_card *card,
83 struct snd_es1688 *chip, struct device *dev, unsigned int n) 99 struct device *dev, unsigned int n)
84{ 100{
101 struct snd_es1688 *chip = card->private_data;
85 static long possible_ports[] = {0x220, 0x240, 0x260}; 102 static long possible_ports[] = {0x220, 0x240, 0x260};
86 static int possible_irqs[] = {5, 9, 10, 7, -1}; 103 static int possible_irqs[] = {5, 9, 10, 7, -1};
87 static int possible_dmas[] = {1, 3, 0, -1}; 104 static int possible_dmas[] = {1, 3, 0, -1};
@@ -117,32 +134,20 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card,
117 return error; 134 return error;
118} 135}
119 136
120static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) 137static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
121{ 138{
122 struct snd_card *card; 139 struct snd_es1688 *chip = card->private_data;
123 struct snd_es1688 *chip;
124 struct snd_opl3 *opl3; 140 struct snd_opl3 *opl3;
125 struct snd_pcm *pcm; 141 struct snd_pcm *pcm;
126 int error; 142 int error;
127 143
128 error = snd_card_create(index[n], id[n], THIS_MODULE,
129 sizeof(struct snd_es1688), &card);
130 if (error < 0)
131 return error;
132
133 chip = card->private_data;
134
135 error = snd_es1688_legacy_create(card, chip, dev, n);
136 if (error < 0)
137 goto out;
138
139 error = snd_es1688_pcm(card, chip, 0, &pcm); 144 error = snd_es1688_pcm(card, chip, 0, &pcm);
140 if (error < 0) 145 if (error < 0)
141 goto out; 146 return error;
142 147
143 error = snd_es1688_mixer(card, chip); 148 error = snd_es1688_mixer(card, chip);
144 if (error < 0) 149 if (error < 0)
145 goto out; 150 return error;
146 151
147 strcpy(card->driver, "ES1688"); 152 strcpy(card->driver, "ES1688");
148 strcpy(card->shortname, pcm->name); 153 strcpy(card->shortname, pcm->name);
@@ -155,12 +160,12 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n)
155 if (fm_port[n] > 0) { 160 if (fm_port[n] > 0) {
156 if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2, 161 if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
157 OPL3_HW_OPL3, 0, &opl3) < 0) 162 OPL3_HW_OPL3, 0, &opl3) < 0)
158 dev_warn(dev, 163 dev_warn(card->dev,
159 "opl3 not detected at 0x%lx\n", fm_port[n]); 164 "opl3 not detected at 0x%lx\n", fm_port[n]);
160 else { 165 else {
161 error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); 166 error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
162 if (error < 0) 167 if (error < 0)
163 goto out; 168 return error;
164 } 169 }
165 } 170 }
166 171
@@ -170,23 +175,41 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n)
170 chip->mpu_port, 0, 175 chip->mpu_port, 0,
171 mpu_irq[n], IRQF_DISABLED, NULL); 176 mpu_irq[n], IRQF_DISABLED, NULL);
172 if (error < 0) 177 if (error < 0)
173 goto out; 178 return error;
174 } 179 }
175 180
181 return snd_card_register(card);
182}
183
184static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n)
185{
186 struct snd_card *card;
187 int error;
188
189 error = snd_card_create(index[n], id[n], THIS_MODULE,
190 sizeof(struct snd_es1688), &card);
191 if (error < 0)
192 return error;
193
194 error = snd_es1688_legacy_create(card, dev, n);
195 if (error < 0)
196 goto out;
197
176 snd_card_set_dev(card, dev); 198 snd_card_set_dev(card, dev);
177 199
178 error = snd_card_register(card); 200 error = snd_es1688_probe(card, n);
179 if (error < 0) 201 if (error < 0)
180 goto out; 202 goto out;
181 203
182 dev_set_drvdata(dev, card); 204 dev_set_drvdata(dev, card);
183 return 0;
184 205
185out: snd_card_free(card); 206 return 0;
207out:
208 snd_card_free(card);
186 return error; 209 return error;
187} 210}
188 211
189static int __devexit snd_es1688_remove(struct device *dev, unsigned int n) 212static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
190{ 213{
191 snd_card_free(dev_get_drvdata(dev)); 214 snd_card_free(dev_get_drvdata(dev));
192 dev_set_drvdata(dev, NULL); 215 dev_set_drvdata(dev, NULL);
@@ -195,8 +218,8 @@ static int __devexit snd_es1688_remove(struct device *dev, unsigned int n)
195 218
196static struct isa_driver snd_es1688_driver = { 219static struct isa_driver snd_es1688_driver = {
197 .match = snd_es1688_match, 220 .match = snd_es1688_match,
198 .probe = snd_es1688_probe, 221 .probe = snd_es1688_isa_probe,
199 .remove = __devexit_p(snd_es1688_remove), 222 .remove = __devexit_p(snd_es1688_isa_remove),
200#if 0 /* FIXME */ 223#if 0 /* FIXME */
201 .suspend = snd_es1688_suspend, 224 .suspend = snd_es1688_suspend,
202 .resume = snd_es1688_resume, 225 .resume = snd_es1688_resume,
@@ -206,14 +229,140 @@ static struct isa_driver snd_es1688_driver = {
206 } 229 }
207}; 230};
208 231
232static int snd_es968_pnp_is_probed;
233
234#ifdef CONFIG_PNP
235static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
236 struct pnp_card_link *pcard,
237 const struct pnp_card_device_id *pid)
238{
239 struct snd_es1688 *chip = card->private_data;
240 struct pnp_dev *pdev;
241 int error;
242
243 pdev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
244 if (pdev == NULL)
245 return -ENODEV;
246
247 error = pnp_activate_dev(pdev);
248 if (error < 0) {
249 snd_printk(KERN_ERR "ES968 pnp configure failure\n");
250 return error;
251 }
252 port[n] = pnp_port_start(pdev, 0);
253 dma8[n] = pnp_dma(pdev, 0);
254 irq[n] = pnp_irq(pdev, 0);
255
256 return snd_es1688_create(card, chip, port[n], mpu_port[n], irq[n],
257 mpu_irq[n], dma8[n], ES1688_HW_AUTO);
258}
259
260static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
261 const struct pnp_card_device_id *pid)
262{
263 struct snd_card *card;
264 static unsigned int dev;
265 int error;
266 struct snd_es1688 *chip;
267
268 if (snd_es968_pnp_is_probed)
269 return -EBUSY;
270 for ( ; dev < SNDRV_CARDS; dev++) {
271 if (enable[dev] && isapnp[dev])
272 break;
273 }
274
275 error = snd_card_create(index[dev], id[dev], THIS_MODULE,
276 sizeof(struct snd_es1688), &card);
277 if (error < 0)
278 return error;
279 chip = card->private_data;
280
281 error = snd_card_es968_pnp(card, dev, pcard, pid);
282 if (error < 0) {
283 snd_card_free(card);
284 return error;
285 }
286 snd_card_set_dev(card, &pcard->card->dev);
287 error = snd_es1688_probe(card, dev);
288 if (error < 0)
289 return error;
290 pnp_set_card_drvdata(pcard, card);
291 snd_es968_pnp_is_probed = 1;
292 return 0;
293}
294
295static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
296{
297 snd_card_free(pnp_get_card_drvdata(pcard));
298 pnp_set_card_drvdata(pcard, NULL);
299 snd_es968_pnp_is_probed = 0;
300}
301
302#ifdef CONFIG_PM
303static int snd_es968_pnp_suspend(struct pnp_card_link *pcard,
304 pm_message_t state)
305{
306 struct snd_card *card = pnp_get_card_drvdata(pcard);
307 struct snd_es1688 *chip = card->private_data;
308
309 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
310 snd_pcm_suspend_all(chip->pcm);
311 return 0;
312}
313
314static int snd_es968_pnp_resume(struct pnp_card_link *pcard)
315{
316 struct snd_card *card = pnp_get_card_drvdata(pcard);
317 struct snd_es1688 *chip = card->private_data;
318
319 snd_es1688_reset(chip);
320 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
321 return 0;
322}
323#endif
324
325static struct pnp_card_device_id snd_es968_pnpids[] = {
326 { .id = "ESS0968", .devs = { { "@@@0968" }, } },
327 { .id = "ESS0968", .devs = { { "ESS0968" }, } },
328 { .id = "", } /* end */
329};
330
331MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
332
333static struct pnp_card_driver es968_pnpc_driver = {
334 .flags = PNP_DRIVER_RES_DISABLE,
335 .name = DEV_NAME " PnP",
336 .id_table = snd_es968_pnpids,
337 .probe = snd_es968_pnp_detect,
338 .remove = __devexit_p(snd_es968_pnp_remove),
339#ifdef CONFIG_PM
340 .suspend = snd_es968_pnp_suspend,
341 .resume = snd_es968_pnp_resume,
342#endif
343};
344#endif
345
209static int __init alsa_card_es1688_init(void) 346static int __init alsa_card_es1688_init(void)
210{ 347{
348#ifdef CONFIG_PNP
349 pnp_register_card_driver(&es968_pnpc_driver);
350 if (snd_es968_pnp_is_probed)
351 return 0;
352 pnp_unregister_card_driver(&es968_pnpc_driver);
353#endif
211 return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS); 354 return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS);
212} 355}
213 356
214static void __exit alsa_card_es1688_exit(void) 357static void __exit alsa_card_es1688_exit(void)
215{ 358{
216 isa_unregister_driver(&snd_es1688_driver); 359 if (!snd_es968_pnp_is_probed) {
360 isa_unregister_driver(&snd_es1688_driver);
361 return;
362 }
363#ifdef CONFIG_PNP
364 pnp_unregister_card_driver(&es968_pnpc_driver);
365#endif
217} 366}
218 367
219module_init(alsa_card_es1688_init); 368module_init(alsa_card_es1688_init);
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index fdd440417bf0..07676200496a 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -99,7 +99,7 @@ static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned cha
99 return result; 99 return result;
100} 100}
101 101
102static int snd_es1688_reset(struct snd_es1688 *chip) 102int snd_es1688_reset(struct snd_es1688 *chip)
103{ 103{
104 int i; 104 int i;
105 105
@@ -115,6 +115,7 @@ static int snd_es1688_reset(struct snd_es1688 *chip)
115 snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */ 115 snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */
116 return 0; 116 return 0;
117} 117}
118EXPORT_SYMBOL(snd_es1688_reset);
118 119
119static int snd_es1688_probe(struct snd_es1688 *chip) 120static int snd_es1688_probe(struct snd_es1688 *chip)
120{ 121{
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile
index af3669681788..08b9fb974658 100644
--- a/sound/isa/sb/Makefile
+++ b/sound/isa/sb/Makefile
@@ -11,7 +11,6 @@ snd-sb8-objs := sb8.o
11snd-sb16-objs := sb16.o 11snd-sb16-objs := sb16.o
12snd-sbawe-objs := sbawe.o emu8000.o 12snd-sbawe-objs := sbawe.o emu8000.o
13snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o 13snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o
14snd-es968-objs := es968.o
15snd-jazz16-objs := jazz16.o 14snd-jazz16-objs := jazz16.o
16 15
17# Toplevel Module Dependency 16# Toplevel Module Dependency
@@ -21,7 +20,6 @@ obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o
21obj-$(CONFIG_SND_SB8) += snd-sb8.o 20obj-$(CONFIG_SND_SB8) += snd-sb8.o
22obj-$(CONFIG_SND_SB16) += snd-sb16.o 21obj-$(CONFIG_SND_SB16) += snd-sb16.o
23obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o 22obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o
24obj-$(CONFIG_SND_ES968) += snd-es968.o
25obj-$(CONFIG_SND_JAZZ16) += snd-jazz16.o 23obj-$(CONFIG_SND_JAZZ16) += snd-jazz16.o
26ifeq ($(CONFIG_SND_SB16_CSP),y) 24ifeq ($(CONFIG_SND_SB16_CSP),y)
27 obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o 25 obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
deleted file mode 100644
index ff18286fef9d..000000000000
--- a/sound/isa/sb/es968.c
+++ /dev/null
@@ -1,248 +0,0 @@
1
2/*
3 card-es968.c - driver for ESS AudioDrive ES968 based soundcards.
4 Copyright (C) 1999 by Massimo Piccioni <dafastidio@libero.it>
5
6 Thanks to Pierfrancesco 'qM2' Passerini.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/init.h>
24#include <linux/time.h>
25#include <linux/pnp.h>
26#include <linux/moduleparam.h>
27#include <sound/core.h>
28#include <sound/initval.h>
29#include <sound/sb.h>
30
31#define PFX "es968: "
32
33MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
34MODULE_DESCRIPTION("ESS AudioDrive ES968");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{ESS,AudioDrive ES968}}");
37
38static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
39static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
40static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
41static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
42static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
43static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
44
45module_param_array(index, int, NULL, 0444);
46MODULE_PARM_DESC(index, "Index value for es968 based soundcard.");
47module_param_array(id, charp, NULL, 0444);
48MODULE_PARM_DESC(id, "ID string for es968 based soundcard.");
49module_param_array(enable, bool, NULL, 0444);
50MODULE_PARM_DESC(enable, "Enable es968 based soundcard.");
51
52struct snd_card_es968 {
53 struct pnp_dev *dev;
54 struct snd_sb *chip;
55};
56
57static struct pnp_card_device_id snd_es968_pnpids[] = {
58 { .id = "ESS0968", .devs = { { "@@@0968" }, } },
59 { .id = "", } /* end */
60};
61
62MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
63
64#define DRIVER_NAME "snd-card-es968"
65
66static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id)
67{
68 struct snd_sb *chip = dev_id;
69
70 if (chip->open & SB_OPEN_PCM) {
71 return snd_sb8dsp_interrupt(chip);
72 } else {
73 return snd_sb8dsp_midi_interrupt(chip);
74 }
75}
76
77static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
78 struct pnp_card_link *card,
79 const struct pnp_card_device_id *id)
80{
81 struct pnp_dev *pdev;
82 int err;
83
84 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
85 if (acard->dev == NULL)
86 return -ENODEV;
87
88 pdev = acard->dev;
89
90 err = pnp_activate_dev(pdev);
91 if (err < 0) {
92 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
93 return err;
94 }
95 port[dev] = pnp_port_start(pdev, 0);
96 dma8[dev] = pnp_dma(pdev, 0);
97 irq[dev] = pnp_irq(pdev, 0);
98
99 return 0;
100}
101
102static int __devinit snd_card_es968_probe(int dev,
103 struct pnp_card_link *pcard,
104 const struct pnp_card_device_id *pid)
105{
106 int error;
107 struct snd_sb *chip;
108 struct snd_card *card;
109 struct snd_card_es968 *acard;
110
111 error = snd_card_create(index[dev], id[dev], THIS_MODULE,
112 sizeof(struct snd_card_es968), &card);
113 if (error < 0)
114 return error;
115 acard = card->private_data;
116 if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) {
117 snd_card_free(card);
118 return error;
119 }
120 snd_card_set_dev(card, &pcard->card->dev);
121
122 if ((error = snd_sbdsp_create(card, port[dev],
123 irq[dev],
124 snd_card_es968_interrupt,
125 dma8[dev],
126 -1,
127 SB_HW_AUTO, &chip)) < 0) {
128 snd_card_free(card);
129 return error;
130 }
131 acard->chip = chip;
132
133 if ((error = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
134 snd_card_free(card);
135 return error;
136 }
137
138 if ((error = snd_sbmixer_new(chip)) < 0) {
139 snd_card_free(card);
140 return error;
141 }
142
143 if ((error = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
144 snd_card_free(card);
145 return error;
146 }
147
148 strcpy(card->driver, "ES968");
149 strcpy(card->shortname, "ESS ES968");
150 sprintf(card->longname, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
151 card->shortname, chip->name, chip->port, irq[dev], dma8[dev]);
152
153 if ((error = snd_card_register(card)) < 0) {
154 snd_card_free(card);
155 return error;
156 }
157 pnp_set_card_drvdata(pcard, card);
158 return 0;
159}
160
161static unsigned int __devinitdata es968_devices;
162
163static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
164 const struct pnp_card_device_id *id)
165{
166 static int dev;
167 int res;
168
169 for ( ; dev < SNDRV_CARDS; dev++) {
170 if (!enable[dev])
171 continue;
172 res = snd_card_es968_probe(dev, card, id);
173 if (res < 0)
174 return res;
175 dev++;
176 es968_devices++;
177 return 0;
178 }
179 return -ENODEV;
180}
181
182static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
183{
184 snd_card_free(pnp_get_card_drvdata(pcard));
185 pnp_set_card_drvdata(pcard, NULL);
186}
187
188#ifdef CONFIG_PM
189static int snd_es968_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
190{
191 struct snd_card *card = pnp_get_card_drvdata(pcard);
192 struct snd_card_es968 *acard = card->private_data;
193 struct snd_sb *chip = acard->chip;
194
195 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
196 snd_pcm_suspend_all(chip->pcm);
197 snd_sbmixer_suspend(chip);
198 return 0;
199}
200
201static int snd_es968_pnp_resume(struct pnp_card_link *pcard)
202{
203 struct snd_card *card = pnp_get_card_drvdata(pcard);
204 struct snd_card_es968 *acard = card->private_data;
205 struct snd_sb *chip = acard->chip;
206
207 snd_sbdsp_reset(chip);
208 snd_sbmixer_resume(chip);
209 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
210 return 0;
211}
212#endif
213
214static struct pnp_card_driver es968_pnpc_driver = {
215 .flags = PNP_DRIVER_RES_DISABLE,
216 .name = "es968",
217 .id_table = snd_es968_pnpids,
218 .probe = snd_es968_pnp_detect,
219 .remove = __devexit_p(snd_es968_pnp_remove),
220#ifdef CONFIG_PM
221 .suspend = snd_es968_pnp_suspend,
222 .resume = snd_es968_pnp_resume,
223#endif
224};
225
226static int __init alsa_card_es968_init(void)
227{
228 int err = pnp_register_card_driver(&es968_pnpc_driver);
229 if (err)
230 return err;
231
232 if (!es968_devices) {
233 pnp_unregister_card_driver(&es968_pnpc_driver);
234#ifdef MODULE
235 snd_printk(KERN_ERR "no ES968 based soundcards found\n");
236#endif
237 return -ENODEV;
238 }
239 return 0;
240}
241
242static void __exit alsa_card_es968_exit(void)
243{
244 pnp_unregister_card_driver(&es968_pnpc_driver);
245}
246
247module_init(alsa_card_es968_init)
248module_exit(alsa_card_es968_exit)