linux/sound/firewire/motu/motu-midi.c
<<
>>
Prefs
   1/*
   2 * motu-midi.h - a part of driver for MOTU FireWire series
   3 *
   4 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
   5 *
   6 * Licensed under the terms of the GNU General Public License, version 2.
   7 */
   8#include "motu.h"
   9
  10static int midi_capture_open(struct snd_rawmidi_substream *substream)
  11{
  12        struct snd_motu *motu = substream->rmidi->private_data;
  13        int err;
  14
  15        err = snd_motu_stream_lock_try(motu);
  16        if (err < 0)
  17                return err;
  18
  19        mutex_lock(&motu->mutex);
  20
  21        motu->capture_substreams++;
  22        err = snd_motu_stream_start_duplex(motu, 0);
  23
  24        mutex_unlock(&motu->mutex);
  25
  26        if (err < 0)
  27                snd_motu_stream_lock_release(motu);
  28
  29        return err;
  30}
  31
  32static int midi_playback_open(struct snd_rawmidi_substream *substream)
  33{
  34        struct snd_motu *motu = substream->rmidi->private_data;
  35        int err;
  36
  37        err = snd_motu_stream_lock_try(motu);
  38        if (err < 0)
  39                return err;
  40
  41        mutex_lock(&motu->mutex);
  42
  43        motu->playback_substreams++;
  44        err = snd_motu_stream_start_duplex(motu, 0);
  45
  46        mutex_unlock(&motu->mutex);
  47
  48        if (err < 0)
  49                snd_motu_stream_lock_release(motu);
  50
  51        return err;
  52}
  53
  54static int midi_capture_close(struct snd_rawmidi_substream *substream)
  55{
  56        struct snd_motu *motu = substream->rmidi->private_data;
  57
  58        mutex_lock(&motu->mutex);
  59
  60        motu->capture_substreams--;
  61        snd_motu_stream_stop_duplex(motu);
  62
  63        mutex_unlock(&motu->mutex);
  64
  65        snd_motu_stream_lock_release(motu);
  66        return 0;
  67}
  68
  69static int midi_playback_close(struct snd_rawmidi_substream *substream)
  70{
  71        struct snd_motu *motu = substream->rmidi->private_data;
  72
  73        mutex_lock(&motu->mutex);
  74
  75        motu->playback_substreams--;
  76        snd_motu_stream_stop_duplex(motu);
  77
  78        mutex_unlock(&motu->mutex);
  79
  80        snd_motu_stream_lock_release(motu);
  81        return 0;
  82}
  83
  84static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  85{
  86        struct snd_motu *motu = substrm->rmidi->private_data;
  87        unsigned long flags;
  88
  89        spin_lock_irqsave(&motu->lock, flags);
  90
  91        if (up)
  92                amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
  93                                        substrm);
  94        else
  95                amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
  96                                        NULL);
  97
  98        spin_unlock_irqrestore(&motu->lock, flags);
  99}
 100
 101static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
 102{
 103        struct snd_motu *motu = substrm->rmidi->private_data;
 104        unsigned long flags;
 105
 106        spin_lock_irqsave(&motu->lock, flags);
 107
 108        if (up)
 109                amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
 110                                        substrm);
 111        else
 112                amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
 113                                        NULL);
 114
 115        spin_unlock_irqrestore(&motu->lock, flags);
 116}
 117
 118static void set_midi_substream_names(struct snd_motu *motu,
 119                                     struct snd_rawmidi_str *str)
 120{
 121        struct snd_rawmidi_substream *subs;
 122
 123        list_for_each_entry(subs, &str->substreams, list) {
 124                snprintf(subs->name, sizeof(subs->name),
 125                         "%s MIDI %d", motu->card->shortname, subs->number + 1);
 126        }
 127}
 128
 129int snd_motu_create_midi_devices(struct snd_motu *motu)
 130{
 131        static const struct snd_rawmidi_ops capture_ops = {
 132                .open           = midi_capture_open,
 133                .close          = midi_capture_close,
 134                .trigger        = midi_capture_trigger,
 135        };
 136        static const struct snd_rawmidi_ops playback_ops = {
 137                .open           = midi_playback_open,
 138                .close          = midi_playback_close,
 139                .trigger        = midi_playback_trigger,
 140        };
 141        struct snd_rawmidi *rmidi;
 142        struct snd_rawmidi_str *str;
 143        int err;
 144
 145        /* create midi ports */
 146        err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
 147        if (err < 0)
 148                return err;
 149
 150        snprintf(rmidi->name, sizeof(rmidi->name),
 151                 "%s MIDI", motu->card->shortname);
 152        rmidi->private_data = motu;
 153
 154        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
 155                             SNDRV_RAWMIDI_INFO_OUTPUT |
 156                             SNDRV_RAWMIDI_INFO_DUPLEX;
 157
 158        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 159                            &capture_ops);
 160        str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
 161        set_midi_substream_names(motu, str);
 162
 163        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
 164                            &playback_ops);
 165        str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
 166        set_midi_substream_names(motu, str);
 167
 168        return 0;
 169}
 170