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