blob: e55cab6d79c7df91d72b6837def3a1bdb1b6bdca [file] [log] [blame]
Takashi Sakamoto9e796e72017-03-22 21:30:23 +09001/*
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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090015 err = snd_motu_stream_lock_try(motu);
16 if (err < 0)
17 return err;
18
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090019 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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090026 if (err < 0)
27 snd_motu_stream_lock_release(motu);
28
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090029 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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090037 err = snd_motu_stream_lock_try(motu);
38 if (err < 0)
39 return err;
40
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090041 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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090048 if (err < 0)
49 snd_motu_stream_lock_release(motu);
50
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090051 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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090065 snd_motu_stream_lock_release(motu);
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090066 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
Takashi Sakamoto71c37972017-03-22 21:30:24 +090080 snd_motu_stream_lock_release(motu);
Takashi Sakamoto9e796e72017-03-22 21:30:23 +090081 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{
Julia Lawalleb2c1832017-08-15 10:09:54 +0200131 static const struct snd_rawmidi_ops capture_ops = {
Takashi Sakamoto9e796e72017-03-22 21:30:23 +0900132 .open = midi_capture_open,
133 .close = midi_capture_close,
134 .trigger = midi_capture_trigger,
135 };
Julia Lawalleb2c1832017-08-15 10:09:54 +0200136 static const struct snd_rawmidi_ops playback_ops = {
Takashi Sakamoto9e796e72017-03-22 21:30:23 +0900137 .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}