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 <asm/io.h> 51#include <linux/init.h> 52#include <linux/time.h> 53#include <linux/wait.h> 54#include <sound/core.h> 55#include <sound/snd_wavefront.h> 56 57static inline int 58wf_mpu_status (snd_wavefront_midi_t *midi) 59 60{ 61 return inb (midi->mpu_status_port); 62} 63 64static inline int 65input_avail (snd_wavefront_midi_t *midi) 66 67{ 68 return !(wf_mpu_status(midi) & INPUT_AVAIL); 69} 70 71static inline int 72output_ready (snd_wavefront_midi_t *midi) 73 74{ 75 return !(wf_mpu_status(midi) & OUTPUT_READY); 76} 77 78static inline int 79read_data (snd_wavefront_midi_t *midi) 80 81{ 82 return inb (midi->mpu_data_port); 83} 84 85static inline void 86write_data (snd_wavefront_midi_t *midi, unsigned char byte) 87 88{ 89 outb (byte, midi->mpu_data_port); 90} 91 92static snd_wavefront_midi_t * 93get_wavefront_midi (struct snd_rawmidi_substream *substream) 94 95{ 96 struct snd_card *card; 97 snd_wavefront_card_t *acard; 98 99 if (substream == NULL || substream->rmidi == NULL) 100 return NULL; 101 102 card = substream->rmidi->card; 103 104 if (card == NULL) 105 return NULL; 106 107 if (card->private_data == NULL) 108 return NULL; 109 110 acard = card->private_data; 111 112 return &acard->wavefront.midi; 113} 114 115static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) 116{ 117 snd_wavefront_midi_t *midi = &card->wavefront.midi; 118 snd_wavefront_mpu_id mpu; 119 unsigned long flags; 120 unsigned char midi_byte; 121 int max = 256, mask = 1; 122 int timeout; 123 124 /* Its not OK to try to change the status of "virtuality" of 125 the MIDI interface while we're outputting stuff. See 126 snd_wavefront_midi_{enable,disable}_virtual () for the 127 other half of this. 128 129 The first loop attempts to flush any data from the 130 current output device, and then the second 131 emits the switch byte (if necessary), and starts 132 outputting data for the output device currently in use. 133 */ 134 135 if (midi->substream_output[midi->output_mpu] == NULL) { 136 goto __second; 137 } 138 139 while (max > 0) { 140 141 142 for (timeout = 30000; timeout > 0; timeout--) { 143 if (output_ready (midi)) 144 break; 145 } 146 147 spin_lock_irqsave (&midi->virtual, flags); 148 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { 149 spin_unlock_irqrestore (&midi->virtual, flags); 150 goto __second; 151 } 152 if (output_ready (midi)) { 153 if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { 154 if (!midi->isvirtual || 155 (midi_byte != WF_INTERNAL_SWITCH && 156 midi_byte != WF_EXTERNAL_SWITCH)) 157 write_data(midi, midi_byte); 158 max--; 159 } else { 160 if (midi->istimer) { 161 if (--midi->istimer <= 0) 162 del_timer(&midi->timer); 163 } 164 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 165 spin_unlock_irqrestore (&midi->virtual, flags); 166 goto __second; 167 } 168 } else { 169 spin_unlock_irqrestore (&midi->virtual, flags); 170 return; 171 } 172 spin_unlock_irqrestore (&midi->virtual, flags); 173 } 174 175 __second: 176 177 if (midi->substream_output[!midi->output_mpu] == NULL) { 178 return; 179 } 180 181 while (max > 0) { 182 183 184 for (timeout = 30000; timeout > 0; timeout--) { 185 if (output_ready (midi)) 186 break; 187 } 188 189 spin_lock_irqsave (&midi->virtual, flags); 190 if (!midi->isvirtual) 191 mask = 0; 192 mpu = midi->output_mpu ^ mask; 193 mask = 0; /* don't invert the value from now */ 194 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { 195 spin_unlock_irqrestore (&midi->virtual, flags); 196 return; 197 } 198 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) 199 goto __timer; 200 if (output_ready (midi)) { 201 if (mpu != midi->output_mpu) { 202 write_data(midi, mpu == internal_mpu ? 203 WF_INTERNAL_SWITCH : 204 WF_EXTERNAL_SWITCH); 205 midi->output_mpu = mpu; 206 } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) { 207 if (!midi->isvirtual || 208 (midi_byte != WF_INTERNAL_SWITCH && 209 midi_byte != WF_EXTERNAL_SWITCH)) 210 write_data(midi, midi_byte); 211 max--; 212 } else { 213 __timer: 214 if (midi->istimer) { 215 if (--midi->istimer <= 0) 216 del_timer(&midi->timer); 217 } 218 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 219 spin_unlock_irqrestore (&midi->virtual, flags); 220 return; 221 } 222 } else { 223 spin_unlock_irqrestore (&midi->virtual, flags); 224 return; 225 } 226 spin_unlock_irqrestore (&midi->virtual, flags); 227 } 228} 229 230static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream) 231{ 232 unsigned long flags; 233 snd_wavefront_midi_t *midi; 234 snd_wavefront_mpu_id mpu; 235 236 if (snd_BUG_ON(!substream || !substream->rmidi)) 237 return -ENXIO; 238 if (snd_BUG_ON(!substream->rmidi->private_data)) 239 return -ENXIO; 240 241 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 242 243 if ((midi = get_wavefront_midi (substream)) == NULL) 244 return -EIO; 245 246 spin_lock_irqsave (&midi->open, flags); 247 midi->mode[mpu] |= MPU401_MODE_INPUT; 248 midi->substream_input[mpu] = substream; 249 spin_unlock_irqrestore (&midi->open, flags); 250 251 return 0; 252} 253 254static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream) 255{ 256 unsigned long flags; 257 snd_wavefront_midi_t *midi; 258 snd_wavefront_mpu_id mpu; 259 260 if (snd_BUG_ON(!substream || !substream->rmidi)) 261 return -ENXIO; 262 if (snd_BUG_ON(!substream->rmidi->private_data)) 263 return -ENXIO; 264 265 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 266 267 if ((midi = get_wavefront_midi (substream)) == NULL) 268 return -EIO; 269 270 spin_lock_irqsave (&midi->open, flags); 271 midi->mode[mpu] |= MPU401_MODE_OUTPUT; 272 midi->substream_output[mpu] = substream; 273 spin_unlock_irqrestore (&midi->open, flags); 274 275 return 0; 276} 277 278static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream) 279{ 280 unsigned long flags; 281 snd_wavefront_midi_t *midi; 282 snd_wavefront_mpu_id mpu; 283 284 if (snd_BUG_ON(!substream || !substream->rmidi)) 285 return -ENXIO; 286 if (snd_BUG_ON(!substream->rmidi->private_data)) 287 return -ENXIO; 288 289 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 290 291 if ((midi = get_wavefront_midi (substream)) == NULL) 292 return -EIO; 293 294 spin_lock_irqsave (&midi->open, flags); 295 midi->mode[mpu] &= ~MPU401_MODE_INPUT; 296 spin_unlock_irqrestore (&midi->open, flags); 297 298 return 0; 299} 300 301static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream) 302{ 303 unsigned long flags; 304 snd_wavefront_midi_t *midi; 305 snd_wavefront_mpu_id mpu; 306 307 if (snd_BUG_ON(!substream || !substream->rmidi)) 308 return -ENXIO; 309 if (snd_BUG_ON(!substream->rmidi->private_data)) 310 return -ENXIO; 311 312 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 313 314 if ((midi = get_wavefront_midi (substream)) == NULL) 315 return -EIO; 316 317 spin_lock_irqsave (&midi->open, flags); 318 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; 319 spin_unlock_irqrestore (&midi->open, flags); 320 return 0; 321} 322 323static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) 324{ 325 unsigned long flags; 326 snd_wavefront_midi_t *midi; 327 snd_wavefront_mpu_id mpu; 328 329 if (substream == NULL || substream->rmidi == NULL) 330 return; 331 332 if (substream->rmidi->private_data == NULL) 333 return; 334 335 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 336 337 if ((midi = get_wavefront_midi (substream)) == NULL) { 338 return; 339 } 340 341 spin_lock_irqsave (&midi->virtual, flags); 342 if (up) { 343 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; 344 } else { 345 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; 346 } 347 spin_unlock_irqrestore (&midi->virtual, flags); 348} 349 350static void snd_wavefront_midi_output_timer(unsigned long data) 351{ 352 snd_wavefront_card_t *card = (snd_wavefront_card_t *)data; 353 snd_wavefront_midi_t *midi = &card->wavefront.midi; 354 unsigned long flags; 355 356 spin_lock_irqsave (&midi->virtual, flags); 357 midi->timer.expires = 1 + jiffies; 358 add_timer(&midi->timer); 359 spin_unlock_irqrestore (&midi->virtual, flags); 360 snd_wavefront_midi_output_write(card); 361} 362 363static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) 364{ 365 unsigned long flags; 366 snd_wavefront_midi_t *midi; 367 snd_wavefront_mpu_id mpu; 368 369 if (substream == NULL || substream->rmidi == NULL) 370 return; 371 372 if (substream->rmidi->private_data == NULL) 373 return; 374 375 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 376 377 if ((midi = get_wavefront_midi (substream)) == NULL) { 378 return; 379 } 380 381 spin_lock_irqsave (&midi->virtual, flags); 382 if (up) { 383 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { 384 if (!midi->istimer) { 385 init_timer(&midi->timer); 386 midi->timer.function = snd_wavefront_midi_output_timer; 387 midi->timer.data = (unsigned long) substream->rmidi->card->private_data; 388 midi->timer.expires = 1 + jiffies; 389 add_timer(&midi->timer); 390 } 391 midi->istimer++; 392 midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; 393 } 394 } else { 395 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 396 } 397 spin_unlock_irqrestore (&midi->virtual, flags); 398 399 if (up) 400 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); 401} 402 403void 404snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) 405 406{ 407 unsigned long flags; 408 snd_wavefront_midi_t *midi; 409 static struct snd_rawmidi_substream *substream = NULL; 410 static int mpu = external_mpu; 411 int max = 128; 412 unsigned char byte; 413 414 midi = &card->wavefront.midi; 415 416 if (!input_avail (midi)) { /* not for us */ 417 snd_wavefront_midi_output_write(card); 418 return; 419 } 420 421 spin_lock_irqsave (&midi->virtual, flags); 422 while (--max) { 423 424 if (input_avail (midi)) { 425 byte = read_data (midi); 426 427 if (midi->isvirtual) { 428 if (byte == WF_EXTERNAL_SWITCH) { 429 substream = midi->substream_input[external_mpu]; 430 mpu = external_mpu; 431 } else if (byte == WF_INTERNAL_SWITCH) { 432 substream = midi->substream_output[internal_mpu]; 433 mpu = internal_mpu; 434 } /* else just leave it as it is */ 435 } else { 436 substream = midi->substream_input[internal_mpu]; 437 mpu = internal_mpu; 438 } 439 440 if (substream == NULL) { 441 continue; 442 } 443 444 if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { 445 snd_rawmidi_receive(substream, &byte, 1); 446 } 447 } else { 448 break; 449 } 450 } 451 spin_unlock_irqrestore (&midi->virtual, flags); 452 453 snd_wavefront_midi_output_write(card); 454} 455 456void 457snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card) 458 459{ 460 unsigned long flags; 461 462 spin_lock_irqsave (&card->wavefront.midi.virtual, flags); 463 card->wavefront.midi.isvirtual = 1; 464 card->wavefront.midi.output_mpu = internal_mpu; 465 card->wavefront.midi.input_mpu = internal_mpu; 466 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); 467} 468 469void 470snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) 471 472{ 473 unsigned long flags; 474 475 spin_lock_irqsave (&card->wavefront.midi.virtual, flags); 476 // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); 477 // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); 478 card->wavefront.midi.isvirtual = 0; 479 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); 480} 481 482int __devinit 483snd_wavefront_midi_start (snd_wavefront_card_t *card) 484 485{ 486 int ok, i; 487 unsigned char rbuf[4], wbuf[4]; 488 snd_wavefront_t *dev; 489 snd_wavefront_midi_t *midi; 490 491 dev = &card->wavefront; 492 midi = &dev->midi; 493 494 /* The ICS2115 MPU-401 interface doesn't do anything 495 until its set into UART mode. 496 */ 497 498 499 for (i = 0; i < 30000 && !output_ready (midi); i++); 500 501 if (!output_ready (midi)) { 502 snd_printk ("MIDI interface not ready for command\n"); 503 return -1; 504 } 505 506 /* Any interrupts received from now on 507 are owned by the MIDI side of things. 508 */ 509 510 dev->interrupts_are_midi = 1; 511 512 outb (UART_MODE_ON, midi->mpu_command_port); 513 514 for (ok = 0, i = 50000; i > 0 && !ok; i--) { 515 if (input_avail (midi)) { 516 if (read_data (midi) == MPU_ACK) { 517 ok = 1; 518 break; 519 } 520 } 521 } 522 523 if (!ok) { 524 snd_printk ("cannot set UART mode for MIDI interface"); 525 dev->interrupts_are_midi = 0; 526 return -1; 527 } 528 529 /* Route external MIDI to WaveFront synth (by default) */ 530 531 if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { 532 snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); 533 } 534 535 /* Turn on Virtual MIDI, but first *always* turn it off, 536 since otherwise consectutive reloads of the driver will 537 never cause the hardware to generate the initial "internal" or 538 "external" source bytes in the MIDI data stream. This 539 is pretty important, since the internal hardware generally will 540 be used to generate none or very little MIDI output, and 541 thus the only source of MIDI data is actually external. Without 542 the switch bytes, the driver will think it all comes from 543 the internal interface. Duh. 544 */ 545 546 if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 547 snd_printk ("virtual MIDI mode not disabled\n"); 548 return 0; /* We're OK, but missing the external MIDI dev */ 549 } 550 551 snd_wavefront_midi_enable_virtual (card); 552 553 if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { 554 snd_printk ("cannot enable virtual MIDI mode.\n"); 555 snd_wavefront_midi_disable_virtual (card); 556 } 557 return 0; 558} 559 560struct snd_rawmidi_ops snd_wavefront_midi_output = 561{ 562 .open = snd_wavefront_midi_output_open, 563 .close = snd_wavefront_midi_output_close, 564 .trigger = snd_wavefront_midi_output_trigger, 565}; 566 567struct snd_rawmidi_ops snd_wavefront_midi_input = 568{ 569 .open = snd_wavefront_midi_input_open, 570 .close = snd_wavefront_midi_input_close, 571 .trigger = snd_wavefront_midi_input_trigger, 572}; 573