aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-10-30 13:43:16 -0400
committerTakashi Iwai <tiwai@suse.de>2015-10-30 14:34:44 -0400
commitd1482fb335b8f3f5e667df72b043c5b3d9d03106 (patch)
tree567b9be1b2393584368e7cd40ca9aaa7bc6ca834 /sound/firewire
parentc5fcee0373b390ab8508022951eabd0bd0e06a48 (diff)
ALSA: firewire-digi00x: add another rawmidi character device for MIDI control ports
Digi 002/003 family uses two ways to transfer MIDI messages. They're different mechanisms, while it's better to handle the ways in different ALSA rawmidi character devices because one character device has just a set of operations. This commit adds another rawmidi character device for control MIDI port. As a result, first rawmidi character device is just for MIDI messages transferred by isochronous packets. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/digi00x/digi00x-midi.c104
1 files changed, 50 insertions, 54 deletions
diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c
index 527f4b31f5c6..1a72a382b384 100644
--- a/sound/firewire/digi00x/digi00x-midi.c
+++ b/sound/firewire/digi00x/digi00x-midi.c
@@ -13,10 +13,6 @@ static int midi_phys_open(struct snd_rawmidi_substream *substream)
13 struct snd_dg00x *dg00x = substream->rmidi->private_data; 13 struct snd_dg00x *dg00x = substream->rmidi->private_data;
14 int err; 14 int err;
15 15
16 /* This port is for asynchronous transaction. */
17 if (substream->number == 0)
18 return 0;
19
20 err = snd_dg00x_stream_lock_try(dg00x); 16 err = snd_dg00x_stream_lock_try(dg00x);
21 if (err < 0) 17 if (err < 0)
22 return err; 18 return err;
@@ -35,10 +31,6 @@ static int midi_phys_close(struct snd_rawmidi_substream *substream)
35{ 31{
36 struct snd_dg00x *dg00x = substream->rmidi->private_data; 32 struct snd_dg00x *dg00x = substream->rmidi->private_data;
37 33
38 /* This port is for asynchronous transaction. */
39 if (substream->number == 0)
40 return 0;
41
42 mutex_lock(&dg00x->mutex); 34 mutex_lock(&dg00x->mutex);
43 dg00x->substreams_counter--; 35 dg00x->substreams_counter--;
44 snd_dg00x_stream_stop_duplex(dg00x); 36 snd_dg00x_stream_stop_duplex(dg00x);
@@ -56,21 +48,12 @@ static void midi_phys_capture_trigger(struct snd_rawmidi_substream *substream,
56 48
57 spin_lock_irqsave(&dg00x->lock, flags); 49 spin_lock_irqsave(&dg00x->lock, flags);
58 50
59 /* This port is for asynchronous transaction. */ 51 if (up)
60 if (substream->number == 0) { 52 amdtp_dot_midi_trigger(&dg00x->tx_stream, substream->number,
61 if (up) 53 substream);
62 dg00x->in_control = substream; 54 else
63 else 55 amdtp_dot_midi_trigger(&dg00x->tx_stream, substream->number,
64 dg00x->in_control = NULL; 56 NULL);
65 } else {
66 if (up)
67 amdtp_dot_midi_trigger(&dg00x->tx_stream,
68 substream->number - 1,
69 substream);
70 else
71 amdtp_dot_midi_trigger(&dg00x->tx_stream,
72 substream->number - 1, NULL);
73 }
74 57
75 spin_unlock_irqrestore(&dg00x->lock, flags); 58 spin_unlock_irqrestore(&dg00x->lock, flags);
76} 59}
@@ -83,20 +66,12 @@ static void midi_phys_playback_trigger(struct snd_rawmidi_substream *substream,
83 66
84 spin_lock_irqsave(&dg00x->lock, flags); 67 spin_lock_irqsave(&dg00x->lock, flags);
85 68
86 /* This port is for asynchronous transaction. */ 69 if (up)
87 if (substream->number == 0) { 70 amdtp_dot_midi_trigger(&dg00x->rx_stream, substream->number,
88 if (up) 71 substream);
89 snd_fw_async_midi_port_run(&dg00x->out_control, 72 else
90 substream); 73 amdtp_dot_midi_trigger(&dg00x->rx_stream, substream->number,
91 } else { 74 NULL);
92 if (up)
93 amdtp_dot_midi_trigger(&dg00x->rx_stream,
94 substream->number - 1,
95 substream);
96 else
97 amdtp_dot_midi_trigger(&dg00x->rx_stream,
98 substream->number - 1, NULL);
99 }
100 75
101 spin_unlock_irqrestore(&dg00x->lock, flags); 76 spin_unlock_irqrestore(&dg00x->lock, flags);
102} 77}
@@ -177,15 +152,16 @@ static struct snd_rawmidi_ops midi_ctl_playback_ops = {
177}; 152};
178 153
179static void set_midi_substream_names(struct snd_dg00x *dg00x, 154static void set_midi_substream_names(struct snd_dg00x *dg00x,
180 struct snd_rawmidi_str *str) 155 struct snd_rawmidi_str *str,
156 bool is_ctl)
181{ 157{
182 struct snd_rawmidi_substream *subs; 158 struct snd_rawmidi_substream *subs;
183 159
184 list_for_each_entry(subs, &str->substreams, list) { 160 list_for_each_entry(subs, &str->substreams, list) {
185 if (subs->number > 0) 161 if (!is_ctl)
186 snprintf(subs->name, sizeof(subs->name), 162 snprintf(subs->name, sizeof(subs->name),
187 "%s MIDI %d", 163 "%s MIDI %d",
188 dg00x->card->shortname, subs->number); 164 dg00x->card->shortname, subs->number + 1);
189 else 165 else
190 /* This port is for asynchronous transaction. */ 166 /* This port is for asynchronous transaction. */
191 snprintf(subs->name, sizeof(subs->name), 167 snprintf(subs->name, sizeof(subs->name),
@@ -196,32 +172,52 @@ static void set_midi_substream_names(struct snd_dg00x *dg00x,
196 172
197int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x) 173int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
198{ 174{
199 struct snd_rawmidi *rmidi; 175 struct snd_rawmidi *rmidi[2];
200 struct snd_rawmidi_str *str; 176 struct snd_rawmidi_str *str;
177 unsigned int i;
201 int err; 178 int err;
202 179
180 /* Add physical midi ports. */
203 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 0, 181 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 0,
204 DOT_MIDI_OUT_PORTS + 1, DOT_MIDI_IN_PORTS + 1, &rmidi); 182 DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS, &rmidi[0]);
205 if (err < 0) 183 if (err < 0)
206 return err; 184 return err;
207 185
208 snprintf(rmidi->name, sizeof(rmidi->name), 186 snprintf(rmidi[0]->name, sizeof(rmidi[0]->name),
209 "%s MIDI", dg00x->card->shortname); 187 "%s MIDI", dg00x->card->shortname);
210 rmidi->private_data = dg00x;
211 188
212 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 189 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_INPUT,
213 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
214 &midi_phys_capture_ops); 190 &midi_phys_capture_ops);
215 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; 191 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_OUTPUT,
216 set_midi_substream_names(dg00x, str);
217
218 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
219 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
220 &midi_phys_playback_ops); 192 &midi_phys_playback_ops);
221 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
222 set_midi_substream_names(dg00x, str);
223 193
224 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; 194 /* Add a pair of control midi ports. */
195 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 1,
196 1, 1, &rmidi[1]);
197 if (err < 0)
198 return err;
199
200 snprintf(rmidi[1]->name, sizeof(rmidi[1]->name),
201 "%s control", dg00x->card->shortname);
202
203 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_INPUT,
204 &midi_ctl_capture_ops);
205 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_OUTPUT,
206 &midi_ctl_playback_ops);
207
208 for (i = 0; i < ARRAY_SIZE(rmidi); i++) {
209 rmidi[i]->private_data = dg00x;
210
211 rmidi[i]->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
212 str = &rmidi[i]->streams[SNDRV_RAWMIDI_STREAM_INPUT];
213 set_midi_substream_names(dg00x, str, i);
214
215 rmidi[i]->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
216 str = &rmidi[i]->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
217 set_midi_substream_names(dg00x, str, i);
218
219 rmidi[i]->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
220 }
225 221
226 return 0; 222 return 0;
227} 223}