linux/sound/pci/echoaudio/midi.c
<<
>>
Prefs
   1/****************************************************************************
   2
   3   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
   4   All rights reserved
   5   www.echoaudio.com
   6
   7   This file is part of Echo Digital Audio's generic driver library.
   8
   9   Echo Digital Audio's generic driver library is free software;
  10   you can redistribute it and/or modify it under the terms of
  11   the GNU General Public License as published by the Free Software
  12   Foundation.
  13
  14   This program is distributed in the hope that it will be useful,
  15   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17   GNU General Public License for more details.
  18
  19   You should have received a copy of the GNU General Public License
  20   along with this program; if not, write to the Free Software
  21   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  22   MA  02111-1307, USA.
  23
  24   *************************************************************************
  25
  26 Translation from C++ and adaptation for use in ALSA-Driver
  27 were made by Giuliano Pochini <pochini@shiny.it>
  28
  29****************************************************************************/
  30
  31
  32/******************************************************************************
  33        MIDI lowlevel code
  34******************************************************************************/
  35
  36/* Start and stop Midi input */
  37static int enable_midi_input(struct echoaudio *chip, char enable)
  38{
  39        dev_dbg(chip->card->dev, "enable_midi_input(%d)\n", enable);
  40
  41        if (wait_handshake(chip))
  42                return -EIO;
  43
  44        if (enable) {
  45                chip->mtc_state = MIDI_IN_STATE_NORMAL;
  46                chip->comm_page->flags |=
  47                        cpu_to_le32(DSP_FLAG_MIDI_INPUT);
  48        } else
  49                chip->comm_page->flags &=
  50                        ~cpu_to_le32(DSP_FLAG_MIDI_INPUT);
  51
  52        clear_handshake(chip);
  53        return send_vector(chip, DSP_VC_UPDATE_FLAGS);
  54}
  55
  56
  57
  58/* Send a buffer full of MIDI data to the DSP
  59Returns how many actually written or < 0 on error */
  60static int write_midi(struct echoaudio *chip, u8 *data, int bytes)
  61{
  62        if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE))
  63                return -EINVAL;
  64
  65        if (wait_handshake(chip))
  66                return -EIO;
  67
  68        /* HF4 indicates that it is safe to write MIDI output data */
  69        if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4))
  70                return 0;
  71
  72        chip->comm_page->midi_output[0] = bytes;
  73        memcpy(&chip->comm_page->midi_output[1], data, bytes);
  74        chip->comm_page->midi_out_free_count = 0;
  75        clear_handshake(chip);
  76        send_vector(chip, DSP_VC_MIDI_WRITE);
  77        dev_dbg(chip->card->dev, "write_midi: %d\n", bytes);
  78        return bytes;
  79}
  80
  81
  82
  83/* Run the state machine for MIDI input data
  84MIDI time code sync isn't supported by this code right now, but you still need
  85this state machine to parse the incoming MIDI data stream.  Every time the DSP
  86sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data
  87stream. The DSP sample position is represented as a 32 bit unsigned value,
  88with the high 16 bits first, followed by the low 16 bits. Since these aren't
  89real MIDI bytes, the following logic is needed to skip them. */
  90static inline int mtc_process_data(struct echoaudio *chip, short midi_byte)
  91{
  92        switch (chip->mtc_state) {
  93        case MIDI_IN_STATE_NORMAL:
  94                if (midi_byte == 0xF1)
  95                        chip->mtc_state = MIDI_IN_STATE_TS_HIGH;
  96                break;
  97        case MIDI_IN_STATE_TS_HIGH:
  98                chip->mtc_state = MIDI_IN_STATE_TS_LOW;
  99                return MIDI_IN_SKIP_DATA;
 100                break;
 101        case MIDI_IN_STATE_TS_LOW:
 102                chip->mtc_state = MIDI_IN_STATE_F1_DATA;
 103                return MIDI_IN_SKIP_DATA;
 104                break;
 105        case MIDI_IN_STATE_F1_DATA:
 106                chip->mtc_state = MIDI_IN_STATE_NORMAL;
 107                break;
 108        }
 109        return 0;
 110}
 111
 112
 113
 114/* This function is called from the IRQ handler and it reads the midi data
 115from the DSP's buffer.  It returns the number of bytes received. */
 116static int midi_service_irq(struct echoaudio *chip)
 117{
 118        short int count, midi_byte, i, received;
 119
 120        /* The count is at index 0, followed by actual data */
 121        count = le16_to_cpu(chip->comm_page->midi_input[0]);
 122
 123        if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE))
 124                return 0;
 125
 126        /* Get the MIDI data from the comm page */
 127        i = 1;
 128        received = 0;
 129        for (i = 1; i <= count; i++) {
 130                /* Get the MIDI byte */
 131                midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]);
 132
 133                /* Parse the incoming MIDI stream. The incoming MIDI data
 134                consists of MIDI bytes and timestamps for the MIDI time code
 135                0xF1 bytes. mtc_process_data() is a little state machine that
 136                parses the stream. If you get MIDI_IN_SKIP_DATA back, then
 137                this is a timestamp byte, not a MIDI byte, so don't store it
 138                in the MIDI input buffer. */
 139                if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA)
 140                        continue;
 141
 142                chip->midi_buffer[received++] = (u8)midi_byte;
 143        }
 144
 145        return received;
 146}
 147
 148
 149
 150
 151/******************************************************************************
 152        MIDI interface
 153******************************************************************************/
 154
 155static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream)
 156{
 157        struct echoaudio *chip = substream->rmidi->private_data;
 158
 159        chip->midi_in = substream;
 160        return 0;
 161}
 162
 163
 164
 165static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream,
 166                                        int up)
 167{
 168        struct echoaudio *chip = substream->rmidi->private_data;
 169
 170        if (up != chip->midi_input_enabled) {
 171                spin_lock_irq(&chip->lock);
 172                enable_midi_input(chip, up);
 173                spin_unlock_irq(&chip->lock);
 174                chip->midi_input_enabled = up;
 175        }
 176}
 177
 178
 179
 180static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream)
 181{
 182        struct echoaudio *chip = substream->rmidi->private_data;
 183
 184        chip->midi_in = NULL;
 185        return 0;
 186}
 187
 188
 189
 190static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream)
 191{
 192        struct echoaudio *chip = substream->rmidi->private_data;
 193
 194        chip->tinuse = 0;
 195        chip->midi_full = 0;
 196        chip->midi_out = substream;
 197        return 0;
 198}
 199
 200
 201
 202static void snd_echo_midi_output_write(struct timer_list *t)
 203{
 204        struct echoaudio *chip = from_timer(chip, t, timer);
 205        unsigned long flags;
 206        int bytes, sent, time;
 207        unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1];
 208
 209        /* No interrupts are involved: we have to check at regular intervals
 210        if the card's output buffer has room for new data. */
 211        sent = bytes = 0;
 212        spin_lock_irqsave(&chip->lock, flags);
 213        chip->midi_full = 0;
 214        if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
 215                bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
 216                                                  MIDI_OUT_BUFFER_SIZE - 1);
 217                dev_dbg(chip->card->dev, "Try to send %d bytes...\n", bytes);
 218                sent = write_midi(chip, buf, bytes);
 219                if (sent < 0) {
 220                        dev_err(chip->card->dev,
 221                                "write_midi() error %d\n", sent);
 222                        /* retry later */
 223                        sent = 9000;
 224                        chip->midi_full = 1;
 225                } else if (sent > 0) {
 226                        dev_dbg(chip->card->dev, "%d bytes sent\n", sent);
 227                        snd_rawmidi_transmit_ack(chip->midi_out, sent);
 228                } else {
 229                        /* Buffer is full. DSP's internal buffer is 64 (128 ?)
 230                        bytes long. Let's wait until half of them are sent */
 231                        dev_dbg(chip->card->dev, "Full\n");
 232                        sent = 32;
 233                        chip->midi_full = 1;
 234                }
 235        }
 236
 237        /* We restart the timer only if there is some data left to send */
 238        if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) {
 239                /* The timer will expire slightly after the data has been
 240                   sent */
 241                time = (sent << 3) / 25 + 1;    /* 8/25=0.32ms to send a byte */
 242                mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
 243                dev_dbg(chip->card->dev,
 244                        "Timer armed(%d)\n", ((time * HZ + 999) / 1000));
 245        }
 246        spin_unlock_irqrestore(&chip->lock, flags);
 247}
 248
 249
 250
 251static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream,
 252                                         int up)
 253{
 254        struct echoaudio *chip = substream->rmidi->private_data;
 255
 256        dev_dbg(chip->card->dev, "snd_echo_midi_output_trigger(%d)\n", up);
 257        spin_lock_irq(&chip->lock);
 258        if (up) {
 259                if (!chip->tinuse) {
 260                        timer_setup(&chip->timer, snd_echo_midi_output_write,
 261                                    0);
 262                        chip->tinuse = 1;
 263                }
 264        } else {
 265                if (chip->tinuse) {
 266                        chip->tinuse = 0;
 267                        spin_unlock_irq(&chip->lock);
 268                        del_timer_sync(&chip->timer);
 269                        dev_dbg(chip->card->dev, "Timer removed\n");
 270                        return;
 271                }
 272        }
 273        spin_unlock_irq(&chip->lock);
 274
 275        if (up && !chip->midi_full)
 276                snd_echo_midi_output_write(&chip->timer);
 277}
 278
 279
 280
 281static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
 282{
 283        struct echoaudio *chip = substream->rmidi->private_data;
 284
 285        chip->midi_out = NULL;
 286        return 0;
 287}
 288
 289
 290
 291static const struct snd_rawmidi_ops snd_echo_midi_input = {
 292        .open = snd_echo_midi_input_open,
 293        .close = snd_echo_midi_input_close,
 294        .trigger = snd_echo_midi_input_trigger,
 295};
 296
 297static const struct snd_rawmidi_ops snd_echo_midi_output = {
 298        .open = snd_echo_midi_output_open,
 299        .close = snd_echo_midi_output_close,
 300        .trigger = snd_echo_midi_output_trigger,
 301};
 302
 303
 304
 305/* <--snd_echo_probe() */
 306static int snd_echo_midi_create(struct snd_card *card,
 307                                struct echoaudio *chip)
 308{
 309        int err;
 310
 311        err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, &chip->rmidi);
 312        if (err < 0)
 313                return err;
 314
 315        strcpy(chip->rmidi->name, card->shortname);
 316        chip->rmidi->private_data = chip;
 317
 318        snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 319                            &snd_echo_midi_input);
 320        snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
 321                            &snd_echo_midi_output);
 322
 323        chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
 324                SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
 325        return 0;
 326}
 327