diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2014-04-25 09:45:18 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-05-26 08:30:16 -0400 |
commit | 248b78027d26735eb22f5ee91a400e5eabfea77d (patch) | |
tree | c0059652bb1b659b6d76f37b061e65e642e849b7 | |
parent | ad9697bad78fab4665d93e61c702892e289e1764 (diff) |
ALSA: bebob: Add MIDI interface
This commit adds a functionality to capture/playback MIDI messages.
When no AMDTP streams are running, this module starts AMDTP stream at current
sampling rate for MIDI substream.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/firewire/Kconfig | 1 | ||||
-rw-r--r-- | sound/firewire/bebob/Makefile | 3 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob.c | 7 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob.h | 3 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_midi.c | 148 |
5 files changed, 161 insertions, 1 deletions
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 5539baac9a5d..708d3c81ef87 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -82,6 +82,7 @@ config SND_FIREWORKS | |||
82 | config SND_BEBOB | 82 | config SND_BEBOB |
83 | tristate "BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware" | 83 | tristate "BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware" |
84 | select SND_FIREWIRE_LIB | 84 | select SND_FIREWIRE_LIB |
85 | select SND_RAWMIDI | ||
85 | help | 86 | help |
86 | Say Y here to include support for FireWire devices based | 87 | Say Y here to include support for FireWire devices based |
87 | on BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware: | 88 | on BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware: |
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile index 757c40ef94df..1e39e591540b 100644 --- a/sound/firewire/bebob/Makefile +++ b/sound/firewire/bebob/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob.o | 1 | snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ |
2 | bebob.o | ||
2 | obj-m += snd-bebob.o | 3 | obj-m += snd-bebob.o |
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 0c3f1f6ab670..383df9a22004 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -164,6 +164,13 @@ bebob_probe(struct fw_unit *unit, | |||
164 | 164 | ||
165 | snd_bebob_proc_init(bebob); | 165 | snd_bebob_proc_init(bebob); |
166 | 166 | ||
167 | if ((bebob->midi_input_ports > 0) || | ||
168 | (bebob->midi_output_ports > 0)) { | ||
169 | err = snd_bebob_create_midi_devices(bebob); | ||
170 | if (err < 0) | ||
171 | goto error; | ||
172 | } | ||
173 | |||
167 | err = snd_bebob_stream_init_duplex(bebob); | 174 | err = snd_bebob_stream_init_duplex(bebob); |
168 | if (err < 0) | 175 | if (err < 0) |
169 | goto error; | 176 | goto error; |
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 1247cca04f63..0d53cff8a68d 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <sound/core.h> | 21 | #include <sound/core.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include <sound/info.h> | 23 | #include <sound/info.h> |
24 | #include <sound/rawmidi.h> | ||
24 | 25 | ||
25 | #include "../lib.h" | 26 | #include "../lib.h" |
26 | #include "../fcp.h" | 27 | #include "../fcp.h" |
@@ -174,6 +175,8 @@ void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob); | |||
174 | 175 | ||
175 | void snd_bebob_proc_init(struct snd_bebob *bebob); | 176 | void snd_bebob_proc_init(struct snd_bebob *bebob); |
176 | 177 | ||
178 | int snd_bebob_create_midi_devices(struct snd_bebob *bebob); | ||
179 | |||
177 | #define SND_BEBOB_DEV_ENTRY(vendor, model) \ | 180 | #define SND_BEBOB_DEV_ENTRY(vendor, model) \ |
178 | { \ | 181 | { \ |
179 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ | 182 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ |
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c new file mode 100644 index 000000000000..120a61b90c59 --- /dev/null +++ b/sound/firewire/bebob/bebob_midi.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * bebob_midi.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "bebob.h" | ||
10 | |||
11 | static int midi_capture_open(struct snd_rawmidi_substream *substream) | ||
12 | { | ||
13 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
14 | |||
15 | atomic_inc(&bebob->capture_substreams); | ||
16 | return snd_bebob_stream_start_duplex(bebob, 0); | ||
17 | } | ||
18 | |||
19 | static int midi_playback_open(struct snd_rawmidi_substream *substream) | ||
20 | { | ||
21 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
22 | |||
23 | atomic_inc(&bebob->playback_substreams); | ||
24 | return snd_bebob_stream_start_duplex(bebob, 0); | ||
25 | } | ||
26 | |||
27 | static int midi_capture_close(struct snd_rawmidi_substream *substream) | ||
28 | { | ||
29 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
30 | |||
31 | atomic_dec(&bebob->capture_substreams); | ||
32 | snd_bebob_stream_stop_duplex(bebob); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int midi_playback_close(struct snd_rawmidi_substream *substream) | ||
38 | { | ||
39 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
40 | |||
41 | atomic_dec(&bebob->playback_substreams); | ||
42 | snd_bebob_stream_stop_duplex(bebob); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
48 | { | ||
49 | struct snd_bebob *bebob = substrm->rmidi->private_data; | ||
50 | unsigned long flags; | ||
51 | |||
52 | spin_lock_irqsave(&bebob->lock, flags); | ||
53 | |||
54 | if (up) | ||
55 | amdtp_stream_midi_trigger(&bebob->tx_stream, | ||
56 | substrm->number, substrm); | ||
57 | else | ||
58 | amdtp_stream_midi_trigger(&bebob->tx_stream, | ||
59 | substrm->number, NULL); | ||
60 | |||
61 | spin_unlock_irqrestore(&bebob->lock, flags); | ||
62 | } | ||
63 | |||
64 | static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
65 | { | ||
66 | struct snd_bebob *bebob = substrm->rmidi->private_data; | ||
67 | unsigned long flags; | ||
68 | |||
69 | spin_lock_irqsave(&bebob->lock, flags); | ||
70 | |||
71 | if (up) | ||
72 | amdtp_stream_midi_trigger(&bebob->rx_stream, | ||
73 | substrm->number, substrm); | ||
74 | else | ||
75 | amdtp_stream_midi_trigger(&bebob->rx_stream, | ||
76 | substrm->number, NULL); | ||
77 | |||
78 | spin_unlock_irqrestore(&bebob->lock, flags); | ||
79 | } | ||
80 | |||
81 | static struct snd_rawmidi_ops midi_capture_ops = { | ||
82 | .open = midi_capture_open, | ||
83 | .close = midi_capture_close, | ||
84 | .trigger = midi_capture_trigger, | ||
85 | }; | ||
86 | |||
87 | static struct snd_rawmidi_ops midi_playback_ops = { | ||
88 | .open = midi_playback_open, | ||
89 | .close = midi_playback_close, | ||
90 | .trigger = midi_playback_trigger, | ||
91 | }; | ||
92 | |||
93 | static void set_midi_substream_names(struct snd_bebob *bebob, | ||
94 | struct snd_rawmidi_str *str) | ||
95 | { | ||
96 | struct snd_rawmidi_substream *subs; | ||
97 | |||
98 | list_for_each_entry(subs, &str->substreams, list) { | ||
99 | snprintf(subs->name, sizeof(subs->name), | ||
100 | "%s MIDI %d", | ||
101 | bebob->card->shortname, subs->number + 1); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | int snd_bebob_create_midi_devices(struct snd_bebob *bebob) | ||
106 | { | ||
107 | struct snd_rawmidi *rmidi; | ||
108 | struct snd_rawmidi_str *str; | ||
109 | int err; | ||
110 | |||
111 | /* create midi ports */ | ||
112 | err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0, | ||
113 | bebob->midi_output_ports, bebob->midi_input_ports, | ||
114 | &rmidi); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | |||
118 | snprintf(rmidi->name, sizeof(rmidi->name), | ||
119 | "%s MIDI", bebob->card->shortname); | ||
120 | rmidi->private_data = bebob; | ||
121 | |||
122 | if (bebob->midi_input_ports > 0) { | ||
123 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
124 | |||
125 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
126 | &midi_capture_ops); | ||
127 | |||
128 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; | ||
129 | |||
130 | set_midi_substream_names(bebob, str); | ||
131 | } | ||
132 | |||
133 | if (bebob->midi_output_ports > 0) { | ||
134 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; | ||
135 | |||
136 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
137 | &midi_playback_ops); | ||
138 | |||
139 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; | ||
140 | |||
141 | set_midi_substream_names(bebob, str); | ||
142 | } | ||
143 | |||
144 | if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0)) | ||
145 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | ||
146 | |||
147 | return 0; | ||
148 | } | ||