aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/fireworks
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 09:45:09 -0400
committerTakashi Iwai <tiwai@suse.de>2014-05-26 08:28:01 -0400
commita63d3ff1059a4d2236521e4fdbafabfc62b4f81a (patch)
tree4598ead1e5c0f3e3b09881d361cd892475be1b88 /sound/firewire/fireworks
parent6a22683e89e2c851f754ebbec0f2a53f2967bc07 (diff)
ALSA: fireworks: Add MIDI interface
This commit adds a functionality to capture/playback MIDI messages. When no AMDTP streams are running, this driver starts AMDTP stream for MIDI stream at current sampling rate. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/fireworks')
-rw-r--r--sound/firewire/fireworks/Makefile3
-rw-r--r--sound/firewire/fireworks/fireworks.c6
-rw-r--r--sound/firewire/fireworks/fireworks.h3
-rw-r--r--sound/firewire/fireworks/fireworks_midi.c147
4 files changed, 158 insertions, 1 deletions
diff --git a/sound/firewire/fireworks/Makefile b/sound/firewire/fireworks/Makefile
index 52bd15e285b0..a2cecc6d8a4a 100644
--- a/sound/firewire/fireworks/Makefile
+++ b/sound/firewire/fireworks/Makefile
@@ -1,3 +1,4 @@
1snd-fireworks-objs := fireworks_transaction.o fireworks_command.o \ 1snd-fireworks-objs := fireworks_transaction.o fireworks_command.o \
2 fireworks_stream.o fireworks_proc.o fireworks.o 2 fireworks_stream.o fireworks_proc.o fireworks_midi.o \
3 fireworks.o
3obj-m += snd-fireworks.o 4obj-m += snd-fireworks.o
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c
index 311e4a6ef0a6..9204c7c56513 100644
--- a/sound/firewire/fireworks/fireworks.c
+++ b/sound/firewire/fireworks/fireworks.c
@@ -226,6 +226,12 @@ efw_probe(struct fw_unit *unit,
226 226
227 snd_efw_proc_init(efw); 227 snd_efw_proc_init(efw);
228 228
229 if (efw->midi_out_ports || efw->midi_in_ports) {
230 err = snd_efw_create_midi_devices(efw);
231 if (err < 0)
232 goto error;
233 }
234
229 err = snd_efw_stream_init_duplex(efw); 235 err = snd_efw_stream_init_duplex(efw);
230 if (err < 0) 236 if (err < 0)
231 goto error; 237 goto error;
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h
index eef7ad89fd4e..d1819696754d 100644
--- a/sound/firewire/fireworks/fireworks.h
+++ b/sound/firewire/fireworks/fireworks.h
@@ -22,6 +22,7 @@
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/pcm.h> 23#include <sound/pcm.h>
24#include <sound/info.h> 24#include <sound/info.h>
25#include <sound/rawmidi.h>
25 26
26#include "../packets-buffer.h" 27#include "../packets-buffer.h"
27#include "../iso-resources.h" 28#include "../iso-resources.h"
@@ -198,6 +199,8 @@ void snd_efw_stream_destroy_duplex(struct snd_efw *efw);
198 199
199void snd_efw_proc_init(struct snd_efw *efw); 200void snd_efw_proc_init(struct snd_efw *efw);
200 201
202int snd_efw_create_midi_devices(struct snd_efw *efw);
203
201#define SND_EFW_DEV_ENTRY(vendor, model) \ 204#define SND_EFW_DEV_ENTRY(vendor, model) \
202{ \ 205{ \
203 .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 206 .match_flags = IEEE1394_MATCH_VENDOR_ID | \
diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c
new file mode 100644
index 000000000000..cbf34e99237f
--- /dev/null
+++ b/sound/firewire/fireworks/fireworks_midi.c
@@ -0,0 +1,147 @@
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
15 atomic_inc(&efw->capture_substreams);
16 return snd_efw_stream_start_duplex(efw, 0);
17}
18
19static int midi_playback_open(struct snd_rawmidi_substream *substream)
20{
21 struct snd_efw *efw = substream->rmidi->private_data;
22
23 atomic_inc(&efw->playback_substreams);
24 return snd_efw_stream_start_duplex(efw, 0);
25}
26
27static int midi_capture_close(struct snd_rawmidi_substream *substream)
28{
29 struct snd_efw *efw = substream->rmidi->private_data;
30
31 atomic_dec(&efw->capture_substreams);
32 snd_efw_stream_stop_duplex(efw);
33
34 return 0;
35}
36
37static int midi_playback_close(struct snd_rawmidi_substream *substream)
38{
39 struct snd_efw *efw = substream->rmidi->private_data;
40
41 atomic_dec(&efw->playback_substreams);
42 snd_efw_stream_stop_duplex(efw);
43
44 return 0;
45}
46
47static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
48{
49 struct snd_efw *efw = substrm->rmidi->private_data;
50 unsigned long flags;
51
52 spin_lock_irqsave(&efw->lock, flags);
53
54 if (up)
55 amdtp_stream_midi_trigger(&efw->tx_stream,
56 substrm->number, substrm);
57 else
58 amdtp_stream_midi_trigger(&efw->tx_stream,
59 substrm->number, NULL);
60
61 spin_unlock_irqrestore(&efw->lock, flags);
62}
63
64static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
65{
66 struct snd_efw *efw = substrm->rmidi->private_data;
67 unsigned long flags;
68
69 spin_lock_irqsave(&efw->lock, flags);
70
71 if (up)
72 amdtp_stream_midi_trigger(&efw->rx_stream,
73 substrm->number, substrm);
74 else
75 amdtp_stream_midi_trigger(&efw->rx_stream,
76 substrm->number, NULL);
77
78 spin_unlock_irqrestore(&efw->lock, flags);
79}
80
81static struct snd_rawmidi_ops midi_capture_ops = {
82 .open = midi_capture_open,
83 .close = midi_capture_close,
84 .trigger = midi_capture_trigger,
85};
86
87static struct snd_rawmidi_ops midi_playback_ops = {
88 .open = midi_playback_open,
89 .close = midi_playback_close,
90 .trigger = midi_playback_trigger,
91};
92
93static void set_midi_substream_names(struct snd_efw *efw,
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", efw->card->shortname, subs->number + 1);
101 }
102}
103
104int snd_efw_create_midi_devices(struct snd_efw *efw)
105{
106 struct snd_rawmidi *rmidi;
107 struct snd_rawmidi_str *str;
108 int err;
109
110 /* create midi ports */
111 err = snd_rawmidi_new(efw->card, efw->card->driver, 0,
112 efw->midi_out_ports, efw->midi_in_ports,
113 &rmidi);
114 if (err < 0)
115 return err;
116
117 snprintf(rmidi->name, sizeof(rmidi->name),
118 "%s MIDI", efw->card->shortname);
119 rmidi->private_data = efw;
120
121 if (efw->midi_in_ports > 0) {
122 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
123
124 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
125 &midi_capture_ops);
126
127 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
128
129 set_midi_substream_names(efw, str);
130 }
131
132 if (efw->midi_out_ports > 0) {
133 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
134
135 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
136 &midi_playback_ops);
137
138 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
139
140 set_midi_substream_names(efw, str);
141 }
142
143 if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))
144 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
145
146 return 0;
147}