aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/wavefront
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/isa/wavefront
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/isa/wavefront')
-rw-r--r--sound/isa/wavefront/Makefile9
-rw-r--r--sound/isa/wavefront/wavefront.c716
-rw-r--r--sound/isa/wavefront/wavefront_fx.c1019
-rw-r--r--sound/isa/wavefront/wavefront_midi.c570
-rw-r--r--sound/isa/wavefront/wavefront_synth.c2243
5 files changed, 4557 insertions, 0 deletions
diff --git a/sound/isa/wavefront/Makefile b/sound/isa/wavefront/Makefile
new file mode 100644
index 000000000000..b4cb28422db0
--- /dev/null
+++ b/sound/isa/wavefront/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o
7
8# Toplevel Module Dependency
9obj-$(CONFIG_SND_WAVEFRONT) += snd-wavefront.o
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
new file mode 100644
index 000000000000..79b022070ba3
--- /dev/null
+++ b/sound/isa/wavefront/wavefront.c
@@ -0,0 +1,716 @@
1/*
2 * ALSA card-level driver for Turtle Beach Wavefront cards
3 * (Maui,Tropez,Tropez+)
4 *
5 * Copyright (c) 1997-1999 by Paul Barton-Davis <pbd@op.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/slab.h>
26#include <linux/pnp.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/initval.h>
30#include <sound/opl3.h>
31#include <sound/snd_wavefront.h>
32
33MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>");
34MODULE_DESCRIPTION("Turtle Beach Wavefront");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
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; /* Enable this card */
41static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
42static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
43static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
44static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
45static int cs4232_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
46static long ics2115_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
47static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */
48static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
49static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
50static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
51static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for WaveFront soundcard.");
57module_param_array(enable, bool, NULL, 0444);
58MODULE_PARM_DESC(enable, "Enable WaveFront soundcard.");
59#ifdef CONFIG_PNP
60module_param_array(isapnp, bool, NULL, 0444);
61MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards.");
62#endif
63module_param_array(cs4232_pcm_port, long, NULL, 0444);
64MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface.");
65module_param_array(cs4232_pcm_irq, int, NULL, 0444);
66MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
67module_param_array(dma1, int, NULL, 0444);
68MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface.");
69module_param_array(dma2, int, NULL, 0444);
70MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface.");
71module_param_array(cs4232_mpu_port, long, NULL, 0444);
72MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface.");
73module_param_array(cs4232_mpu_irq, int, NULL, 0444);
74MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface.");
75module_param_array(ics2115_irq, int, NULL, 0444);
76MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115.");
77module_param_array(ics2115_port, long, NULL, 0444);
78MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115.");
79module_param_array(fm_port, long, NULL, 0444);
80MODULE_PARM_DESC(fm_port, "FM port #.");
81module_param_array(use_cs4232_midi, bool, NULL, 0444);
82MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
83
84static snd_card_t *snd_wavefront_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
85
86#ifdef CONFIG_PNP
87
88static struct pnp_card_device_id snd_wavefront_pnpids[] = {
89 /* Tropez */
90 { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } },
91 /* Tropez+ */
92 { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } },
93 { .id = "" }
94};
95
96MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids);
97
98static int __devinit
99snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card,
100 const struct pnp_card_device_id *id)
101{
102 struct pnp_dev *pdev;
103 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
104 int err;
105
106 if (!cfg)
107 return -ENOMEM;
108
109 /* Check for each logical device. */
110
111 /* CS4232 chip (aka "windows sound system") is logical device 0 */
112
113 acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
114 if (acard->wss == NULL) {
115 kfree(cfg);
116 return -EBUSY;
117 }
118
119 /* there is a game port at logical device 1, but we ignore it completely */
120
121 /* the control interface is logical device 2, but we ignore it
122 completely. in fact, nobody even seems to know what it
123 does.
124 */
125
126 /* Only configure the CS4232 MIDI interface if its been
127 specifically requested. It is logical device 3.
128 */
129
130 if (use_cs4232_midi[dev]) {
131 acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
132 if (acard->mpu == NULL) {
133 kfree(cfg);
134 return -EBUSY;
135 }
136 }
137
138 /* The ICS2115 synth is logical device 4 */
139
140 acard->synth = pnp_request_card_device(card, id->devs[3].id, NULL);
141 if (acard->synth == NULL) {
142 kfree(cfg);
143 return -EBUSY;
144 }
145
146 /* PCM/FM initialization */
147
148 pdev = acard->wss;
149
150 pnp_init_resource_table(cfg);
151
152 /* An interesting note from the Tropez+ FAQ:
153
154 Q. [Ports] Why is the base address of the WSS I/O ports off by 4?
155
156 A. WSS I/O requires a block of 8 I/O addresses ("ports"). Of these, the first
157 4 are used to identify and configure the board. With the advent of PnP,
158 these first 4 addresses have become obsolete, and software applications
159 only use the last 4 addresses to control the codec chip. Therefore, the
160 base address setting "skips past" the 4 unused addresses.
161
162 */
163
164 if (cs4232_pcm_port[dev] != SNDRV_AUTO_PORT)
165 pnp_resource_change(&cfg->port_resource[0], cs4232_pcm_port[dev], 4);
166 if (fm_port[dev] != SNDRV_AUTO_PORT)
167 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
168 if (dma1[dev] != SNDRV_AUTO_DMA)
169 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
170 if (dma2[dev] != SNDRV_AUTO_DMA)
171 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
172 if (cs4232_pcm_irq[dev] != SNDRV_AUTO_IRQ)
173 pnp_resource_change(&cfg->irq_resource[0], cs4232_pcm_irq[dev], 1);
174
175 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
176 snd_printk(KERN_ERR "PnP WSS the requested resources are invalid, using auto config\n");
177 err = pnp_activate_dev(pdev);
178 if (err < 0) {
179 snd_printk(KERN_ERR "PnP WSS pnp configure failure\n");
180 kfree(cfg);
181 return err;
182 }
183
184 cs4232_pcm_port[dev] = pnp_port_start(pdev, 0);
185 fm_port[dev] = pnp_port_start(pdev, 1);
186 dma1[dev] = pnp_dma(pdev, 0);
187 dma2[dev] = pnp_dma(pdev, 1);
188 cs4232_pcm_irq[dev] = pnp_irq(pdev, 0);
189
190 /* Synth initialization */
191
192 pdev = acard->synth;
193
194 pnp_init_resource_table(cfg);
195
196 if (ics2115_port[dev] != SNDRV_AUTO_PORT) {
197 pnp_resource_change(&cfg->port_resource[0], ics2115_port[dev], 16);
198 }
199
200 if (ics2115_port[dev] != SNDRV_AUTO_IRQ) {
201 pnp_resource_change(&cfg->irq_resource[0], ics2115_irq[dev], 1);
202 }
203
204 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
205 snd_printk(KERN_ERR "PnP ICS2115 the requested resources are invalid, using auto config\n");
206 err = pnp_activate_dev(pdev);
207 if (err < 0) {
208 snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n");
209 kfree(cfg);
210 return err;
211 }
212
213 ics2115_port[dev] = pnp_port_start(pdev, 0);
214 ics2115_irq[dev] = pnp_irq(pdev, 0);
215
216 /* CS4232 MPU initialization. Configure this only if
217 explicitly requested, since its physically inaccessible and
218 consumes another IRQ.
219 */
220
221 if (use_cs4232_midi[dev]) {
222
223 pdev = acard->mpu;
224
225 pnp_init_resource_table(cfg);
226
227 if (cs4232_mpu_port[dev] != SNDRV_AUTO_PORT)
228 pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_port[dev], 2);
229 if (cs4232_mpu_irq[dev] != SNDRV_AUTO_IRQ)
230 pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_irq[dev], 1);
231
232 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
233 snd_printk(KERN_ERR "PnP MPU401 the requested resources are invalid, using auto config\n");
234 err = pnp_activate_dev(pdev);
235 if (err < 0) {
236 snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n");
237 cs4232_mpu_port[dev] = SNDRV_AUTO_PORT;
238 } else {
239 cs4232_mpu_port[dev] = pnp_port_start(pdev, 0);
240 cs4232_mpu_irq[dev] = pnp_irq(pdev, 0);
241 }
242
243 snd_printk ("CS4232 MPU: port=0x%lx, irq=%i\n",
244 cs4232_mpu_port[dev],
245 cs4232_mpu_irq[dev]);
246 }
247
248 snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n",
249 cs4232_pcm_port[dev],
250 fm_port[dev],
251 dma1[dev],
252 dma2[dev],
253 cs4232_pcm_irq[dev],
254 ics2115_port[dev],
255 ics2115_irq[dev]);
256
257 kfree(cfg);
258 return 0;
259}
260
261#endif /* CONFIG_PNP */
262
263static irqreturn_t snd_wavefront_ics2115_interrupt(int irq,
264 void *dev_id,
265 struct pt_regs *regs)
266{
267 snd_wavefront_card_t *acard;
268
269 acard = (snd_wavefront_card_t *) dev_id;
270
271 if (acard == NULL)
272 return IRQ_NONE;
273
274 if (acard->wavefront.interrupts_are_midi) {
275 snd_wavefront_midi_interrupt (acard);
276 } else {
277 snd_wavefront_internal_interrupt (acard);
278 }
279 return IRQ_HANDLED;
280}
281
282static snd_hwdep_t * __devinit
283snd_wavefront_new_synth (snd_card_t *card,
284 int hw_dev,
285 snd_wavefront_card_t *acard)
286{
287 snd_hwdep_t *wavefront_synth;
288
289 if (snd_wavefront_detect (acard) < 0) {
290 return NULL;
291 }
292
293 if (snd_wavefront_start (&acard->wavefront) < 0) {
294 return NULL;
295 }
296
297 if (snd_hwdep_new(card, "WaveFront", hw_dev, &wavefront_synth) < 0)
298 return NULL;
299 strcpy (wavefront_synth->name,
300 "WaveFront (ICS2115) wavetable synthesizer");
301 wavefront_synth->ops.open = snd_wavefront_synth_open;
302 wavefront_synth->ops.release = snd_wavefront_synth_release;
303 wavefront_synth->ops.ioctl = snd_wavefront_synth_ioctl;
304
305 return wavefront_synth;
306}
307
308static snd_hwdep_t * __devinit
309snd_wavefront_new_fx (snd_card_t *card,
310 int hw_dev,
311 snd_wavefront_card_t *acard,
312 unsigned long port)
313
314{
315 snd_hwdep_t *fx_processor;
316
317 if (snd_wavefront_fx_start (&acard->wavefront)) {
318 snd_printk ("cannot initialize YSS225 FX processor");
319 return NULL;
320 }
321
322 if (snd_hwdep_new (card, "YSS225", hw_dev, &fx_processor) < 0)
323 return NULL;
324 sprintf (fx_processor->name, "YSS225 FX Processor at 0x%lx", port);
325 fx_processor->ops.open = snd_wavefront_fx_open;
326 fx_processor->ops.release = snd_wavefront_fx_release;
327 fx_processor->ops.ioctl = snd_wavefront_fx_ioctl;
328
329 return fx_processor;
330}
331
332static snd_wavefront_mpu_id internal_id = internal_mpu;
333static snd_wavefront_mpu_id external_id = external_mpu;
334
335static snd_rawmidi_t * __devinit
336snd_wavefront_new_midi (snd_card_t *card,
337 int midi_dev,
338 snd_wavefront_card_t *acard,
339 unsigned long port,
340 snd_wavefront_mpu_id mpu)
341
342{
343 snd_rawmidi_t *rmidi;
344 static int first = 1;
345
346 if (first) {
347 first = 0;
348 acard->wavefront.midi.base = port;
349 if (snd_wavefront_midi_start (acard)) {
350 snd_printk ("cannot initialize MIDI interface\n");
351 return NULL;
352 }
353 }
354
355 if (snd_rawmidi_new (card, "WaveFront MIDI", midi_dev, 1, 1, &rmidi) < 0)
356 return NULL;
357
358 if (mpu == internal_mpu) {
359 strcpy(rmidi->name, "WaveFront MIDI (Internal)");
360 rmidi->private_data = &internal_id;
361 } else {
362 strcpy(rmidi->name, "WaveFront MIDI (External)");
363 rmidi->private_data = &external_id;
364 }
365
366 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_wavefront_midi_output);
367 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input);
368
369 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
370 SNDRV_RAWMIDI_INFO_INPUT |
371 SNDRV_RAWMIDI_INFO_DUPLEX;
372
373 return rmidi;
374}
375
376static void
377snd_wavefront_free(snd_card_t *card)
378{
379 snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
380
381 if (acard) {
382 if (acard->wavefront.res_base != NULL) {
383 release_resource(acard->wavefront.res_base);
384 kfree_nocheck(acard->wavefront.res_base);
385 }
386 if (acard->wavefront.irq > 0)
387 free_irq(acard->wavefront.irq, (void *)acard);
388 }
389}
390
391static int __devinit
392snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
393 const struct pnp_card_device_id *pid)
394{
395 snd_card_t *card;
396 snd_wavefront_card_t *acard;
397 cs4231_t *chip;
398 snd_hwdep_t *wavefront_synth;
399 snd_rawmidi_t *ics2115_internal_rmidi = NULL;
400 snd_rawmidi_t *ics2115_external_rmidi = NULL;
401 snd_hwdep_t *fx_processor;
402 int hw_dev = 0, midi_dev = 0, err;
403
404#ifdef CONFIG_PNP
405 if (!isapnp[dev]) {
406#endif
407 if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
408 snd_printk("specify CS4232 port\n");
409 return -EINVAL;
410 }
411 if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
412 snd_printk("specify ICS2115 port\n");
413 return -ENODEV;
414 }
415#ifdef CONFIG_PNP
416 }
417#endif
418 card = snd_card_new (index[dev],
419 id[dev],
420 THIS_MODULE,
421 sizeof(snd_wavefront_card_t));
422
423 if (card == NULL) {
424 return -ENOMEM;
425 }
426 acard = (snd_wavefront_card_t *)card->private_data;
427 acard->wavefront.irq = -1;
428 spin_lock_init(&acard->wavefront.irq_lock);
429 init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
430 spin_lock_init(&acard->wavefront.midi.open);
431 spin_lock_init(&acard->wavefront.midi.virtual);
432 card->private_free = snd_wavefront_free;
433
434#ifdef CONFIG_PNP
435 if (isapnp[dev]) {
436 if (snd_wavefront_pnp (dev, acard, pcard, pid) < 0) {
437 if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
438 snd_printk ("isapnp detection failed\n");
439 snd_card_free (card);
440 return -ENODEV;
441 }
442 }
443 snd_card_set_dev(card, &pcard->card->dev);
444 }
445#endif /* CONFIG_PNP */
446
447 /* --------- PCM --------------- */
448
449 if ((err = snd_cs4231_create (card,
450 cs4232_pcm_port[dev],
451 -1,
452 cs4232_pcm_irq[dev],
453 dma1[dev],
454 dma2[dev],
455 CS4231_HW_DETECT, 0, &chip)) < 0) {
456 snd_card_free(card);
457 snd_printk ("can't allocate CS4231 device\n");
458 return err;
459 }
460
461 if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0) {
462 snd_card_free(card);
463 return err;
464 }
465 if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0) {
466 snd_card_free(card);
467 return err;
468 }
469
470 /* ---------- OPL3 synth --------- */
471
472 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
473 opl3_t *opl3;
474
475 if ((err = snd_opl3_create(card,
476 fm_port[dev],
477 fm_port[dev] + 2,
478 OPL3_HW_OPL3_CS,
479 0, &opl3)) < 0) {
480 snd_printk ("can't allocate or detect OPL3 synth\n");
481 snd_card_free(card);
482 return err;
483 }
484
485 if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0) {
486 snd_card_free(card);
487 return err;
488 }
489 hw_dev++;
490 }
491
492 /* ------- ICS2115 Wavetable synth ------- */
493
494 if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16, "ICS2115")) == NULL) {
495 snd_printk("unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", ics2115_port[dev], ics2115_port[dev] + 16 - 1);
496 snd_card_free(card);
497 return -EBUSY;
498 }
499 if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, SA_INTERRUPT, "ICS2115", (void *)acard)) {
500 snd_printk("unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
501 snd_card_free(card);
502 return -EBUSY;
503 }
504
505 acard->wavefront.irq = ics2115_irq[dev];
506 acard->wavefront.base = ics2115_port[dev];
507
508 if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) {
509 snd_printk ("can't create WaveFront synth device\n");
510 snd_card_free(card);
511 return -ENOMEM;
512 }
513
514 strcpy (wavefront_synth->name, "ICS2115 Wavetable MIDI Synthesizer");
515 wavefront_synth->iface = SNDRV_HWDEP_IFACE_ICS2115;
516 hw_dev++;
517
518 /* --------- Mixer ------------ */
519
520 if ((err = snd_cs4231_mixer(chip)) < 0) {
521 snd_printk ("can't allocate mixer device\n");
522 snd_card_free(card);
523 return err;
524 }
525
526 /* -------- CS4232 MPU-401 interface -------- */
527
528 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
529 if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
530 cs4232_mpu_port[dev], 0,
531 cs4232_mpu_irq[dev],
532 SA_INTERRUPT,
533 NULL)) < 0) {
534 snd_printk ("can't allocate CS4232 MPU-401 device\n");
535 snd_card_free(card);
536 return err;
537 }
538 midi_dev++;
539 }
540
541 /* ------ ICS2115 internal MIDI ------------ */
542
543 if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) {
544 ics2115_internal_rmidi =
545 snd_wavefront_new_midi (card,
546 midi_dev,
547 acard,
548 ics2115_port[dev],
549 internal_mpu);
550 if (ics2115_internal_rmidi == NULL) {
551 snd_printk ("can't setup ICS2115 internal MIDI device\n");
552 snd_card_free(card);
553 return -ENOMEM;
554 }
555 midi_dev++;
556 }
557
558 /* ------ ICS2115 external MIDI ------------ */
559
560 if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) {
561 ics2115_external_rmidi =
562 snd_wavefront_new_midi (card,
563 midi_dev,
564 acard,
565 ics2115_port[dev],
566 external_mpu);
567 if (ics2115_external_rmidi == NULL) {
568 snd_printk ("can't setup ICS2115 external MIDI device\n");
569 snd_card_free(card);
570 return -ENOMEM;
571 }
572 midi_dev++;
573 }
574
575 /* FX processor for Tropez+ */
576
577 if (acard->wavefront.has_fx) {
578 fx_processor = snd_wavefront_new_fx (card,
579 hw_dev,
580 acard,
581 ics2115_port[dev]);
582 if (fx_processor == NULL) {
583 snd_printk ("can't setup FX device\n");
584 snd_card_free(card);
585 return -ENOMEM;
586 }
587
588 hw_dev++;
589
590 strcpy(card->driver, "Tropez+");
591 strcpy(card->shortname, "Turtle Beach Tropez+");
592 } else {
593 /* Need a way to distinguish between Maui and Tropez */
594 strcpy(card->driver, "WaveFront");
595 strcpy(card->shortname, "Turtle Beach WaveFront");
596 }
597
598 /* ----- Register the card --------- */
599
600 /* Not safe to include "Turtle Beach" in longname, due to
601 length restrictions
602 */
603
604 sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d",
605 card->driver,
606 chip->port,
607 cs4232_pcm_irq[dev],
608 dma1[dev]);
609
610 if (dma2[dev] >= 0 && dma2[dev] < 8)
611 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
612
613 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
614 sprintf (card->longname + strlen (card->longname),
615 " MPU-401 0x%lx irq %d",
616 cs4232_mpu_port[dev],
617 cs4232_mpu_irq[dev]);
618 }
619
620 sprintf (card->longname + strlen (card->longname),
621 " SYNTH 0x%lx irq %d",
622 ics2115_port[dev],
623 ics2115_irq[dev]);
624
625 if ((err = snd_card_register(card)) < 0) {
626 snd_card_free(card);
627 return err;
628 }
629 if (pcard)
630 pnp_set_card_drvdata(pcard, card);
631 else
632 snd_wavefront_legacy[dev] = card;
633 return 0;
634}
635
636#ifdef CONFIG_PNP
637
638static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *card,
639 const struct pnp_card_device_id *id)
640{
641 static int dev;
642 int res;
643
644 for ( ; dev < SNDRV_CARDS; dev++) {
645 if (!enable[dev] || !isapnp[dev])
646 continue;
647 res = snd_wavefront_probe(dev, card, id);
648 if (res < 0)
649 return res;
650 dev++;
651 return 0;
652 }
653
654 return -ENODEV;
655}
656
657static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
658{
659 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
660
661 snd_card_disconnect(card);
662 snd_card_free_in_thread(card);
663}
664
665static struct pnp_card_driver wavefront_pnpc_driver = {
666 .flags = PNP_DRIVER_RES_DISABLE,
667 .name = "wavefront",
668 .id_table = snd_wavefront_pnpids,
669 .probe = snd_wavefront_pnp_detect,
670 .remove = __devexit_p(snd_wavefront_pnp_remove),
671};
672
673#endif /* CONFIG_PNP */
674
675static int __init alsa_card_wavefront_init(void)
676{
677 int cards = 0;
678 int dev;
679 for (dev = 0; dev < SNDRV_CARDS; dev++) {
680 if (!enable[dev])
681 continue;
682#ifdef CONFIG_PNP
683 if (isapnp[dev])
684 continue;
685#endif
686 if (snd_wavefront_probe(dev, NULL, NULL) >= 0)
687 cards++;
688 }
689#ifdef CONFIG_PNP
690 cards += pnp_register_card_driver(&wavefront_pnpc_driver);
691#endif
692 if (!cards) {
693#ifdef CONFIG_PNP
694 pnp_unregister_card_driver(&wavefront_pnpc_driver);
695#endif
696#ifdef MODULE
697 printk (KERN_ERR "No WaveFront cards found or devices busy\n");
698#endif
699 return -ENODEV;
700 }
701 return 0;
702}
703
704static void __exit alsa_card_wavefront_exit(void)
705{
706 int idx;
707
708#ifdef CONFIG_PNP
709 pnp_unregister_card_driver(&wavefront_pnpc_driver);
710#endif
711 for (idx = 0; idx < SNDRV_CARDS; idx++)
712 snd_card_free(snd_wavefront_legacy[idx]);
713}
714
715module_init(alsa_card_wavefront_init)
716module_exit(alsa_card_wavefront_exit)
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
new file mode 100644
index 000000000000..0e13623f69f0
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -0,0 +1,1019 @@
1/*
2 * Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <sound/driver.h>
20#include <asm/io.h>
21#include <linux/init.h>
22#include <linux/time.h>
23#include <linux/wait.h>
24#include <sound/core.h>
25#include <sound/snd_wavefront.h>
26#include <sound/initval.h>
27
28/* Control bits for the Load Control Register
29 */
30
31#define FX_LSB_TRANSFER 0x01 /* transfer after DSP LSB byte written */
32#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */
33#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */
34
35/* weird stuff, derived from port I/O tracing with dosemu */
36
37unsigned char page_zero[] __initdata = {
380x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
390x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
400x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
410x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
500x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
510x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
520x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
530xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
540x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
550x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
560x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
570x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
580x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
590x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
600x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
610x1d, 0x02, 0xdf
62};
63
64unsigned char page_one[] __initdata = {
650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
660x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
670x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
680xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
770x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
780x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
790x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
800x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
810x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
820x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
830x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
840xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
860xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
870x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
880x60, 0x00, 0x1b
89};
90
91unsigned char page_two[] __initdata = {
920xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
930x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
940x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
970x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
980x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
990x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
1000x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
1010x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
1020x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
1030x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
104};
105
106unsigned char page_three[] __initdata = {
1070x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
1080x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
1130xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
1140x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
1150x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1160x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
1170x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
1180x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
119};
120
121unsigned char page_four[] __initdata = {
1220x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
1230x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1280x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
1290x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
1300x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
1310x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
1320x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
1330x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
134};
135
136unsigned char page_six[] __initdata = {
1370x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
1380x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
1390x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
1400x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
1410x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
1420x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
1430x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
1440x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
1450x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
1460x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
1470x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
1480x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
1490x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
1500x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
1510x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
1520x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
1530x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
1540x80, 0x00, 0x7e, 0x80, 0x80
155};
156
157unsigned char page_seven[] __initdata = {
1580x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
1590x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1600x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
1610xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1620x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1630x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1670x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
1720x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
1730xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
1740x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
1750x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
1760x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
1770xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
1780x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
1790xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
1800x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810x00, 0x02, 0x00
182};
183
184unsigned char page_zero_v2[] __initdata = {
1850x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1860x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1870x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1890x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1910x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194};
195
196unsigned char page_one_v2[] __initdata = {
1970x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
1980x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1990x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2000x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2010x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2020x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2030x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2040x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206};
207
208unsigned char page_two_v2[] __initdata = {
2090x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130x00, 0x00, 0x00, 0x00
214};
215unsigned char page_three_v2[] __initdata = {
2160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2170x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2180x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2200x00, 0x00, 0x00, 0x00
221};
222unsigned char page_four_v2[] __initdata = {
2230x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270x00, 0x00, 0x00, 0x00
228};
229
230unsigned char page_seven_v2[] __initdata = {
2310x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2330x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2340x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2350x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2370x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2380x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2390x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240};
241
242unsigned char mod_v2[] __initdata = {
2430x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
2440x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
2450x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
2460x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
2470xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
2480x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
2490x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
2500xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
2510x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
2520x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
2530x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
2540x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
2550x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
2560x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
2570x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
2580xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
2590x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
2600x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
2610x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
2620x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
2630xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
2640x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
2650xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
2660x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
2670xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
2680x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
2690x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
2700x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
271};
272unsigned char coefficients[] __initdata = {
2730x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
2740x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
2750x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
2760x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
2770x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
2780x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
2790x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
2800x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
2810x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
2820x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
2830x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
2840x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
2850x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
2860x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
2870x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
2880x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
2890x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
2900x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
2910x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
2920x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
2930x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
2940x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
2950x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
2960x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
2970x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
2980x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
2990x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
3000x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
3010x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
3020x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
3030x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
3040x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
3050x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
3060xba
307};
308unsigned char coefficients2[] __initdata = {
3090x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
3100xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
3110x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
3120x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
3130x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
314};
315unsigned char coefficients3[] __initdata = {
3160x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
3170x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
3180x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
3190x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
3200x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
3210x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
3220x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
3230x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
3240x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
3250xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
3260x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
3270xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
3280x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
3290x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
3300x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
3310x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
3320x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
3330x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
3340x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
3350x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
3360x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
3370x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
3380x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
3390x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
3400x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
3410xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
3420x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
3430xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
3440x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
3450xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
3460x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
3470x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
3480x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
3490x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
3500x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
3510x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
3520x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
353};
354
355static int
356wavefront_fx_idle (snd_wavefront_t *dev)
357
358{
359 int i;
360 unsigned int x = 0x80;
361
362 for (i = 0; i < 1000; i++) {
363 x = inb (dev->fx_status);
364 if ((x & 0x80) == 0) {
365 break;
366 }
367 }
368
369 if (x & 0x80) {
370 snd_printk ("FX device never idle.\n");
371 return 0;
372 }
373
374 return (1);
375}
376
377static void
378wavefront_fx_mute (snd_wavefront_t *dev, int onoff)
379
380{
381 if (!wavefront_fx_idle(dev)) {
382 return;
383 }
384
385 outb (onoff ? 0x02 : 0x00, dev->fx_op);
386}
387
388static int
389wavefront_fx_memset (snd_wavefront_t *dev,
390 int page,
391 int addr,
392 int cnt,
393 unsigned short *data)
394{
395 if (page < 0 || page > 7) {
396 snd_printk ("FX memset: "
397 "page must be >= 0 and <= 7\n");
398 return -(EINVAL);
399 }
400
401 if (addr < 0 || addr > 0x7f) {
402 snd_printk ("FX memset: "
403 "addr must be >= 0 and <= 7f\n");
404 return -(EINVAL);
405 }
406
407 if (cnt == 1) {
408
409 outb (FX_LSB_TRANSFER, dev->fx_lcr);
410 outb (page, dev->fx_dsp_page);
411 outb (addr, dev->fx_dsp_addr);
412 outb ((data[0] >> 8), dev->fx_dsp_msb);
413 outb ((data[0] & 0xff), dev->fx_dsp_lsb);
414
415 snd_printk ("FX: addr %d:%x set to 0x%x\n",
416 page, addr, data[0]);
417
418 } else {
419 int i;
420
421 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
422 outb (page, dev->fx_dsp_page);
423 outb (addr, dev->fx_dsp_addr);
424
425 for (i = 0; i < cnt; i++) {
426 outb ((data[i] >> 8), dev->fx_dsp_msb);
427 outb ((data[i] & 0xff), dev->fx_dsp_lsb);
428 if (!wavefront_fx_idle (dev)) {
429 break;
430 }
431 }
432
433 if (i != cnt) {
434 snd_printk ("FX memset "
435 "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
436 page, addr, (unsigned long) data, cnt);
437 return -(EIO);
438 }
439 }
440
441 return 0;
442}
443
444int
445snd_wavefront_fx_detect (snd_wavefront_t *dev)
446
447{
448 /* This is a crude check, but its the best one I have for now.
449 Certainly on the Maui and the Tropez, wavefront_fx_idle() will
450 report "never idle", which suggests that this test should
451 work OK.
452 */
453
454 if (inb (dev->fx_status) & 0x80) {
455 snd_printk ("Hmm, probably a Maui or Tropez.\n");
456 return -1;
457 }
458
459 return 0;
460}
461
462int
463snd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file)
464
465{
466 if (!try_module_get(hw->card->module))
467 return -EFAULT;
468 file->private_data = hw;
469 return 0;
470}
471
472int
473snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
474
475{
476 module_put(hw->card->module);
477 return 0;
478}
479
480int
481snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
482 unsigned int cmd, unsigned long arg)
483
484{
485 snd_card_t *card;
486 snd_wavefront_card_t *acard;
487 snd_wavefront_t *dev;
488 wavefront_fx_info r;
489 unsigned short *page_data = NULL;
490 unsigned short *pd;
491 int err = 0;
492
493 snd_assert(sdev->card != NULL, return -ENODEV);
494
495 card = sdev->card;
496
497 snd_assert(card->private_data != NULL, return -ENODEV);
498
499 acard = card->private_data;
500 dev = &acard->wavefront;
501
502 if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
503 return -EFAULT;
504
505 switch (r.request) {
506 case WFFX_MUTE:
507 wavefront_fx_mute (dev, r.data[0]);
508 return -EIO;
509
510 case WFFX_MEMSET:
511 if (r.data[2] <= 0) {
512 snd_printk ("cannot write "
513 "<= 0 bytes to FX\n");
514 return -EIO;
515 } else if (r.data[2] == 1) {
516 pd = (unsigned short *) &r.data[3];
517 } else {
518 if (r.data[2] > 256) {
519 snd_printk ("cannot write "
520 "> 512 bytes to FX\n");
521 return -EIO;
522 }
523 page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
524 if (!page_data)
525 return -ENOMEM;
526 if (copy_from_user (page_data,
527 (unsigned char __user *) r.data[3],
528 r.data[2] * sizeof(short))) {
529 kfree(page_data);
530 return -EFAULT;
531 }
532 pd = page_data;
533 }
534
535 err = wavefront_fx_memset (dev,
536 r.data[0], /* page */
537 r.data[1], /* addr */
538 r.data[2], /* cnt */
539 pd);
540 kfree(page_data);
541 break;
542
543 default:
544 snd_printk ("FX: ioctl %d not yet supported\n",
545 r.request);
546 return -ENOTTY;
547 }
548 return err;
549}
550
551/* YSS225 initialization.
552
553 This code was developed using DOSEMU. The Turtle Beach SETUPSND
554 utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
555 of the port I/O done, using the Yamaha faxback document as a guide
556 to add more logic to the code. Its really pretty weird.
557
558 There was an alternative approach of just dumping the whole I/O
559 sequence as a series of port/value pairs and a simple loop
560 that output it. However, I hope that eventually I'll get more
561 control over what this code does, and so I tried to stick with
562 a somewhat "algorithmic" approach.
563*/
564
565
566int __init
567snd_wavefront_fx_start (snd_wavefront_t *dev)
568
569{
570 unsigned int i, j;
571
572 /* Set all bits for all channels on the MOD unit to zero */
573 /* XXX But why do this twice ? */
574
575 for (j = 0; j < 2; j++) {
576 for (i = 0x10; i <= 0xff; i++) {
577
578 if (!wavefront_fx_idle (dev)) {
579 return (-1);
580 }
581
582 outb (i, dev->fx_mod_addr);
583 outb (0x0, dev->fx_mod_data);
584 }
585 }
586
587 if (!wavefront_fx_idle (dev)) return (-1);
588 outb (0x02, dev->fx_op); /* mute on */
589
590 if (!wavefront_fx_idle (dev)) return (-1);
591 outb (0x07, dev->fx_dsp_page);
592 outb (0x44, dev->fx_dsp_addr);
593 outb (0x00, dev->fx_dsp_msb);
594 outb (0x00, dev->fx_dsp_lsb);
595 if (!wavefront_fx_idle (dev)) return (-1);
596 outb (0x07, dev->fx_dsp_page);
597 outb (0x42, dev->fx_dsp_addr);
598 outb (0x00, dev->fx_dsp_msb);
599 outb (0x00, dev->fx_dsp_lsb);
600 if (!wavefront_fx_idle (dev)) return (-1);
601 outb (0x07, dev->fx_dsp_page);
602 outb (0x43, dev->fx_dsp_addr);
603 outb (0x00, dev->fx_dsp_msb);
604 outb (0x00, dev->fx_dsp_lsb);
605 if (!wavefront_fx_idle (dev)) return (-1);
606 outb (0x07, dev->fx_dsp_page);
607 outb (0x7c, dev->fx_dsp_addr);
608 outb (0x00, dev->fx_dsp_msb);
609 outb (0x00, dev->fx_dsp_lsb);
610 if (!wavefront_fx_idle (dev)) return (-1);
611 outb (0x07, dev->fx_dsp_page);
612 outb (0x7e, dev->fx_dsp_addr);
613 outb (0x00, dev->fx_dsp_msb);
614 outb (0x00, dev->fx_dsp_lsb);
615 if (!wavefront_fx_idle (dev)) return (-1);
616 outb (0x07, dev->fx_dsp_page);
617 outb (0x46, dev->fx_dsp_addr);
618 outb (0x00, dev->fx_dsp_msb);
619 outb (0x00, dev->fx_dsp_lsb);
620 if (!wavefront_fx_idle (dev)) return (-1);
621 outb (0x07, dev->fx_dsp_page);
622 outb (0x49, dev->fx_dsp_addr);
623 outb (0x00, dev->fx_dsp_msb);
624 outb (0x00, dev->fx_dsp_lsb);
625 if (!wavefront_fx_idle (dev)) return (-1);
626 outb (0x07, dev->fx_dsp_page);
627 outb (0x47, dev->fx_dsp_addr);
628 outb (0x00, dev->fx_dsp_msb);
629 outb (0x00, dev->fx_dsp_lsb);
630 if (!wavefront_fx_idle (dev)) return (-1);
631 outb (0x07, dev->fx_dsp_page);
632 outb (0x4a, dev->fx_dsp_addr);
633 outb (0x00, dev->fx_dsp_msb);
634 outb (0x00, dev->fx_dsp_lsb);
635
636 /* either because of stupidity by TB's programmers, or because it
637 actually does something, rezero the MOD page.
638 */
639 for (i = 0x10; i <= 0xff; i++) {
640
641 if (!wavefront_fx_idle (dev)) {
642 return (-1);
643 }
644
645 outb (i, dev->fx_mod_addr);
646 outb (0x0, dev->fx_mod_data);
647 }
648 /* load page zero */
649
650 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
651 outb (0x00, dev->fx_dsp_page);
652 outb (0x00, dev->fx_dsp_addr);
653
654 for (i = 0; i < sizeof (page_zero); i += 2) {
655 outb (page_zero[i], dev->fx_dsp_msb);
656 outb (page_zero[i+1], dev->fx_dsp_lsb);
657 if (!wavefront_fx_idle (dev)) return (-1);
658 }
659
660 /* Now load page one */
661
662 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
663 outb (0x01, dev->fx_dsp_page);
664 outb (0x00, dev->fx_dsp_addr);
665
666 for (i = 0; i < sizeof (page_one); i += 2) {
667 outb (page_one[i], dev->fx_dsp_msb);
668 outb (page_one[i+1], dev->fx_dsp_lsb);
669 if (!wavefront_fx_idle (dev)) return (-1);
670 }
671
672 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
673 outb (0x02, dev->fx_dsp_page);
674 outb (0x00, dev->fx_dsp_addr);
675
676 for (i = 0; i < sizeof (page_two); i++) {
677 outb (page_two[i], dev->fx_dsp_lsb);
678 if (!wavefront_fx_idle (dev)) return (-1);
679 }
680
681 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
682 outb (0x03, dev->fx_dsp_page);
683 outb (0x00, dev->fx_dsp_addr);
684
685 for (i = 0; i < sizeof (page_three); i++) {
686 outb (page_three[i], dev->fx_dsp_lsb);
687 if (!wavefront_fx_idle (dev)) return (-1);
688 }
689
690 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
691 outb (0x04, dev->fx_dsp_page);
692 outb (0x00, dev->fx_dsp_addr);
693
694 for (i = 0; i < sizeof (page_four); i++) {
695 outb (page_four[i], dev->fx_dsp_lsb);
696 if (!wavefront_fx_idle (dev)) return (-1);
697 }
698
699 /* Load memory area (page six) */
700
701 outb (FX_LSB_TRANSFER, dev->fx_lcr);
702 outb (0x06, dev->fx_dsp_page);
703
704 for (i = 0; i < sizeof (page_six); i += 3) {
705 outb (page_six[i], dev->fx_dsp_addr);
706 outb (page_six[i+1], dev->fx_dsp_msb);
707 outb (page_six[i+2], dev->fx_dsp_lsb);
708 if (!wavefront_fx_idle (dev)) return (-1);
709 }
710
711 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
712 outb (0x07, dev->fx_dsp_page);
713 outb (0x00, dev->fx_dsp_addr);
714
715 for (i = 0; i < sizeof (page_seven); i += 2) {
716 outb (page_seven[i], dev->fx_dsp_msb);
717 outb (page_seven[i+1], dev->fx_dsp_lsb);
718 if (!wavefront_fx_idle (dev)) return (-1);
719 }
720
721 /* Now setup the MOD area. We do this algorithmically in order to
722 save a little data space. It could be done in the same fashion
723 as the "pages".
724 */
725
726 for (i = 0x00; i <= 0x0f; i++) {
727 outb (0x01, dev->fx_mod_addr);
728 outb (i, dev->fx_mod_data);
729 if (!wavefront_fx_idle (dev)) return (-1);
730 outb (0x02, dev->fx_mod_addr);
731 outb (0x00, dev->fx_mod_data);
732 if (!wavefront_fx_idle (dev)) return (-1);
733 }
734
735 for (i = 0xb0; i <= 0xbf; i++) {
736 outb (i, dev->fx_mod_addr);
737 outb (0x20, dev->fx_mod_data);
738 if (!wavefront_fx_idle (dev)) return (-1);
739 }
740
741 for (i = 0xf0; i <= 0xff; i++) {
742 outb (i, dev->fx_mod_addr);
743 outb (0x20, dev->fx_mod_data);
744 if (!wavefront_fx_idle (dev)) return (-1);
745 }
746
747 for (i = 0x10; i <= 0x1d; i++) {
748 outb (i, dev->fx_mod_addr);
749 outb (0xff, dev->fx_mod_data);
750 if (!wavefront_fx_idle (dev)) return (-1);
751 }
752
753 outb (0x1e, dev->fx_mod_addr);
754 outb (0x40, dev->fx_mod_data);
755 if (!wavefront_fx_idle (dev)) return (-1);
756
757 for (i = 0x1f; i <= 0x2d; i++) {
758 outb (i, dev->fx_mod_addr);
759 outb (0xff, dev->fx_mod_data);
760 if (!wavefront_fx_idle (dev)) return (-1);
761 }
762
763 outb (0x2e, dev->fx_mod_addr);
764 outb (0x00, dev->fx_mod_data);
765 if (!wavefront_fx_idle (dev)) return (-1);
766
767 for (i = 0x2f; i <= 0x3e; i++) {
768 outb (i, dev->fx_mod_addr);
769 outb (0x00, dev->fx_mod_data);
770 if (!wavefront_fx_idle (dev)) return (-1);
771 }
772
773 outb (0x3f, dev->fx_mod_addr);
774 outb (0x20, dev->fx_mod_data);
775 if (!wavefront_fx_idle (dev)) return (-1);
776
777 for (i = 0x40; i <= 0x4d; i++) {
778 outb (i, dev->fx_mod_addr);
779 outb (0x00, dev->fx_mod_data);
780 if (!wavefront_fx_idle (dev)) return (-1);
781 }
782
783 outb (0x4e, dev->fx_mod_addr);
784 outb (0x0e, dev->fx_mod_data);
785 if (!wavefront_fx_idle (dev)) return (-1);
786 outb (0x4f, dev->fx_mod_addr);
787 outb (0x0e, dev->fx_mod_data);
788 if (!wavefront_fx_idle (dev)) return (-1);
789
790
791 for (i = 0x50; i <= 0x6b; i++) {
792 outb (i, dev->fx_mod_addr);
793 outb (0x00, dev->fx_mod_data);
794 if (!wavefront_fx_idle (dev)) return (-1);
795 }
796
797 outb (0x6c, dev->fx_mod_addr);
798 outb (0x40, dev->fx_mod_data);
799 if (!wavefront_fx_idle (dev)) return (-1);
800
801 outb (0x6d, dev->fx_mod_addr);
802 outb (0x00, dev->fx_mod_data);
803 if (!wavefront_fx_idle (dev)) return (-1);
804
805 outb (0x6e, dev->fx_mod_addr);
806 outb (0x40, dev->fx_mod_data);
807 if (!wavefront_fx_idle (dev)) return (-1);
808
809 outb (0x6f, dev->fx_mod_addr);
810 outb (0x40, dev->fx_mod_data);
811 if (!wavefront_fx_idle (dev)) return (-1);
812
813 for (i = 0x70; i <= 0x7f; i++) {
814 outb (i, dev->fx_mod_addr);
815 outb (0xc0, dev->fx_mod_data);
816 if (!wavefront_fx_idle (dev)) return (-1);
817 }
818
819 for (i = 0x80; i <= 0xaf; i++) {
820 outb (i, dev->fx_mod_addr);
821 outb (0x00, dev->fx_mod_data);
822 if (!wavefront_fx_idle (dev)) return (-1);
823 }
824
825 for (i = 0xc0; i <= 0xdd; i++) {
826 outb (i, dev->fx_mod_addr);
827 outb (0x00, dev->fx_mod_data);
828 if (!wavefront_fx_idle (dev)) return (-1);
829 }
830
831 outb (0xde, dev->fx_mod_addr);
832 outb (0x10, dev->fx_mod_data);
833 if (!wavefront_fx_idle (dev)) return (-1);
834 outb (0xdf, dev->fx_mod_addr);
835 outb (0x10, dev->fx_mod_data);
836 if (!wavefront_fx_idle (dev)) return (-1);
837
838 for (i = 0xe0; i <= 0xef; i++) {
839 outb (i, dev->fx_mod_addr);
840 outb (0x00, dev->fx_mod_data);
841 if (!wavefront_fx_idle (dev)) return (-1);
842 }
843
844 for (i = 0x00; i <= 0x0f; i++) {
845 outb (0x01, dev->fx_mod_addr);
846 outb (i, dev->fx_mod_data);
847 outb (0x02, dev->fx_mod_addr);
848 outb (0x01, dev->fx_mod_data);
849 if (!wavefront_fx_idle (dev)) return (-1);
850 }
851
852 outb (0x02, dev->fx_op); /* mute on */
853
854 /* Now set the coefficients and so forth for the programs above */
855
856 for (i = 0; i < sizeof (coefficients); i += 4) {
857 outb (coefficients[i], dev->fx_dsp_page);
858 outb (coefficients[i+1], dev->fx_dsp_addr);
859 outb (coefficients[i+2], dev->fx_dsp_msb);
860 outb (coefficients[i+3], dev->fx_dsp_lsb);
861 if (!wavefront_fx_idle (dev)) return (-1);
862 }
863
864 /* Some settings (?) that are too small to bundle into loops */
865
866 if (!wavefront_fx_idle (dev)) return (-1);
867 outb (0x1e, dev->fx_mod_addr);
868 outb (0x14, dev->fx_mod_data);
869 if (!wavefront_fx_idle (dev)) return (-1);
870 outb (0xde, dev->fx_mod_addr);
871 outb (0x20, dev->fx_mod_data);
872 if (!wavefront_fx_idle (dev)) return (-1);
873 outb (0xdf, dev->fx_mod_addr);
874 outb (0x20, dev->fx_mod_data);
875
876 /* some more coefficients */
877
878 if (!wavefront_fx_idle (dev)) return (-1);
879 outb (0x06, dev->fx_dsp_page);
880 outb (0x78, dev->fx_dsp_addr);
881 outb (0x00, dev->fx_dsp_msb);
882 outb (0x40, dev->fx_dsp_lsb);
883 if (!wavefront_fx_idle (dev)) return (-1);
884 outb (0x07, dev->fx_dsp_page);
885 outb (0x03, dev->fx_dsp_addr);
886 outb (0x0f, dev->fx_dsp_msb);
887 outb (0xff, dev->fx_dsp_lsb);
888 if (!wavefront_fx_idle (dev)) return (-1);
889 outb (0x07, dev->fx_dsp_page);
890 outb (0x0b, dev->fx_dsp_addr);
891 outb (0x0f, dev->fx_dsp_msb);
892 outb (0xff, dev->fx_dsp_lsb);
893 if (!wavefront_fx_idle (dev)) return (-1);
894 outb (0x07, dev->fx_dsp_page);
895 outb (0x02, dev->fx_dsp_addr);
896 outb (0x00, dev->fx_dsp_msb);
897 outb (0x00, dev->fx_dsp_lsb);
898 if (!wavefront_fx_idle (dev)) return (-1);
899 outb (0x07, dev->fx_dsp_page);
900 outb (0x0a, dev->fx_dsp_addr);
901 outb (0x00, dev->fx_dsp_msb);
902 outb (0x00, dev->fx_dsp_lsb);
903 if (!wavefront_fx_idle (dev)) return (-1);
904 outb (0x07, dev->fx_dsp_page);
905 outb (0x46, dev->fx_dsp_addr);
906 outb (0x00, dev->fx_dsp_msb);
907 outb (0x00, dev->fx_dsp_lsb);
908 if (!wavefront_fx_idle (dev)) return (-1);
909 outb (0x07, dev->fx_dsp_page);
910 outb (0x49, dev->fx_dsp_addr);
911 outb (0x00, dev->fx_dsp_msb);
912 outb (0x00, dev->fx_dsp_lsb);
913
914 /* Now, for some strange reason, lets reload every page
915 and all the coefficients over again. I have *NO* idea
916 why this is done. I do know that no sound is produced
917 is this phase is omitted.
918 */
919
920 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
921 outb (0x00, dev->fx_dsp_page);
922 outb (0x10, dev->fx_dsp_addr);
923
924 for (i = 0; i < sizeof (page_zero_v2); i += 2) {
925 outb (page_zero_v2[i], dev->fx_dsp_msb);
926 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
927 if (!wavefront_fx_idle (dev)) return (-1);
928 }
929
930 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
931 outb (0x01, dev->fx_dsp_page);
932 outb (0x10, dev->fx_dsp_addr);
933
934 for (i = 0; i < sizeof (page_one_v2); i += 2) {
935 outb (page_one_v2[i], dev->fx_dsp_msb);
936 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
937 if (!wavefront_fx_idle (dev)) return (-1);
938 }
939
940 if (!wavefront_fx_idle (dev)) return (-1);
941 if (!wavefront_fx_idle (dev)) return (-1);
942
943 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
944 outb (0x02, dev->fx_dsp_page);
945 outb (0x10, dev->fx_dsp_addr);
946
947 for (i = 0; i < sizeof (page_two_v2); i++) {
948 outb (page_two_v2[i], dev->fx_dsp_lsb);
949 if (!wavefront_fx_idle (dev)) return (-1);
950 }
951 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
952 outb (0x03, dev->fx_dsp_page);
953 outb (0x10, dev->fx_dsp_addr);
954
955 for (i = 0; i < sizeof (page_three_v2); i++) {
956 outb (page_three_v2[i], dev->fx_dsp_lsb);
957 if (!wavefront_fx_idle (dev)) return (-1);
958 }
959
960 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
961 outb (0x04, dev->fx_dsp_page);
962 outb (0x10, dev->fx_dsp_addr);
963
964 for (i = 0; i < sizeof (page_four_v2); i++) {
965 outb (page_four_v2[i], dev->fx_dsp_lsb);
966 if (!wavefront_fx_idle (dev)) return (-1);
967 }
968
969 outb (FX_LSB_TRANSFER, dev->fx_lcr);
970 outb (0x06, dev->fx_dsp_page);
971
972 /* Page six v.2 is algorithmic */
973
974 for (i = 0x10; i <= 0x3e; i += 2) {
975 outb (i, dev->fx_dsp_addr);
976 outb (0x00, dev->fx_dsp_msb);
977 outb (0x00, dev->fx_dsp_lsb);
978 if (!wavefront_fx_idle (dev)) return (-1);
979 }
980
981 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
982 outb (0x07, dev->fx_dsp_page);
983 outb (0x10, dev->fx_dsp_addr);
984
985 for (i = 0; i < sizeof (page_seven_v2); i += 2) {
986 outb (page_seven_v2[i], dev->fx_dsp_msb);
987 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
988 if (!wavefront_fx_idle (dev)) return (-1);
989 }
990
991 for (i = 0x00; i < sizeof(mod_v2); i += 2) {
992 outb (mod_v2[i], dev->fx_mod_addr);
993 outb (mod_v2[i+1], dev->fx_mod_data);
994 if (!wavefront_fx_idle (dev)) return (-1);
995 }
996
997 for (i = 0; i < sizeof (coefficients2); i += 4) {
998 outb (coefficients2[i], dev->fx_dsp_page);
999 outb (coefficients2[i+1], dev->fx_dsp_addr);
1000 outb (coefficients2[i+2], dev->fx_dsp_msb);
1001 outb (coefficients2[i+3], dev->fx_dsp_lsb);
1002 if (!wavefront_fx_idle (dev)) return (-1);
1003 }
1004
1005 for (i = 0; i < sizeof (coefficients3); i += 2) {
1006 int x;
1007
1008 outb (0x07, dev->fx_dsp_page);
1009 x = (i % 4) ? 0x4e : 0x4c;
1010 outb (x, dev->fx_dsp_addr);
1011 outb (coefficients3[i], dev->fx_dsp_msb);
1012 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1013 }
1014
1015 outb (0x00, dev->fx_op); /* mute off */
1016 if (!wavefront_fx_idle (dev)) return (-1);
1017
1018 return (0);
1019}
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
new file mode 100644
index 000000000000..6f51d64fb565
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -0,0 +1,570 @@
1/*
2 * Copyright (C) by Paul Barton-Davis 1998-1999
3 *
4 * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
5 * Version 2 (June 1991). See the "COPYING" file distributed with this
6 * software for more info.
7 */
8
9/* The low level driver for the WaveFront ICS2115 MIDI interface(s)
10 *
11 * Note that there is also an MPU-401 emulation (actually, a UART-401
12 * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
13 * has nothing to do with that interface at all.
14 *
15 * The interface is essentially just a UART-401, but is has the
16 * interesting property of supporting what Turtle Beach called
17 * "Virtual MIDI" mode. In this mode, there are effectively *two*
18 * MIDI buses accessible via the interface, one that is routed
19 * solely to/from the external WaveFront synthesizer and the other
20 * corresponding to the pin/socket connector used to link external
21 * MIDI devices to the board.
22 *
23 * This driver fully supports this mode, allowing two distinct MIDI
24 * busses to be used completely independently, giving 32 channels of
25 * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
26 * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
27 * where `n' is the card number. Note that the device numbers may be
28 * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
29 * is enabled.
30 *
31 * Switching between the two is accomplished externally by the driver
32 * using the two otherwise unused MIDI bytes. See the code for more details.
33 *
34 * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
35 *
36 * The main reason to turn off Virtual MIDI mode is when you want to
37 * tightly couple the WaveFront synth with an external MIDI
38 * device. You won't be able to distinguish the source of any MIDI
39 * data except via SysEx ID, but thats probably OK, since for the most
40 * part, the WaveFront won't be sending any MIDI data at all.
41 *
42 * The main reason to turn on Virtual MIDI Mode is to provide two
43 * completely independent 16-channel MIDI buses, one to the
44 * WaveFront and one to any external MIDI devices. Given the 32
45 * voice nature of the WaveFront, its pretty easy to find a use
46 * for all 16 channels driving just that synth.
47 *
48 */
49
50#include <sound/driver.h>
51#include <asm/io.h>
52#include <linux/init.h>
53#include <linux/time.h>
54#include <linux/wait.h>
55#include <sound/core.h>
56#include <sound/snd_wavefront.h>
57
58static inline int
59wf_mpu_status (snd_wavefront_midi_t *midi)
60
61{
62 return inb (midi->mpu_status_port);
63}
64
65static inline int
66input_avail (snd_wavefront_midi_t *midi)
67
68{
69 return !(wf_mpu_status(midi) & INPUT_AVAIL);
70}
71
72static inline int
73output_ready (snd_wavefront_midi_t *midi)
74
75{
76 return !(wf_mpu_status(midi) & OUTPUT_READY);
77}
78
79static inline int
80read_data (snd_wavefront_midi_t *midi)
81
82{
83 return inb (midi->mpu_data_port);
84}
85
86static inline void
87write_data (snd_wavefront_midi_t *midi, unsigned char byte)
88
89{
90 outb (byte, midi->mpu_data_port);
91}
92
93static snd_wavefront_midi_t *
94get_wavefront_midi (snd_rawmidi_substream_t *substream)
95
96{
97 snd_card_t *card;
98 snd_wavefront_card_t *acard;
99
100 if (substream == NULL || substream->rmidi == NULL)
101 return NULL;
102
103 card = substream->rmidi->card;
104
105 if (card == NULL)
106 return NULL;
107
108 if (card->private_data == NULL)
109 return NULL;
110
111 acard = card->private_data;
112
113 return &acard->wavefront.midi;
114}
115
116static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
117{
118 snd_wavefront_midi_t *midi = &card->wavefront.midi;
119 snd_wavefront_mpu_id mpu;
120 unsigned long flags;
121 unsigned char midi_byte;
122 int max = 256, mask = 1;
123 int timeout;
124
125 /* Its not OK to try to change the status of "virtuality" of
126 the MIDI interface while we're outputting stuff. See
127 snd_wavefront_midi_{enable,disable}_virtual () for the
128 other half of this.
129
130 The first loop attempts to flush any data from the
131 current output device, and then the second
132 emits the switch byte (if necessary), and starts
133 outputting data for the output device currently in use.
134 */
135
136 if (midi->substream_output[midi->output_mpu] == NULL) {
137 goto __second;
138 }
139
140 while (max > 0) {
141
142 /* XXX fix me - no hard timing loops allowed! */
143
144 for (timeout = 30000; timeout > 0; timeout--) {
145 if (output_ready (midi))
146 break;
147 }
148
149 spin_lock_irqsave (&midi->virtual, flags);
150 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
151 spin_unlock_irqrestore (&midi->virtual, flags);
152 goto __second;
153 }
154 if (output_ready (midi)) {
155 if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
156 if (!midi->isvirtual ||
157 (midi_byte != WF_INTERNAL_SWITCH &&
158 midi_byte != WF_EXTERNAL_SWITCH))
159 write_data(midi, midi_byte);
160 max--;
161 } else {
162 if (midi->istimer) {
163 if (--midi->istimer <= 0)
164 del_timer(&midi->timer);
165 }
166 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
167 spin_unlock_irqrestore (&midi->virtual, flags);
168 goto __second;
169 }
170 } else {
171 spin_unlock_irqrestore (&midi->virtual, flags);
172 return;
173 }
174 spin_unlock_irqrestore (&midi->virtual, flags);
175 }
176
177 __second:
178
179 if (midi->substream_output[!midi->output_mpu] == NULL) {
180 return;
181 }
182
183 while (max > 0) {
184
185 /* XXX fix me - no hard timing loops allowed! */
186
187 for (timeout = 30000; timeout > 0; timeout--) {
188 if (output_ready (midi))
189 break;
190 }
191
192 spin_lock_irqsave (&midi->virtual, flags);
193 if (!midi->isvirtual)
194 mask = 0;
195 mpu = midi->output_mpu ^ mask;
196 mask = 0; /* don't invert the value from now */
197 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
198 spin_unlock_irqrestore (&midi->virtual, flags);
199 return;
200 }
201 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
202 goto __timer;
203 if (output_ready (midi)) {
204 if (mpu != midi->output_mpu) {
205 write_data(midi, mpu == internal_mpu ?
206 WF_INTERNAL_SWITCH :
207 WF_EXTERNAL_SWITCH);
208 midi->output_mpu = mpu;
209 } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
210 if (!midi->isvirtual ||
211 (midi_byte != WF_INTERNAL_SWITCH &&
212 midi_byte != WF_EXTERNAL_SWITCH))
213 write_data(midi, midi_byte);
214 max--;
215 } else {
216 __timer:
217 if (midi->istimer) {
218 if (--midi->istimer <= 0)
219 del_timer(&midi->timer);
220 }
221 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
222 spin_unlock_irqrestore (&midi->virtual, flags);
223 return;
224 }
225 } else {
226 spin_unlock_irqrestore (&midi->virtual, flags);
227 return;
228 }
229 spin_unlock_irqrestore (&midi->virtual, flags);
230 }
231}
232
233static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream)
234{
235 unsigned long flags;
236 snd_wavefront_midi_t *midi;
237 snd_wavefront_mpu_id mpu;
238
239 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
240 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
241
242 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
243
244 if ((midi = get_wavefront_midi (substream)) == NULL)
245 return -EIO;
246
247 spin_lock_irqsave (&midi->open, flags);
248 midi->mode[mpu] |= MPU401_MODE_INPUT;
249 midi->substream_input[mpu] = substream;
250 spin_unlock_irqrestore (&midi->open, flags);
251
252 return 0;
253}
254
255static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream)
256{
257 unsigned long flags;
258 snd_wavefront_midi_t *midi;
259 snd_wavefront_mpu_id mpu;
260
261 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
262 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
263
264 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
265
266 if ((midi = get_wavefront_midi (substream)) == NULL)
267 return -EIO;
268
269 spin_lock_irqsave (&midi->open, flags);
270 midi->mode[mpu] |= MPU401_MODE_OUTPUT;
271 midi->substream_output[mpu] = substream;
272 spin_unlock_irqrestore (&midi->open, flags);
273
274 return 0;
275}
276
277static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream)
278{
279 unsigned long flags;
280 snd_wavefront_midi_t *midi;
281 snd_wavefront_mpu_id mpu;
282
283 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
284 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
285
286 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
287
288 if ((midi = get_wavefront_midi (substream)) == NULL)
289 return -EIO;
290
291 spin_lock_irqsave (&midi->open, flags);
292 midi->mode[mpu] &= ~MPU401_MODE_INPUT;
293 spin_unlock_irqrestore (&midi->open, flags);
294
295 return 0;
296}
297
298static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream)
299{
300 unsigned long flags;
301 snd_wavefront_midi_t *midi;
302 snd_wavefront_mpu_id mpu;
303
304 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
305 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
306
307 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
308
309 if ((midi = get_wavefront_midi (substream)) == NULL)
310 return -EIO;
311
312 spin_lock_irqsave (&midi->open, flags);
313 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
314 spin_unlock_irqrestore (&midi->open, flags);
315 return 0;
316}
317
318static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
319{
320 unsigned long flags;
321 snd_wavefront_midi_t *midi;
322 snd_wavefront_mpu_id mpu;
323
324 if (substream == NULL || substream->rmidi == NULL)
325 return;
326
327 if (substream->rmidi->private_data == NULL)
328 return;
329
330 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
331
332 if ((midi = get_wavefront_midi (substream)) == NULL) {
333 return;
334 }
335
336 spin_lock_irqsave (&midi->virtual, flags);
337 if (up) {
338 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
339 } else {
340 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
341 }
342 spin_unlock_irqrestore (&midi->virtual, flags);
343}
344
345static void snd_wavefront_midi_output_timer(unsigned long data)
346{
347 snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;
348 snd_wavefront_midi_t *midi = &card->wavefront.midi;
349 unsigned long flags;
350
351 spin_lock_irqsave (&midi->virtual, flags);
352 midi->timer.expires = 1 + jiffies;
353 add_timer(&midi->timer);
354 spin_unlock_irqrestore (&midi->virtual, flags);
355 snd_wavefront_midi_output_write(card);
356}
357
358static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
359{
360 unsigned long flags;
361 snd_wavefront_midi_t *midi;
362 snd_wavefront_mpu_id mpu;
363
364 if (substream == NULL || substream->rmidi == NULL)
365 return;
366
367 if (substream->rmidi->private_data == NULL)
368 return;
369
370 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
371
372 if ((midi = get_wavefront_midi (substream)) == NULL) {
373 return;
374 }
375
376 spin_lock_irqsave (&midi->virtual, flags);
377 if (up) {
378 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
379 if (!midi->istimer) {
380 init_timer(&midi->timer);
381 midi->timer.function = snd_wavefront_midi_output_timer;
382 midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
383 midi->timer.expires = 1 + jiffies;
384 add_timer(&midi->timer);
385 }
386 midi->istimer++;
387 midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
388 }
389 } else {
390 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
391 }
392 spin_unlock_irqrestore (&midi->virtual, flags);
393
394 if (up)
395 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
396}
397
398void
399snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
400
401{
402 unsigned long flags;
403 snd_wavefront_midi_t *midi;
404 static snd_rawmidi_substream_t *substream = NULL;
405 static int mpu = external_mpu;
406 int max = 128;
407 unsigned char byte;
408
409 midi = &card->wavefront.midi;
410
411 if (!input_avail (midi)) { /* not for us */
412 snd_wavefront_midi_output_write(card);
413 return;
414 }
415
416 spin_lock_irqsave (&midi->virtual, flags);
417 while (--max) {
418
419 if (input_avail (midi)) {
420 byte = read_data (midi);
421
422 if (midi->isvirtual) {
423 if (byte == WF_EXTERNAL_SWITCH) {
424 substream = midi->substream_input[external_mpu];
425 mpu = external_mpu;
426 } else if (byte == WF_INTERNAL_SWITCH) {
427 substream = midi->substream_output[internal_mpu];
428 mpu = internal_mpu;
429 } /* else just leave it as it is */
430 } else {
431 substream = midi->substream_input[internal_mpu];
432 mpu = internal_mpu;
433 }
434
435 if (substream == NULL) {
436 continue;
437 }
438
439 if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
440 snd_rawmidi_receive(substream, &byte, 1);
441 }
442 } else {
443 break;
444 }
445 }
446 spin_unlock_irqrestore (&midi->virtual, flags);
447
448 snd_wavefront_midi_output_write(card);
449}
450
451void
452snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
453
454{
455 unsigned long flags;
456
457 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
458 card->wavefront.midi.isvirtual = 1;
459 card->wavefront.midi.output_mpu = internal_mpu;
460 card->wavefront.midi.input_mpu = internal_mpu;
461 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
462}
463
464void
465snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
466
467{
468 unsigned long flags;
469
470 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
471 // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
472 // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
473 card->wavefront.midi.isvirtual = 0;
474 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
475}
476
477int __init
478snd_wavefront_midi_start (snd_wavefront_card_t *card)
479
480{
481 int ok, i;
482 unsigned char rbuf[4], wbuf[4];
483 snd_wavefront_t *dev;
484 snd_wavefront_midi_t *midi;
485
486 dev = &card->wavefront;
487 midi = &dev->midi;
488
489 /* The ICS2115 MPU-401 interface doesn't do anything
490 until its set into UART mode.
491 */
492
493 /* XXX fix me - no hard timing loops allowed! */
494
495 for (i = 0; i < 30000 && !output_ready (midi); i++);
496
497 if (!output_ready (midi)) {
498 snd_printk ("MIDI interface not ready for command\n");
499 return -1;
500 }
501
502 /* Any interrupts received from now on
503 are owned by the MIDI side of things.
504 */
505
506 dev->interrupts_are_midi = 1;
507
508 outb (UART_MODE_ON, midi->mpu_command_port);
509
510 for (ok = 0, i = 50000; i > 0 && !ok; i--) {
511 if (input_avail (midi)) {
512 if (read_data (midi) == MPU_ACK) {
513 ok = 1;
514 break;
515 }
516 }
517 }
518
519 if (!ok) {
520 snd_printk ("cannot set UART mode for MIDI interface");
521 dev->interrupts_are_midi = 0;
522 return -1;
523 }
524
525 /* Route external MIDI to WaveFront synth (by default) */
526
527 if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
528 snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
529 /* XXX error ? */
530 }
531
532 /* Turn on Virtual MIDI, but first *always* turn it off,
533 since otherwise consectutive reloads of the driver will
534 never cause the hardware to generate the initial "internal" or
535 "external" source bytes in the MIDI data stream. This
536 is pretty important, since the internal hardware generally will
537 be used to generate none or very little MIDI output, and
538 thus the only source of MIDI data is actually external. Without
539 the switch bytes, the driver will think it all comes from
540 the internal interface. Duh.
541 */
542
543 if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
544 snd_printk ("virtual MIDI mode not disabled\n");
545 return 0; /* We're OK, but missing the external MIDI dev */
546 }
547
548 snd_wavefront_midi_enable_virtual (card);
549
550 if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
551 snd_printk ("cannot enable virtual MIDI mode.\n");
552 snd_wavefront_midi_disable_virtual (card);
553 }
554 return 0;
555}
556
557snd_rawmidi_ops_t snd_wavefront_midi_output =
558{
559 .open = snd_wavefront_midi_output_open,
560 .close = snd_wavefront_midi_output_close,
561 .trigger = snd_wavefront_midi_output_trigger,
562};
563
564snd_rawmidi_ops_t snd_wavefront_midi_input =
565{
566 .open = snd_wavefront_midi_input_open,
567 .close = snd_wavefront_midi_input_close,
568 .trigger = snd_wavefront_midi_input_trigger,
569};
570
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
new file mode 100644
index 000000000000..0c3c951009d8
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -0,0 +1,2243 @@
1/* Copyright (C) by Paul Barton-Davis 1998-1999
2 *
3 * Some portions of this file are taken from work that is
4 * copyright (C) by Hannu Savolainen 1993-1996
5 *
6 * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
7 * Version 2 (June 1991). See the "COPYING" file distributed with this software
8 * for more info.
9 */
10
11/*
12 * An ALSA lowlevel driver for Turtle Beach ICS2115 wavetable synth
13 * (Maui, Tropez, Tropez Plus)
14 *
15 * This driver supports the onboard wavetable synthesizer (an ICS2115),
16 * including patch, sample and program loading and unloading, conversion
17 * of GUS patches during loading, and full user-level access to all
18 * WaveFront commands. It tries to provide semi-intelligent patch and
19 * sample management as well.
20 *
21 */
22
23#include <sound/driver.h>
24#include <asm/io.h>
25#include <linux/interrupt.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/time.h>
29#include <linux/wait.h>
30#include <linux/moduleparam.h>
31#include <sound/core.h>
32#include <sound/snd_wavefront.h>
33#include <sound/initval.h>
34
35static int wf_raw = 0; /* we normally check for "raw state" to firmware
36 loading. if non-zero, then during driver loading, the
37 state of the board is ignored, and we reset the
38 board and load the firmware anyway.
39 */
40
41static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
42 whatever state it is when the driver is loaded.
43 The default is to download the microprogram and
44 associated coefficients to set it up for "default"
45 operation, whatever that means.
46 */
47
48static int debug_default = 0; /* you can set this to control debugging
49 during driver loading. it takes any combination
50 of the WF_DEBUG_* flags defined in
51 wavefront.h
52 */
53
54/* XXX this needs to be made firmware and hardware version dependent */
55
56static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
57 version of the WaveFront OS
58 */
59
60static int wait_usecs = 150; /* This magic number seems to give pretty optimal
61 throughput based on my limited experimentation.
62 If you want to play around with it and find a better
63 value, be my guest. Remember, the idea is to
64 get a number that causes us to just busy wait
65 for as many WaveFront commands as possible, without
66 coming up with a number so large that we hog the
67 whole CPU.
68
69 Specifically, with this number, out of about 134,000
70 status waits, only about 250 result in a sleep.
71 */
72
73static int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */
74static int sleep_tries = 50; /* number of times we'll try to sleep */
75
76static int reset_time = 2; /* hundreths of a second we wait after a HW
77 reset for the expected interrupt.
78 */
79
80static int ramcheck_time = 20; /* time in seconds to wait while ROM code
81 checks on-board RAM.
82 */
83
84static int osrun_time = 10; /* time in seconds we wait for the OS to
85 start running.
86 */
87module_param(wf_raw, int, 0444);
88MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS");
89module_param(fx_raw, int, 0444);
90MODULE_PARM_DESC(fx_raw, "if non-zero, assume that the FX process needs help");
91module_param(debug_default, int, 0444);
92MODULE_PARM_DESC(debug_default, "debug parameters for card initialization");
93module_param(wait_usecs, int, 0444);
94MODULE_PARM_DESC(wait_usecs, "how long to wait without sleeping, usecs");
95module_param(sleep_interval, int, 0444);
96MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply");
97module_param(sleep_tries, int, 0444);
98MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait");
99module_param(ospath, charp, 0444);
100MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware");
101module_param(reset_time, int, 0444);
102MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect");
103module_param(ramcheck_time, int, 0444);
104MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test");
105module_param(osrun_time, int, 0444);
106MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
107
108/* if WF_DEBUG not defined, no run-time debugging messages will
109 be available via the debug flag setting. Given the current
110 beta state of the driver, this will remain set until a future
111 version.
112*/
113
114#define WF_DEBUG 1
115
116#ifdef WF_DEBUG
117
118#if defined(NEW_MACRO_VARARGS) || __GNUC__ >= 3
119#define DPRINT(cond, ...) \
120 if ((dev->debug & (cond)) == (cond)) { \
121 snd_printk (__VA_ARGS__); \
122 }
123#else
124#define DPRINT(cond, args...) \
125 if ((dev->debug & (cond)) == (cond)) { \
126 snd_printk (args); \
127 }
128#endif
129#else
130#define DPRINT(cond, args...)
131#endif /* WF_DEBUG */
132
133#define LOGNAME "WaveFront: "
134
135/* bitmasks for WaveFront status port value */
136
137#define STAT_RINTR_ENABLED 0x01
138#define STAT_CAN_READ 0x02
139#define STAT_INTR_READ 0x04
140#define STAT_WINTR_ENABLED 0x10
141#define STAT_CAN_WRITE 0x20
142#define STAT_INTR_WRITE 0x40
143
144static int wavefront_delete_sample (snd_wavefront_t *, int sampnum);
145static int wavefront_find_free_sample (snd_wavefront_t *);
146
147typedef struct {
148 int cmd;
149 char *action;
150 unsigned int read_cnt;
151 unsigned int write_cnt;
152 int need_ack;
153} wavefront_command;
154
155static struct {
156 int errno;
157 const char *errstr;
158} wavefront_errors[] = {
159 { 0x01, "Bad sample number" },
160 { 0x02, "Out of sample memory" },
161 { 0x03, "Bad patch number" },
162 { 0x04, "Error in number of voices" },
163 { 0x06, "Sample load already in progress" },
164 { 0x0B, "No sample load request pending" },
165 { 0x0E, "Bad MIDI channel number" },
166 { 0x10, "Download Record Error" },
167 { 0x80, "Success" },
168 { 0x0 }
169};
170
171#define NEEDS_ACK 1
172
173static wavefront_command wavefront_commands[] = {
174 { WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK },
175 { WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0},
176 { WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK },
177 { WFC_GET_NVOICES, "get number of voices", 1, 0, 0 },
178 { WFC_SET_TUNING, "set synthesizer tuning", 0, 2, NEEDS_ACK },
179 { WFC_GET_TUNING, "get synthesizer tuning", 2, 0, 0 },
180 { WFC_DISABLE_CHANNEL, "disable synth channel", 0, 1, NEEDS_ACK },
181 { WFC_ENABLE_CHANNEL, "enable synth channel", 0, 1, NEEDS_ACK },
182 { WFC_GET_CHANNEL_STATUS, "get synth channel status", 3, 0, 0 },
183 { WFC_MISYNTH_OFF, "disable midi-in to synth", 0, 0, NEEDS_ACK },
184 { WFC_MISYNTH_ON, "enable midi-in to synth", 0, 0, NEEDS_ACK },
185 { WFC_VMIDI_ON, "enable virtual midi mode", 0, 0, NEEDS_ACK },
186 { WFC_VMIDI_OFF, "disable virtual midi mode", 0, 0, NEEDS_ACK },
187 { WFC_MIDI_STATUS, "report midi status", 1, 0, 0 },
188 { WFC_FIRMWARE_VERSION, "report firmware version", 2, 0, 0 },
189 { WFC_HARDWARE_VERSION, "report hardware version", 2, 0, 0 },
190 { WFC_GET_NSAMPLES, "report number of samples", 2, 0, 0 },
191 { WFC_INSTOUT_LEVELS, "report instantaneous output levels", 7, 0, 0 },
192 { WFC_PEAKOUT_LEVELS, "report peak output levels", 7, 0, 0 },
193 { WFC_DOWNLOAD_SAMPLE, "download sample",
194 0, WF_SAMPLE_BYTES, NEEDS_ACK },
195 { WFC_DOWNLOAD_BLOCK, "download block", 0, 0, NEEDS_ACK},
196 { WFC_DOWNLOAD_SAMPLE_HEADER, "download sample header",
197 0, WF_SAMPLE_HDR_BYTES, NEEDS_ACK },
198 { WFC_UPLOAD_SAMPLE_HEADER, "upload sample header", 13, 2, 0 },
199
200 /* This command requires a variable number of bytes to be written.
201 There is a hack in snd_wavefront_cmd() to support this. The actual
202 count is passed in as the read buffer ptr, cast appropriately.
203 Ugh.
204 */
205
206 { WFC_DOWNLOAD_MULTISAMPLE, "download multisample", 0, 0, NEEDS_ACK },
207
208 /* This one is a hack as well. We just read the first byte of the
209 response, don't fetch an ACK, and leave the rest to the
210 calling function. Ugly, ugly, ugly.
211 */
212
213 { WFC_UPLOAD_MULTISAMPLE, "upload multisample", 2, 1, 0 },
214 { WFC_DOWNLOAD_SAMPLE_ALIAS, "download sample alias",
215 0, WF_ALIAS_BYTES, NEEDS_ACK },
216 { WFC_UPLOAD_SAMPLE_ALIAS, "upload sample alias", WF_ALIAS_BYTES, 2, 0},
217 { WFC_DELETE_SAMPLE, "delete sample", 0, 2, NEEDS_ACK },
218 { WFC_IDENTIFY_SAMPLE_TYPE, "identify sample type", 5, 2, 0 },
219 { WFC_UPLOAD_SAMPLE_PARAMS, "upload sample parameters" },
220 { WFC_REPORT_FREE_MEMORY, "report free memory", 4, 0, 0 },
221 { WFC_DOWNLOAD_PATCH, "download patch", 0, 134, NEEDS_ACK },
222 { WFC_UPLOAD_PATCH, "upload patch", 132, 2, 0 },
223 { WFC_DOWNLOAD_PROGRAM, "download program", 0, 33, NEEDS_ACK },
224 { WFC_UPLOAD_PROGRAM, "upload program", 32, 1, 0 },
225 { WFC_DOWNLOAD_EDRUM_PROGRAM, "download enhanced drum program", 0, 9,
226 NEEDS_ACK},
227 { WFC_UPLOAD_EDRUM_PROGRAM, "upload enhanced drum program", 8, 1, 0},
228 { WFC_SET_EDRUM_CHANNEL, "set enhanced drum program channel",
229 0, 1, NEEDS_ACK },
230 { WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK },
231 { WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers",
232 32, 0, 0 },
233 { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK },
234 { 0x00 }
235};
236
237static const char *
238wavefront_errorstr (int errnum)
239
240{
241 int i;
242
243 for (i = 0; wavefront_errors[i].errstr; i++) {
244 if (wavefront_errors[i].errno == errnum) {
245 return wavefront_errors[i].errstr;
246 }
247 }
248
249 return "Unknown WaveFront error";
250}
251
252static wavefront_command *
253wavefront_get_command (int cmd)
254
255{
256 int i;
257
258 for (i = 0; wavefront_commands[i].cmd != 0; i++) {
259 if (cmd == wavefront_commands[i].cmd) {
260 return &wavefront_commands[i];
261 }
262 }
263
264 return (wavefront_command *) 0;
265}
266
267static inline int
268wavefront_status (snd_wavefront_t *dev)
269
270{
271 return inb (dev->status_port);
272}
273
274static int
275wavefront_sleep (int limit)
276
277{
278 set_current_state(TASK_INTERRUPTIBLE);
279 schedule_timeout(limit);
280
281 return signal_pending(current);
282}
283
284static int
285wavefront_wait (snd_wavefront_t *dev, int mask)
286
287{
288 int i;
289
290 /* Spin for a short period of time, because >99% of all
291 requests to the WaveFront can be serviced inline like this.
292 */
293
294 for (i = 0; i < wait_usecs; i += 5) {
295 if (wavefront_status (dev) & mask) {
296 return 1;
297 }
298 udelay(5);
299 }
300
301 for (i = 0; i < sleep_tries; i++) {
302
303 if (wavefront_status (dev) & mask) {
304 return 1;
305 }
306
307 if (wavefront_sleep (HZ/sleep_interval)) {
308 return (0);
309 }
310 }
311
312 return (0);
313}
314
315static int
316wavefront_read (snd_wavefront_t *dev)
317
318{
319 if (wavefront_wait (dev, STAT_CAN_READ))
320 return inb (dev->data_port);
321
322 DPRINT (WF_DEBUG_DATA, "read timeout.\n");
323
324 return -1;
325}
326
327static int
328wavefront_write (snd_wavefront_t *dev, unsigned char data)
329
330{
331 if (wavefront_wait (dev, STAT_CAN_WRITE)) {
332 outb (data, dev->data_port);
333 return 0;
334 }
335
336 DPRINT (WF_DEBUG_DATA, "write timeout.\n");
337
338 return -1;
339}
340
341int
342snd_wavefront_cmd (snd_wavefront_t *dev,
343 int cmd, unsigned char *rbuf, unsigned char *wbuf)
344
345{
346 int ack;
347 unsigned int i;
348 int c;
349 wavefront_command *wfcmd;
350
351 if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
352 snd_printk ("command 0x%x not supported.\n",
353 cmd);
354 return 1;
355 }
356
357 /* Hack to handle the one variable-size write command. See
358 wavefront_send_multisample() for the other half of this
359 gross and ugly strategy.
360 */
361
362 if (cmd == WFC_DOWNLOAD_MULTISAMPLE) {
363 wfcmd->write_cnt = (unsigned long) rbuf;
364 rbuf = NULL;
365 }
366
367 DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
368 cmd, wfcmd->action, wfcmd->read_cnt,
369 wfcmd->write_cnt, wfcmd->need_ack);
370
371 if (wavefront_write (dev, cmd)) {
372 DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request "
373 "0x%x [%s].\n",
374 cmd, wfcmd->action);
375 return 1;
376 }
377
378 if (wfcmd->write_cnt > 0) {
379 DPRINT (WF_DEBUG_DATA, "writing %d bytes "
380 "for 0x%x\n",
381 wfcmd->write_cnt, cmd);
382
383 for (i = 0; i < wfcmd->write_cnt; i++) {
384 if (wavefront_write (dev, wbuf[i])) {
385 DPRINT (WF_DEBUG_IO, "bad write for byte "
386 "%d of 0x%x [%s].\n",
387 i, cmd, wfcmd->action);
388 return 1;
389 }
390
391 DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n",
392 i, wbuf[i]);
393 }
394 }
395
396 if (wfcmd->read_cnt > 0) {
397 DPRINT (WF_DEBUG_DATA, "reading %d ints "
398 "for 0x%x\n",
399 wfcmd->read_cnt, cmd);
400
401 for (i = 0; i < wfcmd->read_cnt; i++) {
402
403 if ((c = wavefront_read (dev)) == -1) {
404 DPRINT (WF_DEBUG_IO, "bad read for byte "
405 "%d of 0x%x [%s].\n",
406 i, cmd, wfcmd->action);
407 return 1;
408 }
409
410 /* Now handle errors. Lots of special cases here */
411
412 if (c == 0xff) {
413 if ((c = wavefront_read (dev)) == -1) {
414 DPRINT (WF_DEBUG_IO, "bad read for "
415 "error byte at "
416 "read byte %d "
417 "of 0x%x [%s].\n",
418 i, cmd,
419 wfcmd->action);
420 return 1;
421 }
422
423 /* Can you believe this madness ? */
424
425 if (c == 1 &&
426 wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) {
427 rbuf[0] = WF_ST_EMPTY;
428 return (0);
429
430 } else if (c == 3 &&
431 wfcmd->cmd == WFC_UPLOAD_PATCH) {
432
433 return 3;
434
435 } else if (c == 1 &&
436 wfcmd->cmd == WFC_UPLOAD_PROGRAM) {
437
438 return 1;
439
440 } else {
441
442 DPRINT (WF_DEBUG_IO, "error %d (%s) "
443 "during "
444 "read for byte "
445 "%d of 0x%x "
446 "[%s].\n",
447 c,
448 wavefront_errorstr (c),
449 i, cmd,
450 wfcmd->action);
451 return 1;
452
453 }
454
455 } else {
456 rbuf[i] = c;
457 }
458
459 DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]);
460 }
461 }
462
463 if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
464
465 DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd);
466
467 /* Some commands need an ACK, but return zero instead
468 of the standard value.
469 */
470
471 if ((ack = wavefront_read (dev)) == 0) {
472 ack = WF_ACK;
473 }
474
475 if (ack != WF_ACK) {
476 if (ack == -1) {
477 DPRINT (WF_DEBUG_IO, "cannot read ack for "
478 "0x%x [%s].\n",
479 cmd, wfcmd->action);
480 return 1;
481
482 } else {
483 int err = -1; /* something unknown */
484
485 if (ack == 0xff) { /* explicit error */
486
487 if ((err = wavefront_read (dev)) == -1) {
488 DPRINT (WF_DEBUG_DATA,
489 "cannot read err "
490 "for 0x%x [%s].\n",
491 cmd, wfcmd->action);
492 }
493 }
494
495 DPRINT (WF_DEBUG_IO, "0x%x [%s] "
496 "failed (0x%x, 0x%x, %s)\n",
497 cmd, wfcmd->action, ack, err,
498 wavefront_errorstr (err));
499
500 return -err;
501 }
502 }
503
504 DPRINT (WF_DEBUG_DATA, "ack received "
505 "for 0x%x [%s]\n",
506 cmd, wfcmd->action);
507 } else {
508
509 DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need "
510 "ACK (%d,%d,%d)\n",
511 cmd, wfcmd->action, wfcmd->read_cnt,
512 wfcmd->write_cnt, wfcmd->need_ack);
513 }
514
515 return 0;
516
517}
518
519/***********************************************************************
520WaveFront data munging
521
522Things here are weird. All data written to the board cannot
523have its most significant bit set. Any data item with values
524potentially > 0x7F (127) must be split across multiple bytes.
525
526Sometimes, we need to munge numeric values that are represented on
527the x86 side as 8-32 bit values. Sometimes, we need to munge data
528that is represented on the x86 side as an array of bytes. The most
529efficient approach to handling both cases seems to be to use 2
530different functions for munging and 2 for de-munging. This avoids
531weird casting and worrying about bit-level offsets.
532
533**********************************************************************/
534
535static unsigned char *
536munge_int32 (unsigned int src,
537 unsigned char *dst,
538 unsigned int dst_size)
539{
540 unsigned int i;
541
542 for (i = 0; i < dst_size; i++) {
543 *dst = src & 0x7F; /* Mask high bit of LSB */
544 src = src >> 7; /* Rotate Right 7 bits */
545 /* Note: we leave the upper bits in place */
546
547 dst++;
548 };
549 return dst;
550};
551
552static int
553demunge_int32 (unsigned char* src, int src_size)
554
555{
556 int i;
557 int outval = 0;
558
559 for (i = src_size - 1; i >= 0; i--) {
560 outval=(outval<<7)+src[i];
561 }
562
563 return outval;
564};
565
566static
567unsigned char *
568munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size)
569
570{
571 unsigned int i;
572 unsigned int last = dst_size / 2;
573
574 for (i = 0; i < last; i++) {
575 *dst++ = src[i] & 0x7f;
576 *dst++ = src[i] >> 7;
577 }
578 return dst;
579}
580
581static
582unsigned char *
583demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes)
584
585{
586 int i;
587 unsigned char *end = src + src_bytes;
588
589 end = src + src_bytes;
590
591 /* NOTE: src and dst *CAN* point to the same address */
592
593 for (i = 0; src != end; i++) {
594 dst[i] = *src++;
595 dst[i] |= (*src++)<<7;
596 }
597
598 return dst;
599}
600
601/***********************************************************************
602WaveFront: sample, patch and program management.
603***********************************************************************/
604
605static int
606wavefront_delete_sample (snd_wavefront_t *dev, int sample_num)
607
608{
609 unsigned char wbuf[2];
610 int x;
611
612 wbuf[0] = sample_num & 0x7f;
613 wbuf[1] = sample_num >> 7;
614
615 if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) {
616 dev->sample_status[sample_num] = WF_ST_EMPTY;
617 }
618
619 return x;
620}
621
622static int
623wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom)
624
625{
626 int i;
627 unsigned char rbuf[32], wbuf[32];
628 unsigned int sc_real, sc_alias, sc_multi;
629
630 /* check sample status */
631
632 if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) {
633 snd_printk ("cannot request sample count.\n");
634 return -1;
635 }
636
637 sc_real = sc_alias = sc_multi = dev->samples_used = 0;
638
639 for (i = 0; i < WF_MAX_SAMPLE; i++) {
640
641 wbuf[0] = i & 0x7f;
642 wbuf[1] = i >> 7;
643
644 if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
645 snd_printk("cannot identify sample "
646 "type of slot %d\n", i);
647 dev->sample_status[i] = WF_ST_EMPTY;
648 continue;
649 }
650
651 dev->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
652
653 if (assume_rom) {
654 dev->sample_status[i] |= WF_SLOT_ROM;
655 }
656
657 switch (rbuf[0] & WF_ST_MASK) {
658 case WF_ST_SAMPLE:
659 sc_real++;
660 break;
661 case WF_ST_MULTISAMPLE:
662 sc_multi++;
663 break;
664 case WF_ST_ALIAS:
665 sc_alias++;
666 break;
667 case WF_ST_EMPTY:
668 break;
669
670 default:
671 snd_printk ("unknown sample type for "
672 "slot %d (0x%x)\n",
673 i, rbuf[0]);
674 }
675
676 if (rbuf[0] != WF_ST_EMPTY) {
677 dev->samples_used++;
678 }
679 }
680
681 snd_printk ("%d samples used (%d real, %d aliases, %d multi), "
682 "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi,
683 WF_MAX_SAMPLE - dev->samples_used);
684
685
686 return (0);
687
688}
689
690static int
691wavefront_get_patch_status (snd_wavefront_t *dev)
692
693{
694 unsigned char patchbuf[WF_PATCH_BYTES];
695 unsigned char patchnum[2];
696 wavefront_patch *p;
697 int i, x, cnt, cnt2;
698
699 for (i = 0; i < WF_MAX_PATCH; i++) {
700 patchnum[0] = i & 0x7f;
701 patchnum[1] = i >> 7;
702
703 if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PATCH, patchbuf,
704 patchnum)) == 0) {
705
706 dev->patch_status[i] |= WF_SLOT_FILLED;
707 p = (wavefront_patch *) patchbuf;
708 dev->sample_status
709 [p->sample_number|(p->sample_msb<<7)] |=
710 WF_SLOT_USED;
711
712 } else if (x == 3) { /* Bad patch number */
713 dev->patch_status[i] = 0;
714 } else {
715 snd_printk ("upload patch "
716 "error 0x%x\n", x);
717 dev->patch_status[i] = 0;
718 return 1;
719 }
720 }
721
722 /* program status has already filled in slot_used bits */
723
724 for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) {
725 if (dev->patch_status[i] & WF_SLOT_FILLED) {
726 cnt++;
727 }
728 if (dev->patch_status[i] & WF_SLOT_USED) {
729 cnt2++;
730 }
731
732 }
733 snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2);
734
735 return (0);
736}
737
738static int
739wavefront_get_program_status (snd_wavefront_t *dev)
740
741{
742 unsigned char progbuf[WF_PROGRAM_BYTES];
743 wavefront_program prog;
744 unsigned char prognum;
745 int i, x, l, cnt;
746
747 for (i = 0; i < WF_MAX_PROGRAM; i++) {
748 prognum = i;
749
750 if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PROGRAM, progbuf,
751 &prognum)) == 0) {
752
753 dev->prog_status[i] |= WF_SLOT_USED;
754
755 demunge_buf (progbuf, (unsigned char *) &prog,
756 WF_PROGRAM_BYTES);
757
758 for (l = 0; l < WF_NUM_LAYERS; l++) {
759 if (prog.layer[l].mute) {
760 dev->patch_status
761 [prog.layer[l].patch_number] |=
762 WF_SLOT_USED;
763 }
764 }
765 } else if (x == 1) { /* Bad program number */
766 dev->prog_status[i] = 0;
767 } else {
768 snd_printk ("upload program "
769 "error 0x%x\n", x);
770 dev->prog_status[i] = 0;
771 }
772 }
773
774 for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) {
775 if (dev->prog_status[i]) {
776 cnt++;
777 }
778 }
779
780 snd_printk ("%d programs slots in use\n", cnt);
781
782 return (0);
783}
784
785static int
786wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header)
787
788{
789 unsigned char buf[WF_PATCH_BYTES+2];
790 unsigned char *bptr;
791
792 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
793 header->number);
794
795 dev->patch_status[header->number] |= WF_SLOT_FILLED;
796
797 bptr = buf;
798 bptr = munge_int32 (header->number, buf, 2);
799 munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
800
801 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) {
802 snd_printk ("download patch failed\n");
803 return -(EIO);
804 }
805
806 return (0);
807}
808
809static int
810wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header)
811
812{
813 unsigned char buf[WF_PROGRAM_BYTES+1];
814 int i;
815
816 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
817 header->number);
818
819 dev->prog_status[header->number] = WF_SLOT_USED;
820
821 /* XXX need to zero existing SLOT_USED bit for program_status[i]
822 where `i' is the program that's being (potentially) overwritten.
823 */
824
825 for (i = 0; i < WF_NUM_LAYERS; i++) {
826 if (header->hdr.pr.layer[i].mute) {
827 dev->patch_status[header->hdr.pr.layer[i].patch_number] |=
828 WF_SLOT_USED;
829
830 /* XXX need to mark SLOT_USED for sample used by
831 patch_number, but this means we have to load it. Ick.
832 */
833 }
834 }
835
836 buf[0] = header->number;
837 munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
838
839 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
840 snd_printk ("download patch failed\n");
841 return -(EIO);
842 }
843
844 return (0);
845}
846
847static int
848wavefront_freemem (snd_wavefront_t *dev)
849
850{
851 char rbuf[8];
852
853 if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
854 snd_printk ("can't get memory stats.\n");
855 return -1;
856 } else {
857 return demunge_int32 (rbuf, 4);
858 }
859}
860
861static int
862wavefront_send_sample (snd_wavefront_t *dev,
863 wavefront_patch_info *header,
864 u16 __user *dataptr,
865 int data_is_unsigned)
866
867{
868 /* samples are downloaded via a 16-bit wide i/o port
869 (you could think of it as 2 adjacent 8-bit wide ports
870 but its less efficient that way). therefore, all
871 the blocksizes and so forth listed in the documentation,
872 and used conventionally to refer to sample sizes,
873 which are given in 8-bit units (bytes), need to be
874 divided by 2.
875 */
876
877 u16 sample_short;
878 u32 length;
879 u16 __user *data_end = NULL;
880 unsigned int i;
881 const unsigned int max_blksize = 4096/2;
882 unsigned int written;
883 unsigned int blocksize;
884 int dma_ack;
885 int blocknum;
886 unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES];
887 unsigned char *shptr;
888 int skip = 0;
889 int initial_skip = 0;
890
891 DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, "
892 "type %d, %d bytes from 0x%lx\n",
893 header->size ? "" : "header ",
894 header->number, header->subkey,
895 header->size,
896 (unsigned long) header->dataptr);
897
898 if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) {
899 int x;
900
901 if ((x = wavefront_find_free_sample (dev)) < 0) {
902 return -ENOMEM;
903 }
904 snd_printk ("unspecified sample => %d\n", x);
905 header->number = x;
906 }
907
908 if (header->size) {
909
910 /* XXX it's a debatable point whether or not RDONLY semantics
911 on the ROM samples should cover just the sample data or
912 the sample header. For now, it only covers the sample data,
913 so anyone is free at all times to rewrite sample headers.
914
915 My reason for this is that we have the sample headers
916 available in the WFB file for General MIDI, and so these
917 can always be reset if needed. The sample data, however,
918 cannot be recovered without a complete reset and firmware
919 reload of the ICS2115, which is a very expensive operation.
920
921 So, doing things this way allows us to honor the notion of
922 "RESETSAMPLES" reasonably cheaply. Note however, that this
923 is done purely at user level: there is no WFB parser in
924 this driver, and so a complete reset (back to General MIDI,
925 or theoretically some other configuration) is the
926 responsibility of the user level library.
927
928 To try to do this in the kernel would be a little
929 crazy: we'd need 158K of kernel space just to hold
930 a copy of the patch/program/sample header data.
931 */
932
933 if (dev->rom_samples_rdonly) {
934 if (dev->sample_status[header->number] & WF_SLOT_ROM) {
935 snd_printk ("sample slot %d "
936 "write protected\n",
937 header->number);
938 return -EACCES;
939 }
940 }
941
942 wavefront_delete_sample (dev, header->number);
943 }
944
945 if (header->size) {
946 dev->freemem = wavefront_freemem (dev);
947
948 if (dev->freemem < (int)header->size) {
949 snd_printk ("insufficient memory to "
950 "load %d byte sample.\n",
951 header->size);
952 return -ENOMEM;
953 }
954
955 }
956
957 skip = WF_GET_CHANNEL(&header->hdr.s);
958
959 if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
960 snd_printk ("channel selection only "
961 "possible on 16-bit samples");
962 return -(EINVAL);
963 }
964
965 switch (skip) {
966 case 0:
967 initial_skip = 0;
968 skip = 1;
969 break;
970 case 1:
971 initial_skip = 0;
972 skip = 2;
973 break;
974 case 2:
975 initial_skip = 1;
976 skip = 2;
977 break;
978 case 3:
979 initial_skip = 2;
980 skip = 3;
981 break;
982 case 4:
983 initial_skip = 3;
984 skip = 4;
985 break;
986 case 5:
987 initial_skip = 4;
988 skip = 5;
989 break;
990 case 6:
991 initial_skip = 5;
992 skip = 6;
993 break;
994 }
995
996 DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => "
997 "initial skip = %d, skip = %d\n",
998 WF_GET_CHANNEL (&header->hdr.s),
999 initial_skip, skip);
1000
1001 /* Be safe, and zero the "Unused" bits ... */
1002
1003 WF_SET_CHANNEL(&header->hdr.s, 0);
1004
1005 /* adjust size for 16 bit samples by dividing by two. We always
1006 send 16 bits per write, even for 8 bit samples, so the length
1007 is always half the size of the sample data in bytes.
1008 */
1009
1010 length = header->size / 2;
1011
1012 /* the data we're sent has not been munged, and in fact, the
1013 header we have to send isn't just a munged copy either.
1014 so, build the sample header right here.
1015 */
1016
1017 shptr = &sample_hdr[0];
1018
1019 shptr = munge_int32 (header->number, shptr, 2);
1020
1021 if (header->size) {
1022 shptr = munge_int32 (length, shptr, 4);
1023 }
1024
1025 /* Yes, a 4 byte result doesn't contain all of the offset bits,
1026 but the offset only uses 24 bits.
1027 */
1028
1029 shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleStartOffset),
1030 shptr, 4);
1031 shptr = munge_int32 (*((u32 *) &header->hdr.s.loopStartOffset),
1032 shptr, 4);
1033 shptr = munge_int32 (*((u32 *) &header->hdr.s.loopEndOffset),
1034 shptr, 4);
1035 shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleEndOffset),
1036 shptr, 4);
1037
1038 /* This one is truly weird. What kind of weirdo decided that in
1039 a system dominated by 16 and 32 bit integers, they would use
1040 a just 12 bits ?
1041 */
1042
1043 shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);
1044
1045 /* Why is this nybblified, when the MSB is *always* zero ?
1046 Anyway, we can't take address of bitfield, so make a
1047 good-faith guess at where it starts.
1048 */
1049
1050 shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),
1051 shptr, 2);
1052
1053 if (snd_wavefront_cmd (dev,
1054 header->size ?
1055 WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
1056 NULL, sample_hdr)) {
1057 snd_printk ("sample %sdownload refused.\n",
1058 header->size ? "" : "header ");
1059 return -(EIO);
1060 }
1061
1062 if (header->size == 0) {
1063 goto sent; /* Sorry. Just had to have one somewhere */
1064 }
1065
1066 data_end = dataptr + length;
1067
1068 /* Do any initial skip over an unused channel's data */
1069
1070 dataptr += initial_skip;
1071
1072 for (written = 0, blocknum = 0;
1073 written < length; written += max_blksize, blocknum++) {
1074
1075 if ((length - written) > max_blksize) {
1076 blocksize = max_blksize;
1077 } else {
1078 /* round to nearest 16-byte value */
1079 blocksize = ((length-written+7)&~0x7);
1080 }
1081
1082 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
1083 snd_printk ("download block "
1084 "request refused.\n");
1085 return -(EIO);
1086 }
1087
1088 for (i = 0; i < blocksize; i++) {
1089
1090 if (dataptr < data_end) {
1091
1092 __get_user (sample_short, dataptr);
1093 dataptr += skip;
1094
1095 if (data_is_unsigned) { /* GUS ? */
1096
1097 if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {
1098
1099 /* 8 bit sample
1100 resolution, sign
1101 extend both bytes.
1102 */
1103
1104 ((unsigned char*)
1105 &sample_short)[0] += 0x7f;
1106 ((unsigned char*)
1107 &sample_short)[1] += 0x7f;
1108
1109 } else {
1110
1111 /* 16 bit sample
1112 resolution, sign
1113 extend the MSB.
1114 */
1115
1116 sample_short += 0x7fff;
1117 }
1118 }
1119
1120 } else {
1121
1122 /* In padding section of final block:
1123
1124 Don't fetch unsupplied data from
1125 user space, just continue with
1126 whatever the final value was.
1127 */
1128 }
1129
1130 if (i < blocksize - 1) {
1131 outw (sample_short, dev->block_port);
1132 } else {
1133 outw (sample_short, dev->last_block_port);
1134 }
1135 }
1136
1137 /* Get "DMA page acknowledge", even though its really
1138 nothing to do with DMA at all.
1139 */
1140
1141 if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) {
1142 if (dma_ack == -1) {
1143 snd_printk ("upload sample "
1144 "DMA ack timeout\n");
1145 return -(EIO);
1146 } else {
1147 snd_printk ("upload sample "
1148 "DMA ack error 0x%x\n",
1149 dma_ack);
1150 return -(EIO);
1151 }
1152 }
1153 }
1154
1155 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
1156
1157 /* Note, label is here because sending the sample header shouldn't
1158 alter the sample_status info at all.
1159 */
1160
1161 sent:
1162 return (0);
1163}
1164
1165static int
1166wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header)
1167
1168{
1169 unsigned char alias_hdr[WF_ALIAS_BYTES];
1170
1171 DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is "
1172 "alias for %d\n",
1173 header->number,
1174 header->hdr.a.OriginalSample);
1175
1176 munge_int32 (header->number, &alias_hdr[0], 2);
1177 munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
1178 munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset),
1179 &alias_hdr[4], 4);
1180 munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset),
1181 &alias_hdr[8], 4);
1182 munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset),
1183 &alias_hdr[12], 4);
1184 munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset),
1185 &alias_hdr[16], 4);
1186 munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
1187 munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
1188
1189 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
1190 snd_printk ("download alias failed.\n");
1191 return -(EIO);
1192 }
1193
1194 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
1195
1196 return (0);
1197}
1198
1199static int
1200wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
1201{
1202 int i;
1203 int num_samples;
1204 unsigned char *msample_hdr;
1205
1206 msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);
1207 if (! msample_hdr)
1208 return -ENOMEM;
1209
1210 munge_int32 (header->number, &msample_hdr[0], 2);
1211
1212 /* You'll recall at this point that the "number of samples" value
1213 in a wavefront_multisample struct is actually the log2 of the
1214 real number of samples.
1215 */
1216
1217 num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
1218 msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
1219
1220 DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n",
1221 header->number,
1222 header->hdr.ms.NumberOfSamples,
1223 num_samples);
1224
1225 for (i = 0; i < num_samples; i++) {
1226 DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n",
1227 i, header->hdr.ms.SampleNumber[i]);
1228 munge_int32 (header->hdr.ms.SampleNumber[i],
1229 &msample_hdr[3+(i*2)], 2);
1230 }
1231
1232 /* Need a hack here to pass in the number of bytes
1233 to be written to the synth. This is ugly, and perhaps
1234 one day, I'll fix it.
1235 */
1236
1237 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE,
1238 (unsigned char *) (long) ((num_samples*2)+3),
1239 msample_hdr)) {
1240 snd_printk ("download of multisample failed.\n");
1241 kfree(msample_hdr);
1242 return -(EIO);
1243 }
1244
1245 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
1246
1247 kfree(msample_hdr);
1248 return (0);
1249}
1250
1251static int
1252wavefront_fetch_multisample (snd_wavefront_t *dev,
1253 wavefront_patch_info *header)
1254{
1255 int i;
1256 unsigned char log_ns[1];
1257 unsigned char number[2];
1258 int num_samples;
1259
1260 munge_int32 (header->number, number, 2);
1261
1262 if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
1263 snd_printk ("upload multisample failed.\n");
1264 return -(EIO);
1265 }
1266
1267 DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n",
1268 header->number, log_ns[0]);
1269
1270 header->hdr.ms.NumberOfSamples = log_ns[0];
1271
1272 /* get the number of samples ... */
1273
1274 num_samples = (1 << log_ns[0]);
1275
1276 for (i = 0; i < num_samples; i++) {
1277 char d[2];
1278 int val;
1279
1280 if ((val = wavefront_read (dev)) == -1) {
1281 snd_printk ("upload multisample failed "
1282 "during sample loop.\n");
1283 return -(EIO);
1284 }
1285 d[0] = val;
1286
1287 if ((val = wavefront_read (dev)) == -1) {
1288 snd_printk ("upload multisample failed "
1289 "during sample loop.\n");
1290 return -(EIO);
1291 }
1292 d[1] = val;
1293
1294 header->hdr.ms.SampleNumber[i] =
1295 demunge_int32 ((unsigned char *) d, 2);
1296
1297 DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n",
1298 i, header->hdr.ms.SampleNumber[i]);
1299 }
1300
1301 return (0);
1302}
1303
1304
1305static int
1306wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header)
1307
1308{
1309 unsigned char drumbuf[WF_DRUM_BYTES];
1310 wavefront_drum *drum = &header->hdr.d;
1311 int i;
1312
1313 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI "
1314 "note %d, patch = %d\n",
1315 header->number, drum->PatchNumber);
1316
1317 drumbuf[0] = header->number & 0x7f;
1318
1319 for (i = 0; i < 4; i++) {
1320 munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
1321 }
1322
1323 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
1324 snd_printk ("download drum failed.\n");
1325 return -(EIO);
1326 }
1327
1328 return (0);
1329}
1330
1331static int
1332wavefront_find_free_sample (snd_wavefront_t *dev)
1333
1334{
1335 int i;
1336
1337 for (i = 0; i < WF_MAX_SAMPLE; i++) {
1338 if (!(dev->sample_status[i] & WF_SLOT_FILLED)) {
1339 return i;
1340 }
1341 }
1342 snd_printk ("no free sample slots!\n");
1343 return -1;
1344}
1345
1346#if 0
1347static int
1348wavefront_find_free_patch (snd_wavefront_t *dev)
1349
1350{
1351 int i;
1352
1353 for (i = 0; i < WF_MAX_PATCH; i++) {
1354 if (!(dev->patch_status[i] & WF_SLOT_FILLED)) {
1355 return i;
1356 }
1357 }
1358 snd_printk ("no free patch slots!\n");
1359 return -1;
1360}
1361#endif
1362
1363static int
1364wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr)
1365{
1366 wavefront_patch_info *header;
1367 int err;
1368
1369 header = kmalloc(sizeof(*header), GFP_KERNEL);
1370 if (! header)
1371 return -ENOMEM;
1372
1373 if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
1374 sizeof(wavefront_any))) {
1375 snd_printk ("bad address for load patch.\n");
1376 err = -EFAULT;
1377 goto __error;
1378 }
1379
1380 DPRINT (WF_DEBUG_LOAD_PATCH, "download "
1381 "Sample type: %d "
1382 "Sample number: %d "
1383 "Sample size: %d\n",
1384 header->subkey,
1385 header->number,
1386 header->size);
1387
1388 switch (header->subkey) {
1389 case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
1390
1391 if (copy_from_user (&header->hdr.s, header->hdrptr,
1392 sizeof (wavefront_sample))) {
1393 err = -EFAULT;
1394 break;
1395 }
1396
1397 err = wavefront_send_sample (dev, header, header->dataptr, 0);
1398 break;
1399
1400 case WF_ST_MULTISAMPLE:
1401
1402 if (copy_from_user (&header->hdr.s, header->hdrptr,
1403 sizeof (wavefront_multisample))) {
1404 err = -EFAULT;
1405 break;
1406 }
1407
1408 err = wavefront_send_multisample (dev, header);
1409 break;
1410
1411 case WF_ST_ALIAS:
1412
1413 if (copy_from_user (&header->hdr.a, header->hdrptr,
1414 sizeof (wavefront_alias))) {
1415 err = -EFAULT;
1416 break;
1417 }
1418
1419 err = wavefront_send_alias (dev, header);
1420 break;
1421
1422 case WF_ST_DRUM:
1423 if (copy_from_user (&header->hdr.d, header->hdrptr,
1424 sizeof (wavefront_drum))) {
1425 err = -EFAULT;
1426 break;
1427 }
1428
1429 err = wavefront_send_drum (dev, header);
1430 break;
1431
1432 case WF_ST_PATCH:
1433 if (copy_from_user (&header->hdr.p, header->hdrptr,
1434 sizeof (wavefront_patch))) {
1435 err = -EFAULT;
1436 break;
1437 }
1438
1439 err = wavefront_send_patch (dev, header);
1440 break;
1441
1442 case WF_ST_PROGRAM:
1443 if (copy_from_user (&header->hdr.pr, header->hdrptr,
1444 sizeof (wavefront_program))) {
1445 err = -EFAULT;
1446 break;
1447 }
1448
1449 err = wavefront_send_program (dev, header);
1450 break;
1451
1452 default:
1453 snd_printk ("unknown patch type %d.\n",
1454 header->subkey);
1455 err = -EINVAL;
1456 break;
1457 }
1458
1459 __error:
1460 kfree(header);
1461 return err;
1462}
1463
1464/***********************************************************************
1465WaveFront: hardware-dependent interface
1466***********************************************************************/
1467
1468static void
1469process_sample_hdr (u8 *buf)
1470
1471{
1472 wavefront_sample s;
1473 u8 *ptr;
1474
1475 ptr = buf;
1476
1477 /* The board doesn't send us an exact copy of a "wavefront_sample"
1478 in response to an Upload Sample Header command. Instead, we
1479 have to convert the data format back into our data structure,
1480 just as in the Download Sample command, where we have to do
1481 something very similar in the reverse direction.
1482 */
1483
1484 *((u32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
1485 *((u32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
1486 *((u32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
1487 *((u32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
1488 *((u32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3;
1489
1490 s.SampleResolution = *ptr & 0x3;
1491 s.Loop = *ptr & 0x8;
1492 s.Bidirectional = *ptr & 0x10;
1493 s.Reverse = *ptr & 0x40;
1494
1495 /* Now copy it back to where it came from */
1496
1497 memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample));
1498}
1499
1500static int
1501wavefront_synth_control (snd_wavefront_card_t *acard,
1502 wavefront_control *wc)
1503
1504{
1505 snd_wavefront_t *dev = &acard->wavefront;
1506 unsigned char patchnumbuf[2];
1507 int i;
1508
1509 DPRINT (WF_DEBUG_CMD, "synth control with "
1510 "cmd 0x%x\n", wc->cmd);
1511
1512 /* Pre-handling of or for various commands */
1513
1514 switch (wc->cmd) {
1515
1516 case WFC_DISABLE_INTERRUPTS:
1517 snd_printk ("interrupts disabled.\n");
1518 outb (0x80|0x20, dev->control_port);
1519 dev->interrupts_are_midi = 1;
1520 return 0;
1521
1522 case WFC_ENABLE_INTERRUPTS:
1523 snd_printk ("interrupts enabled.\n");
1524 outb (0x80|0x40|0x20, dev->control_port);
1525 dev->interrupts_are_midi = 1;
1526 return 0;
1527
1528 case WFC_INTERRUPT_STATUS:
1529 wc->rbuf[0] = dev->interrupts_are_midi;
1530 return 0;
1531
1532 case WFC_ROMSAMPLES_RDONLY:
1533 dev->rom_samples_rdonly = wc->wbuf[0];
1534 wc->status = 0;
1535 return 0;
1536
1537 case WFC_IDENTIFY_SLOT_TYPE:
1538 i = wc->wbuf[0] | (wc->wbuf[1] << 7);
1539 if (i <0 || i >= WF_MAX_SAMPLE) {
1540 snd_printk ("invalid slot ID %d\n",
1541 i);
1542 wc->status = EINVAL;
1543 return -EINVAL;
1544 }
1545 wc->rbuf[0] = dev->sample_status[i];
1546 wc->status = 0;
1547 return 0;
1548
1549 case WFC_DEBUG_DRIVER:
1550 dev->debug = wc->wbuf[0];
1551 snd_printk ("debug = 0x%x\n", dev->debug);
1552 return 0;
1553
1554 case WFC_UPLOAD_PATCH:
1555 munge_int32 (*((u32 *) wc->wbuf), patchnumbuf, 2);
1556 memcpy (wc->wbuf, patchnumbuf, 2);
1557 break;
1558
1559 case WFC_UPLOAD_MULTISAMPLE:
1560 /* multisamples have to be handled differently, and
1561 cannot be dealt with properly by snd_wavefront_cmd() alone.
1562 */
1563 wc->status = wavefront_fetch_multisample
1564 (dev, (wavefront_patch_info *) wc->rbuf);
1565 return 0;
1566
1567 case WFC_UPLOAD_SAMPLE_ALIAS:
1568 snd_printk ("support for sample alias upload "
1569 "being considered.\n");
1570 wc->status = EINVAL;
1571 return -EINVAL;
1572 }
1573
1574 wc->status = snd_wavefront_cmd (dev, wc->cmd, wc->rbuf, wc->wbuf);
1575
1576 /* Post-handling of certain commands.
1577
1578 In particular, if the command was an upload, demunge the data
1579 so that the user-level doesn't have to think about it.
1580 */
1581
1582 if (wc->status == 0) {
1583 switch (wc->cmd) {
1584 /* intercept any freemem requests so that we know
1585 we are always current with the user-level view
1586 of things.
1587 */
1588
1589 case WFC_REPORT_FREE_MEMORY:
1590 dev->freemem = demunge_int32 (wc->rbuf, 4);
1591 break;
1592
1593 case WFC_UPLOAD_PATCH:
1594 demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES);
1595 break;
1596
1597 case WFC_UPLOAD_PROGRAM:
1598 demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES);
1599 break;
1600
1601 case WFC_UPLOAD_EDRUM_PROGRAM:
1602 demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1);
1603 break;
1604
1605 case WFC_UPLOAD_SAMPLE_HEADER:
1606 process_sample_hdr (wc->rbuf);
1607 break;
1608
1609 case WFC_UPLOAD_SAMPLE_ALIAS:
1610 snd_printk ("support for "
1611 "sample aliases still "
1612 "being considered.\n");
1613 break;
1614
1615 case WFC_VMIDI_OFF:
1616 snd_wavefront_midi_disable_virtual (acard);
1617 break;
1618
1619 case WFC_VMIDI_ON:
1620 snd_wavefront_midi_enable_virtual (acard);
1621 break;
1622 }
1623 }
1624
1625 return 0;
1626}
1627
1628int
1629snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
1630
1631{
1632 if (!try_module_get(hw->card->module))
1633 return -EFAULT;
1634 file->private_data = hw;
1635 return 0;
1636}
1637
1638int
1639snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
1640
1641{
1642 module_put(hw->card->module);
1643 return 0;
1644}
1645
1646int
1647snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
1648 unsigned int cmd, unsigned long arg)
1649
1650{
1651 snd_card_t *card;
1652 snd_wavefront_t *dev;
1653 snd_wavefront_card_t *acard;
1654 wavefront_control *wc;
1655 void __user *argp = (void __user *)arg;
1656 int err;
1657
1658 card = (snd_card_t *) hw->card;
1659
1660 snd_assert(card != NULL, return -ENODEV);
1661
1662 snd_assert(card->private_data != NULL, return -ENODEV);
1663
1664 acard = card->private_data;
1665 dev = &acard->wavefront;
1666
1667 switch (cmd) {
1668 case WFCTL_LOAD_SPP:
1669 if (wavefront_load_patch (dev, argp) != 0) {
1670 return -EIO;
1671 }
1672 break;
1673
1674 case WFCTL_WFCMD:
1675 wc = kmalloc(sizeof(*wc), GFP_KERNEL);
1676 if (! wc)
1677 return -ENOMEM;
1678 if (copy_from_user (wc, argp, sizeof (*wc)))
1679 err = -EFAULT;
1680 else if (wavefront_synth_control (acard, wc) < 0)
1681 err = -EIO;
1682 else if (copy_to_user (argp, wc, sizeof (*wc)))
1683 err = -EFAULT;
1684 else
1685 err = 0;
1686 kfree(wc);
1687 return err;
1688
1689 default:
1690 return -EINVAL;
1691 }
1692
1693 return 0;
1694}
1695
1696
1697/***********************************************************************/
1698/* WaveFront: interface for card-level wavefront module */
1699/***********************************************************************/
1700
1701void
1702snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
1703{
1704 snd_wavefront_t *dev = &card->wavefront;
1705
1706 /*
1707 Some comments on interrupts. I attempted a version of this
1708 driver that used interrupts throughout the code instead of
1709 doing busy and/or sleep-waiting. Alas, it appears that once
1710 the Motorola firmware is downloaded, the card *never*
1711 generates an RX interrupt. These are successfully generated
1712 during firmware loading, and after that wavefront_status()
1713 reports that an interrupt is pending on the card from time
1714 to time, but it never seems to be delivered to this
1715 driver. Note also that wavefront_status() continues to
1716 report that RX interrupts are enabled, suggesting that I
1717 didn't goof up and disable them by mistake.
1718
1719 Thus, I stepped back to a prior version of
1720 wavefront_wait(), the only place where this really
1721 matters. Its sad, but I've looked through the code to check
1722 on things, and I really feel certain that the Motorola
1723 firmware prevents RX-ready interrupts.
1724 */
1725
1726 if ((wavefront_status(dev) & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) {
1727 return;
1728 }
1729
1730 spin_lock(&dev->irq_lock);
1731 dev->irq_ok = 1;
1732 dev->irq_cnt++;
1733 spin_unlock(&dev->irq_lock);
1734 wake_up(&dev->interrupt_sleeper);
1735}
1736
1737/* STATUS REGISTER
1738
17390 Host Rx Interrupt Enable (1=Enabled)
17401 Host Rx Register Full (1=Full)
17412 Host Rx Interrupt Pending (1=Interrupt)
17423 Unused
17434 Host Tx Interrupt (1=Enabled)
17445 Host Tx Register empty (1=Empty)
17456 Host Tx Interrupt Pending (1=Interrupt)
17467 Unused
1747*/
1748
1749static int __init
1750snd_wavefront_interrupt_bits (int irq)
1751
1752{
1753 int bits;
1754
1755 switch (irq) {
1756 case 9:
1757 bits = 0x00;
1758 break;
1759 case 5:
1760 bits = 0x08;
1761 break;
1762 case 12:
1763 bits = 0x10;
1764 break;
1765 case 15:
1766 bits = 0x18;
1767 break;
1768
1769 default:
1770 snd_printk ("invalid IRQ %d\n", irq);
1771 bits = -1;
1772 }
1773
1774 return bits;
1775}
1776
1777static void __init
1778wavefront_should_cause_interrupt (snd_wavefront_t *dev,
1779 int val, int port, int timeout)
1780
1781{
1782 wait_queue_t wait;
1783
1784 init_waitqueue_entry(&wait, current);
1785 spin_lock_irq(&dev->irq_lock);
1786 add_wait_queue(&dev->interrupt_sleeper, &wait);
1787 dev->irq_ok = 0;
1788 outb (val,port);
1789 spin_unlock_irq(&dev->irq_lock);
1790 while (1) {
1791 set_current_state(TASK_INTERRUPTIBLE);
1792 if ((timeout = schedule_timeout(timeout)) == 0)
1793 return;
1794 if (dev->irq_ok)
1795 return;
1796 }
1797}
1798
1799static int __init
1800wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
1801
1802{
1803 int bits;
1804 int hwv[2];
1805
1806 /* IRQ already checked */
1807
1808 bits = snd_wavefront_interrupt_bits (dev->irq);
1809
1810 /* try reset of port */
1811
1812 outb (0x0, dev->control_port);
1813
1814 /* At this point, the board is in reset, and the H/W initialization
1815 register is accessed at the same address as the data port.
1816
1817 Bit 7 - Enable IRQ Driver
1818 0 - Tri-state the Wave-Board drivers for the PC Bus IRQs
1819 1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus.
1820
1821 Bit 6 - MIDI Interface Select
1822
1823 0 - Use the MIDI Input from the 26-pin WaveBlaster
1824 compatible header as the serial MIDI source
1825 1 - Use the MIDI Input from the 9-pin D connector as the
1826 serial MIDI source.
1827
1828 Bits 5:3 - IRQ Selection
1829 0 0 0 - IRQ 2/9
1830 0 0 1 - IRQ 5
1831 0 1 0 - IRQ 12
1832 0 1 1 - IRQ 15
1833 1 0 0 - Reserved
1834 1 0 1 - Reserved
1835 1 1 0 - Reserved
1836 1 1 1 - Reserved
1837
1838 Bits 2:1 - Reserved
1839 Bit 0 - Disable Boot ROM
1840 0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM
1841 1 - memory accesses to 03FC30-03FFFFH are directed to external
1842 storage.
1843
1844 */
1845
1846 /* configure hardware: IRQ, enable interrupts,
1847 plus external 9-pin MIDI interface selected
1848 */
1849
1850 outb (0x80 | 0x40 | bits, dev->data_port);
1851
1852 /* CONTROL REGISTER
1853
1854 0 Host Rx Interrupt Enable (1=Enabled) 0x1
1855 1 Unused 0x2
1856 2 Unused 0x4
1857 3 Unused 0x8
1858 4 Host Tx Interrupt Enable 0x10
1859 5 Mute (0=Mute; 1=Play) 0x20
1860 6 Master Interrupt Enable (1=Enabled) 0x40
1861 7 Master Reset (0=Reset; 1=Run) 0x80
1862
1863 Take us out of reset, mute output, master + TX + RX interrupts on.
1864
1865 We'll get an interrupt presumably to tell us that the TX
1866 register is clear.
1867 */
1868
1869 wavefront_should_cause_interrupt(dev, 0x80|0x40|0x10|0x1,
1870 dev->control_port,
1871 (reset_time*HZ)/100);
1872
1873 /* Note: data port is now the data port, not the h/w initialization
1874 port.
1875 */
1876
1877 if (!dev->irq_ok) {
1878 snd_printk ("intr not received after h/w un-reset.\n");
1879 goto gone_bad;
1880 }
1881
1882 /* Note: data port is now the data port, not the h/w initialization
1883 port.
1884
1885 At this point, only "HW VERSION" or "DOWNLOAD OS" commands
1886 will work. So, issue one of them, and wait for TX
1887 interrupt. This can take a *long* time after a cold boot,
1888 while the ISC ROM does its RAM test. The SDK says up to 4
1889 seconds - with 12MB of RAM on a Tropez+, it takes a lot
1890 longer than that (~16secs). Note that the card understands
1891 the difference between a warm and a cold boot, so
1892 subsequent ISC2115 reboots (say, caused by module
1893 reloading) will get through this much faster.
1894
1895 XXX Interesting question: why is no RX interrupt received first ?
1896 */
1897
1898 wavefront_should_cause_interrupt(dev, WFC_HARDWARE_VERSION,
1899 dev->data_port, ramcheck_time*HZ);
1900
1901 if (!dev->irq_ok) {
1902 snd_printk ("post-RAM-check interrupt not received.\n");
1903 goto gone_bad;
1904 }
1905
1906 if (!wavefront_wait (dev, STAT_CAN_READ)) {
1907 snd_printk ("no response to HW version cmd.\n");
1908 goto gone_bad;
1909 }
1910
1911 if ((hwv[0] = wavefront_read (dev)) == -1) {
1912 snd_printk ("board not responding correctly.\n");
1913 goto gone_bad;
1914 }
1915
1916 if (hwv[0] == 0xFF) { /* NAK */
1917
1918 /* Board's RAM test failed. Try to read error code,
1919 and tell us about it either way.
1920 */
1921
1922 if ((hwv[0] = wavefront_read (dev)) == -1) {
1923 snd_printk ("on-board RAM test failed "
1924 "(bad error code).\n");
1925 } else {
1926 snd_printk ("on-board RAM test failed "
1927 "(error code: 0x%x).\n",
1928 hwv[0]);
1929 }
1930 goto gone_bad;
1931 }
1932
1933 /* We're OK, just get the next byte of the HW version response */
1934
1935 if ((hwv[1] = wavefront_read (dev)) == -1) {
1936 snd_printk ("incorrect h/w response.\n");
1937 goto gone_bad;
1938 }
1939
1940 snd_printk ("hardware version %d.%d\n",
1941 hwv[0], hwv[1]);
1942
1943 return 0;
1944
1945
1946 gone_bad:
1947 return (1);
1948}
1949
1950#include <linux/fs.h>
1951#include <linux/mm.h>
1952#include <linux/slab.h>
1953#include <linux/unistd.h>
1954#include <linux/syscalls.h>
1955#include <asm/uaccess.h>
1956
1957
1958static int __init
1959wavefront_download_firmware (snd_wavefront_t *dev, char *path)
1960
1961{
1962 unsigned char section[WF_SECTION_MAX];
1963 signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
1964 int section_cnt_downloaded = 0;
1965 int fd;
1966 int c;
1967 int i;
1968 mm_segment_t fs;
1969
1970 /* This tries to be a bit cleverer than the stuff Alan Cox did for
1971 the generic sound firmware, in that it actually knows
1972 something about the structure of the Motorola firmware. In
1973 particular, it uses a version that has been stripped of the
1974 20K of useless header information, and had section lengths
1975 added, making it possible to load the entire OS without any
1976 [kv]malloc() activity, since the longest entity we ever read is
1977 42 bytes (well, WF_SECTION_MAX) long.
1978 */
1979
1980 fs = get_fs();
1981 set_fs (get_ds());
1982
1983 if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
1984 snd_printk ("Unable to load \"%s\".\n",
1985 path);
1986 return 1;
1987 }
1988
1989 while (1) {
1990 int x;
1991
1992 if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
1993 sizeof (section_length)) {
1994 snd_printk ("firmware read error.\n");
1995 goto failure;
1996 }
1997
1998 if (section_length == 0) {
1999 break;
2000 }
2001
2002 if (section_length < 0 || section_length > WF_SECTION_MAX) {
2003 snd_printk ("invalid firmware section length %d\n",
2004 section_length);
2005 goto failure;
2006 }
2007
2008 if (sys_read (fd, (char __user *) section, section_length) != section_length) {
2009 snd_printk ("firmware section "
2010 "read error.\n");
2011 goto failure;
2012 }
2013
2014 /* Send command */
2015
2016 if (wavefront_write (dev, WFC_DOWNLOAD_OS)) {
2017 goto failure;
2018 }
2019
2020 for (i = 0; i < section_length; i++) {
2021 if (wavefront_write (dev, section[i])) {
2022 goto failure;
2023 }
2024 }
2025
2026 /* get ACK */
2027
2028 if (wavefront_wait (dev, STAT_CAN_READ)) {
2029
2030 if ((c = inb (dev->data_port)) != WF_ACK) {
2031
2032 snd_printk ("download "
2033 "of section #%d not "
2034 "acknowledged, ack = 0x%x\n",
2035 section_cnt_downloaded + 1, c);
2036 goto failure;
2037
2038 }
2039
2040 } else {
2041 snd_printk ("time out for firmware ACK.\n");
2042 goto failure;
2043 }
2044
2045 }
2046
2047 sys_close (fd);
2048 set_fs (fs);
2049 return 0;
2050
2051 failure:
2052 sys_close (fd);
2053 set_fs (fs);
2054 snd_printk ("firmware download failed!!!\n");
2055 return 1;
2056}
2057
2058
2059static int __init
2060wavefront_do_reset (snd_wavefront_t *dev)
2061
2062{
2063 char voices[1];
2064
2065 if (wavefront_reset_to_cleanliness (dev)) {
2066 snd_printk ("hw reset failed.\n");
2067 goto gone_bad;
2068 }
2069
2070 if (dev->israw) {
2071 if (wavefront_download_firmware (dev, ospath)) {
2072 goto gone_bad;
2073 }
2074
2075 dev->israw = 0;
2076
2077 /* Wait for the OS to get running. The protocol for
2078 this is non-obvious, and was determined by
2079 using port-IO tracing in DOSemu and some
2080 experimentation here.
2081
2082 Rather than using timed waits, use interrupts creatively.
2083 */
2084
2085 wavefront_should_cause_interrupt (dev, WFC_NOOP,
2086 dev->data_port,
2087 (osrun_time*HZ));
2088
2089 if (!dev->irq_ok) {
2090 snd_printk ("no post-OS interrupt.\n");
2091 goto gone_bad;
2092 }
2093
2094 /* Now, do it again ! */
2095
2096 wavefront_should_cause_interrupt (dev, WFC_NOOP,
2097 dev->data_port, (10*HZ));
2098
2099 if (!dev->irq_ok) {
2100 snd_printk ("no post-OS interrupt(2).\n");
2101 goto gone_bad;
2102 }
2103
2104 /* OK, no (RX/TX) interrupts any more, but leave mute
2105 in effect.
2106 */
2107
2108 outb (0x80|0x40, dev->control_port);
2109 }
2110
2111 /* SETUPSND.EXE asks for sample memory config here, but since i
2112 have no idea how to interpret the result, we'll forget
2113 about it.
2114 */
2115
2116 if ((dev->freemem = wavefront_freemem (dev)) < 0) {
2117 goto gone_bad;
2118 }
2119
2120 snd_printk ("available DRAM %dk\n", dev->freemem / 1024);
2121
2122 if (wavefront_write (dev, 0xf0) ||
2123 wavefront_write (dev, 1) ||
2124 (wavefront_read (dev) < 0)) {
2125 dev->debug = 0;
2126 snd_printk ("MPU emulation mode not set.\n");
2127 goto gone_bad;
2128 }
2129
2130 voices[0] = 32;
2131
2132 if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {
2133 snd_printk ("cannot set number of voices to 32.\n");
2134 goto gone_bad;
2135 }
2136
2137
2138 return 0;
2139
2140 gone_bad:
2141 /* reset that sucker so that it doesn't bother us. */
2142
2143 outb (0x0, dev->control_port);
2144 dev->interrupts_are_midi = 0;
2145 return 1;
2146}
2147
2148int __init
2149snd_wavefront_start (snd_wavefront_t *dev)
2150
2151{
2152 int samples_are_from_rom;
2153
2154 /* IMPORTANT: assumes that snd_wavefront_detect() and/or
2155 wavefront_reset_to_cleanliness() has already been called
2156 */
2157
2158 if (dev->israw) {
2159 samples_are_from_rom = 1;
2160 } else {
2161 /* XXX is this always true ? */
2162 samples_are_from_rom = 0;
2163 }
2164
2165 if (dev->israw || fx_raw) {
2166 if (wavefront_do_reset (dev)) {
2167 return -1;
2168 }
2169 }
2170 /* Check for FX device, present only on Tropez+ */
2171
2172 dev->has_fx = (snd_wavefront_fx_detect (dev) == 0);
2173
2174 if (dev->has_fx && fx_raw) {
2175 snd_wavefront_fx_start (dev);
2176 }
2177
2178 wavefront_get_sample_status (dev, samples_are_from_rom);
2179 wavefront_get_program_status (dev);
2180 wavefront_get_patch_status (dev);
2181
2182 /* Start normal operation: unreset, master interrupt enabled, no mute
2183 */
2184
2185 outb (0x80|0x40|0x20, dev->control_port);
2186
2187 return (0);
2188}
2189
2190int __init
2191snd_wavefront_detect (snd_wavefront_card_t *card)
2192
2193{
2194 unsigned char rbuf[4], wbuf[4];
2195 snd_wavefront_t *dev = &card->wavefront;
2196
2197 /* returns zero if a WaveFront card is successfully detected.
2198 negative otherwise.
2199 */
2200
2201 dev->israw = 0;
2202 dev->has_fx = 0;
2203 dev->debug = debug_default;
2204 dev->interrupts_are_midi = 0;
2205 dev->irq_cnt = 0;
2206 dev->rom_samples_rdonly = 1;
2207
2208 if (snd_wavefront_cmd (dev, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
2209
2210 dev->fw_version[0] = rbuf[0];
2211 dev->fw_version[1] = rbuf[1];
2212
2213 snd_printk ("firmware %d.%d already loaded.\n",
2214 rbuf[0], rbuf[1]);
2215
2216 /* check that a command actually works */
2217
2218 if (snd_wavefront_cmd (dev, WFC_HARDWARE_VERSION,
2219 rbuf, wbuf) == 0) {
2220 dev->hw_version[0] = rbuf[0];
2221 dev->hw_version[1] = rbuf[1];
2222 } else {
2223 snd_printk ("not raw, but no "
2224 "hardware version!\n");
2225 return -1;
2226 }
2227
2228 if (!wf_raw) {
2229 return 0;
2230 } else {
2231 snd_printk ("reloading firmware as you requested.\n");
2232 dev->israw = 1;
2233 }
2234
2235 } else {
2236
2237 dev->israw = 1;
2238 snd_printk ("no response to firmware probe, assume raw.\n");
2239
2240 }
2241
2242 return 0;
2243}