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