1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (C) by Paul Barton-Davis 1998-1999 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) 5*1da177e4SLinus Torvalds * Version 2 (June 1991). See the "COPYING" file distributed with this 6*1da177e4SLinus Torvalds * software for more info. 7*1da177e4SLinus Torvalds */ 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds /* The low level driver for the WaveFront ICS2115 MIDI interface(s) 10*1da177e4SLinus Torvalds * 11*1da177e4SLinus Torvalds * Note that there is also an MPU-401 emulation (actually, a UART-401 12*1da177e4SLinus Torvalds * emulation) on the CS4232 on the Tropez and Tropez Plus. This code 13*1da177e4SLinus Torvalds * has nothing to do with that interface at all. 14*1da177e4SLinus Torvalds * 15*1da177e4SLinus Torvalds * The interface is essentially just a UART-401, but is has the 16*1da177e4SLinus Torvalds * interesting property of supporting what Turtle Beach called 17*1da177e4SLinus Torvalds * "Virtual MIDI" mode. In this mode, there are effectively *two* 18*1da177e4SLinus Torvalds * MIDI buses accessible via the interface, one that is routed 19*1da177e4SLinus Torvalds * solely to/from the external WaveFront synthesizer and the other 20*1da177e4SLinus Torvalds * corresponding to the pin/socket connector used to link external 21*1da177e4SLinus Torvalds * MIDI devices to the board. 22*1da177e4SLinus Torvalds * 23*1da177e4SLinus Torvalds * This driver fully supports this mode, allowing two distinct MIDI 24*1da177e4SLinus Torvalds * busses to be used completely independently, giving 32 channels of 25*1da177e4SLinus Torvalds * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI 26*1da177e4SLinus Torvalds * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1, 27*1da177e4SLinus Torvalds * where `n' is the card number. Note that the device numbers may be 28*1da177e4SLinus Torvalds * something other than 0 and 1 if the CS4232 UART/MPU-401 interface 29*1da177e4SLinus Torvalds * is enabled. 30*1da177e4SLinus Torvalds * 31*1da177e4SLinus Torvalds * Switching between the two is accomplished externally by the driver 32*1da177e4SLinus Torvalds * using the two otherwise unused MIDI bytes. See the code for more details. 33*1da177e4SLinus Torvalds * 34*1da177e4SLinus Torvalds * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c) 35*1da177e4SLinus Torvalds * 36*1da177e4SLinus Torvalds * The main reason to turn off Virtual MIDI mode is when you want to 37*1da177e4SLinus Torvalds * tightly couple the WaveFront synth with an external MIDI 38*1da177e4SLinus Torvalds * device. You won't be able to distinguish the source of any MIDI 39*1da177e4SLinus Torvalds * data except via SysEx ID, but thats probably OK, since for the most 40*1da177e4SLinus Torvalds * part, the WaveFront won't be sending any MIDI data at all. 41*1da177e4SLinus Torvalds * 42*1da177e4SLinus Torvalds * The main reason to turn on Virtual MIDI Mode is to provide two 43*1da177e4SLinus Torvalds * completely independent 16-channel MIDI buses, one to the 44*1da177e4SLinus Torvalds * WaveFront and one to any external MIDI devices. Given the 32 45*1da177e4SLinus Torvalds * voice nature of the WaveFront, its pretty easy to find a use 46*1da177e4SLinus Torvalds * for all 16 channels driving just that synth. 47*1da177e4SLinus Torvalds * 48*1da177e4SLinus Torvalds */ 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds #include <sound/driver.h> 51*1da177e4SLinus Torvalds #include <asm/io.h> 52*1da177e4SLinus Torvalds #include <linux/init.h> 53*1da177e4SLinus Torvalds #include <linux/time.h> 54*1da177e4SLinus Torvalds #include <linux/wait.h> 55*1da177e4SLinus Torvalds #include <sound/core.h> 56*1da177e4SLinus Torvalds #include <sound/snd_wavefront.h> 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds static inline int 59*1da177e4SLinus Torvalds wf_mpu_status (snd_wavefront_midi_t *midi) 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds { 62*1da177e4SLinus Torvalds return inb (midi->mpu_status_port); 63*1da177e4SLinus Torvalds } 64*1da177e4SLinus Torvalds 65*1da177e4SLinus Torvalds static inline int 66*1da177e4SLinus Torvalds input_avail (snd_wavefront_midi_t *midi) 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds { 69*1da177e4SLinus Torvalds return !(wf_mpu_status(midi) & INPUT_AVAIL); 70*1da177e4SLinus Torvalds } 71*1da177e4SLinus Torvalds 72*1da177e4SLinus Torvalds static inline int 73*1da177e4SLinus Torvalds output_ready (snd_wavefront_midi_t *midi) 74*1da177e4SLinus Torvalds 75*1da177e4SLinus Torvalds { 76*1da177e4SLinus Torvalds return !(wf_mpu_status(midi) & OUTPUT_READY); 77*1da177e4SLinus Torvalds } 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds static inline int 80*1da177e4SLinus Torvalds read_data (snd_wavefront_midi_t *midi) 81*1da177e4SLinus Torvalds 82*1da177e4SLinus Torvalds { 83*1da177e4SLinus Torvalds return inb (midi->mpu_data_port); 84*1da177e4SLinus Torvalds } 85*1da177e4SLinus Torvalds 86*1da177e4SLinus Torvalds static inline void 87*1da177e4SLinus Torvalds write_data (snd_wavefront_midi_t *midi, unsigned char byte) 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds { 90*1da177e4SLinus Torvalds outb (byte, midi->mpu_data_port); 91*1da177e4SLinus Torvalds } 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds static snd_wavefront_midi_t * 94*1da177e4SLinus Torvalds get_wavefront_midi (snd_rawmidi_substream_t *substream) 95*1da177e4SLinus Torvalds 96*1da177e4SLinus Torvalds { 97*1da177e4SLinus Torvalds snd_card_t *card; 98*1da177e4SLinus Torvalds snd_wavefront_card_t *acard; 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds if (substream == NULL || substream->rmidi == NULL) 101*1da177e4SLinus Torvalds return NULL; 102*1da177e4SLinus Torvalds 103*1da177e4SLinus Torvalds card = substream->rmidi->card; 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds if (card == NULL) 106*1da177e4SLinus Torvalds return NULL; 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds if (card->private_data == NULL) 109*1da177e4SLinus Torvalds return NULL; 110*1da177e4SLinus Torvalds 111*1da177e4SLinus Torvalds acard = card->private_data; 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds return &acard->wavefront.midi; 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) 117*1da177e4SLinus Torvalds { 118*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi = &card->wavefront.midi; 119*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 120*1da177e4SLinus Torvalds unsigned long flags; 121*1da177e4SLinus Torvalds unsigned char midi_byte; 122*1da177e4SLinus Torvalds int max = 256, mask = 1; 123*1da177e4SLinus Torvalds int timeout; 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds /* Its not OK to try to change the status of "virtuality" of 126*1da177e4SLinus Torvalds the MIDI interface while we're outputting stuff. See 127*1da177e4SLinus Torvalds snd_wavefront_midi_{enable,disable}_virtual () for the 128*1da177e4SLinus Torvalds other half of this. 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds The first loop attempts to flush any data from the 131*1da177e4SLinus Torvalds current output device, and then the second 132*1da177e4SLinus Torvalds emits the switch byte (if necessary), and starts 133*1da177e4SLinus Torvalds outputting data for the output device currently in use. 134*1da177e4SLinus Torvalds */ 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds if (midi->substream_output[midi->output_mpu] == NULL) { 137*1da177e4SLinus Torvalds goto __second; 138*1da177e4SLinus Torvalds } 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds while (max > 0) { 141*1da177e4SLinus Torvalds 142*1da177e4SLinus Torvalds /* XXX fix me - no hard timing loops allowed! */ 143*1da177e4SLinus Torvalds 144*1da177e4SLinus Torvalds for (timeout = 30000; timeout > 0; timeout--) { 145*1da177e4SLinus Torvalds if (output_ready (midi)) 146*1da177e4SLinus Torvalds break; 147*1da177e4SLinus Torvalds } 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 150*1da177e4SLinus Torvalds if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { 151*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 152*1da177e4SLinus Torvalds goto __second; 153*1da177e4SLinus Torvalds } 154*1da177e4SLinus Torvalds if (output_ready (midi)) { 155*1da177e4SLinus Torvalds if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { 156*1da177e4SLinus Torvalds if (!midi->isvirtual || 157*1da177e4SLinus Torvalds (midi_byte != WF_INTERNAL_SWITCH && 158*1da177e4SLinus Torvalds midi_byte != WF_EXTERNAL_SWITCH)) 159*1da177e4SLinus Torvalds write_data(midi, midi_byte); 160*1da177e4SLinus Torvalds max--; 161*1da177e4SLinus Torvalds } else { 162*1da177e4SLinus Torvalds if (midi->istimer) { 163*1da177e4SLinus Torvalds if (--midi->istimer <= 0) 164*1da177e4SLinus Torvalds del_timer(&midi->timer); 165*1da177e4SLinus Torvalds } 166*1da177e4SLinus Torvalds midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 167*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 168*1da177e4SLinus Torvalds goto __second; 169*1da177e4SLinus Torvalds } 170*1da177e4SLinus Torvalds } else { 171*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 172*1da177e4SLinus Torvalds return; 173*1da177e4SLinus Torvalds } 174*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 175*1da177e4SLinus Torvalds } 176*1da177e4SLinus Torvalds 177*1da177e4SLinus Torvalds __second: 178*1da177e4SLinus Torvalds 179*1da177e4SLinus Torvalds if (midi->substream_output[!midi->output_mpu] == NULL) { 180*1da177e4SLinus Torvalds return; 181*1da177e4SLinus Torvalds } 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds while (max > 0) { 184*1da177e4SLinus Torvalds 185*1da177e4SLinus Torvalds /* XXX fix me - no hard timing loops allowed! */ 186*1da177e4SLinus Torvalds 187*1da177e4SLinus Torvalds for (timeout = 30000; timeout > 0; timeout--) { 188*1da177e4SLinus Torvalds if (output_ready (midi)) 189*1da177e4SLinus Torvalds break; 190*1da177e4SLinus Torvalds } 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 193*1da177e4SLinus Torvalds if (!midi->isvirtual) 194*1da177e4SLinus Torvalds mask = 0; 195*1da177e4SLinus Torvalds mpu = midi->output_mpu ^ mask; 196*1da177e4SLinus Torvalds mask = 0; /* don't invert the value from now */ 197*1da177e4SLinus Torvalds if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { 198*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 199*1da177e4SLinus Torvalds return; 200*1da177e4SLinus Torvalds } 201*1da177e4SLinus Torvalds if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) 202*1da177e4SLinus Torvalds goto __timer; 203*1da177e4SLinus Torvalds if (output_ready (midi)) { 204*1da177e4SLinus Torvalds if (mpu != midi->output_mpu) { 205*1da177e4SLinus Torvalds write_data(midi, mpu == internal_mpu ? 206*1da177e4SLinus Torvalds WF_INTERNAL_SWITCH : 207*1da177e4SLinus Torvalds WF_EXTERNAL_SWITCH); 208*1da177e4SLinus Torvalds midi->output_mpu = mpu; 209*1da177e4SLinus Torvalds } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) { 210*1da177e4SLinus Torvalds if (!midi->isvirtual || 211*1da177e4SLinus Torvalds (midi_byte != WF_INTERNAL_SWITCH && 212*1da177e4SLinus Torvalds midi_byte != WF_EXTERNAL_SWITCH)) 213*1da177e4SLinus Torvalds write_data(midi, midi_byte); 214*1da177e4SLinus Torvalds max--; 215*1da177e4SLinus Torvalds } else { 216*1da177e4SLinus Torvalds __timer: 217*1da177e4SLinus Torvalds if (midi->istimer) { 218*1da177e4SLinus Torvalds if (--midi->istimer <= 0) 219*1da177e4SLinus Torvalds del_timer(&midi->timer); 220*1da177e4SLinus Torvalds } 221*1da177e4SLinus Torvalds midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 222*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 223*1da177e4SLinus Torvalds return; 224*1da177e4SLinus Torvalds } 225*1da177e4SLinus Torvalds } else { 226*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 227*1da177e4SLinus Torvalds return; 228*1da177e4SLinus Torvalds } 229*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds 233*1da177e4SLinus Torvalds static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream) 234*1da177e4SLinus Torvalds { 235*1da177e4SLinus Torvalds unsigned long flags; 236*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 237*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 238*1da177e4SLinus Torvalds 239*1da177e4SLinus Torvalds snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 240*1da177e4SLinus Torvalds snd_assert(substream->rmidi->private_data != NULL, return -EIO); 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) 245*1da177e4SLinus Torvalds return -EIO; 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->open, flags); 248*1da177e4SLinus Torvalds midi->mode[mpu] |= MPU401_MODE_INPUT; 249*1da177e4SLinus Torvalds midi->substream_input[mpu] = substream; 250*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->open, flags); 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds return 0; 253*1da177e4SLinus Torvalds } 254*1da177e4SLinus Torvalds 255*1da177e4SLinus Torvalds static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream) 256*1da177e4SLinus Torvalds { 257*1da177e4SLinus Torvalds unsigned long flags; 258*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 259*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 260*1da177e4SLinus Torvalds 261*1da177e4SLinus Torvalds snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 262*1da177e4SLinus Torvalds snd_assert(substream->rmidi->private_data != NULL, return -EIO); 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 265*1da177e4SLinus Torvalds 266*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) 267*1da177e4SLinus Torvalds return -EIO; 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->open, flags); 270*1da177e4SLinus Torvalds midi->mode[mpu] |= MPU401_MODE_OUTPUT; 271*1da177e4SLinus Torvalds midi->substream_output[mpu] = substream; 272*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->open, flags); 273*1da177e4SLinus Torvalds 274*1da177e4SLinus Torvalds return 0; 275*1da177e4SLinus Torvalds } 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream) 278*1da177e4SLinus Torvalds { 279*1da177e4SLinus Torvalds unsigned long flags; 280*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 281*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 284*1da177e4SLinus Torvalds snd_assert(substream->rmidi->private_data != NULL, return -EIO); 285*1da177e4SLinus Torvalds 286*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) 289*1da177e4SLinus Torvalds return -EIO; 290*1da177e4SLinus Torvalds 291*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->open, flags); 292*1da177e4SLinus Torvalds midi->mode[mpu] &= ~MPU401_MODE_INPUT; 293*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->open, flags); 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds return 0; 296*1da177e4SLinus Torvalds } 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream) 299*1da177e4SLinus Torvalds { 300*1da177e4SLinus Torvalds unsigned long flags; 301*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 302*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 305*1da177e4SLinus Torvalds snd_assert(substream->rmidi->private_data != NULL, return -EIO); 306*1da177e4SLinus Torvalds 307*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 308*1da177e4SLinus Torvalds 309*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) 310*1da177e4SLinus Torvalds return -EIO; 311*1da177e4SLinus Torvalds 312*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->open, flags); 313*1da177e4SLinus Torvalds midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; 314*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->open, flags); 315*1da177e4SLinus Torvalds return 0; 316*1da177e4SLinus Torvalds } 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up) 319*1da177e4SLinus Torvalds { 320*1da177e4SLinus Torvalds unsigned long flags; 321*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 322*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 323*1da177e4SLinus Torvalds 324*1da177e4SLinus Torvalds if (substream == NULL || substream->rmidi == NULL) 325*1da177e4SLinus Torvalds return; 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds if (substream->rmidi->private_data == NULL) 328*1da177e4SLinus Torvalds return; 329*1da177e4SLinus Torvalds 330*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) { 333*1da177e4SLinus Torvalds return; 334*1da177e4SLinus Torvalds } 335*1da177e4SLinus Torvalds 336*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 337*1da177e4SLinus Torvalds if (up) { 338*1da177e4SLinus Torvalds midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; 339*1da177e4SLinus Torvalds } else { 340*1da177e4SLinus Torvalds midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; 341*1da177e4SLinus Torvalds } 342*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 343*1da177e4SLinus Torvalds } 344*1da177e4SLinus Torvalds 345*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_timer(unsigned long data) 346*1da177e4SLinus Torvalds { 347*1da177e4SLinus Torvalds snd_wavefront_card_t *card = (snd_wavefront_card_t *)data; 348*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi = &card->wavefront.midi; 349*1da177e4SLinus Torvalds unsigned long flags; 350*1da177e4SLinus Torvalds 351*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 352*1da177e4SLinus Torvalds midi->timer.expires = 1 + jiffies; 353*1da177e4SLinus Torvalds add_timer(&midi->timer); 354*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 355*1da177e4SLinus Torvalds snd_wavefront_midi_output_write(card); 356*1da177e4SLinus Torvalds } 357*1da177e4SLinus Torvalds 358*1da177e4SLinus Torvalds static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) 359*1da177e4SLinus Torvalds { 360*1da177e4SLinus Torvalds unsigned long flags; 361*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 362*1da177e4SLinus Torvalds snd_wavefront_mpu_id mpu; 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds if (substream == NULL || substream->rmidi == NULL) 365*1da177e4SLinus Torvalds return; 366*1da177e4SLinus Torvalds 367*1da177e4SLinus Torvalds if (substream->rmidi->private_data == NULL) 368*1da177e4SLinus Torvalds return; 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvalds mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 371*1da177e4SLinus Torvalds 372*1da177e4SLinus Torvalds if ((midi = get_wavefront_midi (substream)) == NULL) { 373*1da177e4SLinus Torvalds return; 374*1da177e4SLinus Torvalds } 375*1da177e4SLinus Torvalds 376*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 377*1da177e4SLinus Torvalds if (up) { 378*1da177e4SLinus Torvalds if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { 379*1da177e4SLinus Torvalds if (!midi->istimer) { 380*1da177e4SLinus Torvalds init_timer(&midi->timer); 381*1da177e4SLinus Torvalds midi->timer.function = snd_wavefront_midi_output_timer; 382*1da177e4SLinus Torvalds midi->timer.data = (unsigned long) substream->rmidi->card->private_data; 383*1da177e4SLinus Torvalds midi->timer.expires = 1 + jiffies; 384*1da177e4SLinus Torvalds add_timer(&midi->timer); 385*1da177e4SLinus Torvalds } 386*1da177e4SLinus Torvalds midi->istimer++; 387*1da177e4SLinus Torvalds midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; 388*1da177e4SLinus Torvalds } 389*1da177e4SLinus Torvalds } else { 390*1da177e4SLinus Torvalds midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; 391*1da177e4SLinus Torvalds } 392*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds if (up) 395*1da177e4SLinus Torvalds snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); 396*1da177e4SLinus Torvalds } 397*1da177e4SLinus Torvalds 398*1da177e4SLinus Torvalds void 399*1da177e4SLinus Torvalds snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) 400*1da177e4SLinus Torvalds 401*1da177e4SLinus Torvalds { 402*1da177e4SLinus Torvalds unsigned long flags; 403*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 404*1da177e4SLinus Torvalds static snd_rawmidi_substream_t *substream = NULL; 405*1da177e4SLinus Torvalds static int mpu = external_mpu; 406*1da177e4SLinus Torvalds int max = 128; 407*1da177e4SLinus Torvalds unsigned char byte; 408*1da177e4SLinus Torvalds 409*1da177e4SLinus Torvalds midi = &card->wavefront.midi; 410*1da177e4SLinus Torvalds 411*1da177e4SLinus Torvalds if (!input_avail (midi)) { /* not for us */ 412*1da177e4SLinus Torvalds snd_wavefront_midi_output_write(card); 413*1da177e4SLinus Torvalds return; 414*1da177e4SLinus Torvalds } 415*1da177e4SLinus Torvalds 416*1da177e4SLinus Torvalds spin_lock_irqsave (&midi->virtual, flags); 417*1da177e4SLinus Torvalds while (--max) { 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds if (input_avail (midi)) { 420*1da177e4SLinus Torvalds byte = read_data (midi); 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds if (midi->isvirtual) { 423*1da177e4SLinus Torvalds if (byte == WF_EXTERNAL_SWITCH) { 424*1da177e4SLinus Torvalds substream = midi->substream_input[external_mpu]; 425*1da177e4SLinus Torvalds mpu = external_mpu; 426*1da177e4SLinus Torvalds } else if (byte == WF_INTERNAL_SWITCH) { 427*1da177e4SLinus Torvalds substream = midi->substream_output[internal_mpu]; 428*1da177e4SLinus Torvalds mpu = internal_mpu; 429*1da177e4SLinus Torvalds } /* else just leave it as it is */ 430*1da177e4SLinus Torvalds } else { 431*1da177e4SLinus Torvalds substream = midi->substream_input[internal_mpu]; 432*1da177e4SLinus Torvalds mpu = internal_mpu; 433*1da177e4SLinus Torvalds } 434*1da177e4SLinus Torvalds 435*1da177e4SLinus Torvalds if (substream == NULL) { 436*1da177e4SLinus Torvalds continue; 437*1da177e4SLinus Torvalds } 438*1da177e4SLinus Torvalds 439*1da177e4SLinus Torvalds if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { 440*1da177e4SLinus Torvalds snd_rawmidi_receive(substream, &byte, 1); 441*1da177e4SLinus Torvalds } 442*1da177e4SLinus Torvalds } else { 443*1da177e4SLinus Torvalds break; 444*1da177e4SLinus Torvalds } 445*1da177e4SLinus Torvalds } 446*1da177e4SLinus Torvalds spin_unlock_irqrestore (&midi->virtual, flags); 447*1da177e4SLinus Torvalds 448*1da177e4SLinus Torvalds snd_wavefront_midi_output_write(card); 449*1da177e4SLinus Torvalds } 450*1da177e4SLinus Torvalds 451*1da177e4SLinus Torvalds void 452*1da177e4SLinus Torvalds snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card) 453*1da177e4SLinus Torvalds 454*1da177e4SLinus Torvalds { 455*1da177e4SLinus Torvalds unsigned long flags; 456*1da177e4SLinus Torvalds 457*1da177e4SLinus Torvalds spin_lock_irqsave (&card->wavefront.midi.virtual, flags); 458*1da177e4SLinus Torvalds card->wavefront.midi.isvirtual = 1; 459*1da177e4SLinus Torvalds card->wavefront.midi.output_mpu = internal_mpu; 460*1da177e4SLinus Torvalds card->wavefront.midi.input_mpu = internal_mpu; 461*1da177e4SLinus Torvalds spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); 462*1da177e4SLinus Torvalds } 463*1da177e4SLinus Torvalds 464*1da177e4SLinus Torvalds void 465*1da177e4SLinus Torvalds snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) 466*1da177e4SLinus Torvalds 467*1da177e4SLinus Torvalds { 468*1da177e4SLinus Torvalds unsigned long flags; 469*1da177e4SLinus Torvalds 470*1da177e4SLinus Torvalds spin_lock_irqsave (&card->wavefront.midi.virtual, flags); 471*1da177e4SLinus Torvalds // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); 472*1da177e4SLinus Torvalds // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); 473*1da177e4SLinus Torvalds card->wavefront.midi.isvirtual = 0; 474*1da177e4SLinus Torvalds spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); 475*1da177e4SLinus Torvalds } 476*1da177e4SLinus Torvalds 477*1da177e4SLinus Torvalds int __init 478*1da177e4SLinus Torvalds snd_wavefront_midi_start (snd_wavefront_card_t *card) 479*1da177e4SLinus Torvalds 480*1da177e4SLinus Torvalds { 481*1da177e4SLinus Torvalds int ok, i; 482*1da177e4SLinus Torvalds unsigned char rbuf[4], wbuf[4]; 483*1da177e4SLinus Torvalds snd_wavefront_t *dev; 484*1da177e4SLinus Torvalds snd_wavefront_midi_t *midi; 485*1da177e4SLinus Torvalds 486*1da177e4SLinus Torvalds dev = &card->wavefront; 487*1da177e4SLinus Torvalds midi = &dev->midi; 488*1da177e4SLinus Torvalds 489*1da177e4SLinus Torvalds /* The ICS2115 MPU-401 interface doesn't do anything 490*1da177e4SLinus Torvalds until its set into UART mode. 491*1da177e4SLinus Torvalds */ 492*1da177e4SLinus Torvalds 493*1da177e4SLinus Torvalds /* XXX fix me - no hard timing loops allowed! */ 494*1da177e4SLinus Torvalds 495*1da177e4SLinus Torvalds for (i = 0; i < 30000 && !output_ready (midi); i++); 496*1da177e4SLinus Torvalds 497*1da177e4SLinus Torvalds if (!output_ready (midi)) { 498*1da177e4SLinus Torvalds snd_printk ("MIDI interface not ready for command\n"); 499*1da177e4SLinus Torvalds return -1; 500*1da177e4SLinus Torvalds } 501*1da177e4SLinus Torvalds 502*1da177e4SLinus Torvalds /* Any interrupts received from now on 503*1da177e4SLinus Torvalds are owned by the MIDI side of things. 504*1da177e4SLinus Torvalds */ 505*1da177e4SLinus Torvalds 506*1da177e4SLinus Torvalds dev->interrupts_are_midi = 1; 507*1da177e4SLinus Torvalds 508*1da177e4SLinus Torvalds outb (UART_MODE_ON, midi->mpu_command_port); 509*1da177e4SLinus Torvalds 510*1da177e4SLinus Torvalds for (ok = 0, i = 50000; i > 0 && !ok; i--) { 511*1da177e4SLinus Torvalds if (input_avail (midi)) { 512*1da177e4SLinus Torvalds if (read_data (midi) == MPU_ACK) { 513*1da177e4SLinus Torvalds ok = 1; 514*1da177e4SLinus Torvalds break; 515*1da177e4SLinus Torvalds } 516*1da177e4SLinus Torvalds } 517*1da177e4SLinus Torvalds } 518*1da177e4SLinus Torvalds 519*1da177e4SLinus Torvalds if (!ok) { 520*1da177e4SLinus Torvalds snd_printk ("cannot set UART mode for MIDI interface"); 521*1da177e4SLinus Torvalds dev->interrupts_are_midi = 0; 522*1da177e4SLinus Torvalds return -1; 523*1da177e4SLinus Torvalds } 524*1da177e4SLinus Torvalds 525*1da177e4SLinus Torvalds /* Route external MIDI to WaveFront synth (by default) */ 526*1da177e4SLinus Torvalds 527*1da177e4SLinus Torvalds if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { 528*1da177e4SLinus Torvalds snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); 529*1da177e4SLinus Torvalds /* XXX error ? */ 530*1da177e4SLinus Torvalds } 531*1da177e4SLinus Torvalds 532*1da177e4SLinus Torvalds /* Turn on Virtual MIDI, but first *always* turn it off, 533*1da177e4SLinus Torvalds since otherwise consectutive reloads of the driver will 534*1da177e4SLinus Torvalds never cause the hardware to generate the initial "internal" or 535*1da177e4SLinus Torvalds "external" source bytes in the MIDI data stream. This 536*1da177e4SLinus Torvalds is pretty important, since the internal hardware generally will 537*1da177e4SLinus Torvalds be used to generate none or very little MIDI output, and 538*1da177e4SLinus Torvalds thus the only source of MIDI data is actually external. Without 539*1da177e4SLinus Torvalds the switch bytes, the driver will think it all comes from 540*1da177e4SLinus Torvalds the internal interface. Duh. 541*1da177e4SLinus Torvalds */ 542*1da177e4SLinus Torvalds 543*1da177e4SLinus Torvalds if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 544*1da177e4SLinus Torvalds snd_printk ("virtual MIDI mode not disabled\n"); 545*1da177e4SLinus Torvalds return 0; /* We're OK, but missing the external MIDI dev */ 546*1da177e4SLinus Torvalds } 547*1da177e4SLinus Torvalds 548*1da177e4SLinus Torvalds snd_wavefront_midi_enable_virtual (card); 549*1da177e4SLinus Torvalds 550*1da177e4SLinus Torvalds if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { 551*1da177e4SLinus Torvalds snd_printk ("cannot enable virtual MIDI mode.\n"); 552*1da177e4SLinus Torvalds snd_wavefront_midi_disable_virtual (card); 553*1da177e4SLinus Torvalds } 554*1da177e4SLinus Torvalds return 0; 555*1da177e4SLinus Torvalds } 556*1da177e4SLinus Torvalds 557*1da177e4SLinus Torvalds snd_rawmidi_ops_t snd_wavefront_midi_output = 558*1da177e4SLinus Torvalds { 559*1da177e4SLinus Torvalds .open = snd_wavefront_midi_output_open, 560*1da177e4SLinus Torvalds .close = snd_wavefront_midi_output_close, 561*1da177e4SLinus Torvalds .trigger = snd_wavefront_midi_output_trigger, 562*1da177e4SLinus Torvalds }; 563*1da177e4SLinus Torvalds 564*1da177e4SLinus Torvalds snd_rawmidi_ops_t snd_wavefront_midi_input = 565*1da177e4SLinus Torvalds { 566*1da177e4SLinus Torvalds .open = snd_wavefront_midi_input_open, 567*1da177e4SLinus Torvalds .close = snd_wavefront_midi_input_close, 568*1da177e4SLinus Torvalds .trigger = snd_wavefront_midi_input_trigger, 569*1da177e4SLinus Torvalds }; 570*1da177e4SLinus Torvalds 571