Skip to content

Commit ff2c293

Browse files
takaswietiwai
authored andcommitted
ALSA: fireface: add support for MIDI functionality
In previous commit, fireface driver supports unique transaction mechanism for MIDI feature. This commit adds MIDI functionality for userspace applications. As I wrote in a followed commit, user space applications get some requirement from this driver. It should not touch a register to which units transmit MIDI messages. It should configure a register in which MIDI transmission is controlled. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 1917429 commit ff2c293

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

sound/firewire/fireface/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
snd-fireface-objs := ff.o ff-transaction.o
1+
snd-fireface-objs := ff.o ff-transaction.o ff-midi.o
22
obj-$(CONFIG_SND_FIREFACE) += snd-fireface.o

sound/firewire/fireface/ff-midi.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* ff-midi.c - a part of driver for RME Fireface series
3+
*
4+
* Copyright (c) 2015-2017 Takashi Sakamoto
5+
*
6+
* Licensed under the terms of the GNU General Public License, version 2.
7+
*/
8+
9+
#include "ff.h"
10+
11+
static int midi_capture_open(struct snd_rawmidi_substream *substream)
12+
{
13+
/* Do nothing. */
14+
return 0;
15+
}
16+
17+
static int midi_playback_open(struct snd_rawmidi_substream *substream)
18+
{
19+
struct snd_ff *ff = substream->rmidi->private_data;
20+
21+
/* Initialize internal status. */
22+
ff->running_status[substream->number] = 0;
23+
ff->rx_midi_error[substream->number] = false;
24+
25+
ACCESS_ONCE(ff->rx_midi_substreams[substream->number]) = substream;
26+
27+
return 0;
28+
}
29+
30+
static int midi_capture_close(struct snd_rawmidi_substream *substream)
31+
{
32+
/* Do nothing. */
33+
return 0;
34+
}
35+
36+
static int midi_playback_close(struct snd_rawmidi_substream *substream)
37+
{
38+
struct snd_ff *ff = substream->rmidi->private_data;
39+
40+
cancel_work_sync(&ff->rx_midi_work[substream->number]);
41+
ACCESS_ONCE(ff->rx_midi_substreams[substream->number]) = NULL;
42+
43+
return 0;
44+
}
45+
46+
static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
47+
int up)
48+
{
49+
struct snd_ff *ff = substream->rmidi->private_data;
50+
unsigned long flags;
51+
52+
spin_lock_irqsave(&ff->lock, flags);
53+
54+
if (up)
55+
ACCESS_ONCE(ff->tx_midi_substreams[substream->number]) =
56+
substream;
57+
else
58+
ACCESS_ONCE(ff->tx_midi_substreams[substream->number]) = NULL;
59+
60+
spin_unlock_irqrestore(&ff->lock, flags);
61+
}
62+
63+
static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
64+
int up)
65+
{
66+
struct snd_ff *ff = substream->rmidi->private_data;
67+
unsigned long flags;
68+
69+
spin_lock_irqsave(&ff->lock, flags);
70+
71+
if (up || !ff->rx_midi_error[substream->number])
72+
schedule_work(&ff->rx_midi_work[substream->number]);
73+
74+
spin_unlock_irqrestore(&ff->lock, flags);
75+
}
76+
77+
static struct snd_rawmidi_ops midi_capture_ops = {
78+
.open = midi_capture_open,
79+
.close = midi_capture_close,
80+
.trigger = midi_capture_trigger,
81+
};
82+
83+
static struct snd_rawmidi_ops midi_playback_ops = {
84+
.open = midi_playback_open,
85+
.close = midi_playback_close,
86+
.trigger = midi_playback_trigger,
87+
};
88+
89+
static void set_midi_substream_names(struct snd_rawmidi_str *stream,
90+
const char *const name)
91+
{
92+
struct snd_rawmidi_substream *substream;
93+
94+
list_for_each_entry(substream, &stream->substreams, list) {
95+
snprintf(substream->name, sizeof(substream->name),
96+
"%s MIDI %d", name, substream->number + 1);
97+
}
98+
}
99+
100+
int snd_ff_create_midi_devices(struct snd_ff *ff)
101+
{
102+
struct snd_rawmidi *rmidi;
103+
struct snd_rawmidi_str *stream;
104+
int err;
105+
106+
err = snd_rawmidi_new(ff->card, ff->card->driver, 0,
107+
ff->spec->midi_out_ports, ff->spec->midi_in_ports,
108+
&rmidi);
109+
if (err < 0)
110+
return err;
111+
112+
snprintf(rmidi->name, sizeof(rmidi->name),
113+
"%s MIDI", ff->card->shortname);
114+
rmidi->private_data = ff;
115+
116+
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
117+
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
118+
&midi_capture_ops);
119+
stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
120+
set_midi_substream_names(stream, ff->card->shortname);
121+
122+
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
123+
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
124+
&midi_playback_ops);
125+
stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
126+
set_midi_substream_names(stream, ff->card->shortname);
127+
128+
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
129+
130+
return 0;
131+
}

sound/firewire/fireface/ff.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ static void do_registration(struct work_struct *work)
6161

6262
name_card(ff);
6363

64+
err = snd_ff_create_midi_devices(ff);
65+
if (err < 0)
66+
goto error;
67+
6468
err = snd_card_register(ff->card);
6569
if (err < 0)
6670
goto error;
@@ -91,6 +95,7 @@ static int snd_ff_probe(struct fw_unit *unit,
9195
dev_set_drvdata(&unit->device, ff);
9296

9397
mutex_init(&ff->mutex);
98+
spin_lock_init(&ff->lock);
9499

95100
ff->spec = (const struct snd_ff_spec *)entry->driver_data;
96101

sound/firewire/fireface/ff.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct snd_ff {
4747
struct snd_card *card;
4848
struct fw_unit *unit;
4949
struct mutex mutex;
50+
spinlock_t lock;
5051

5152
bool registered;
5253
struct delayed_work dwork;
@@ -98,4 +99,6 @@ int snd_ff_transaction_register(struct snd_ff *ff);
9899
int snd_ff_transaction_reregister(struct snd_ff *ff);
99100
void snd_ff_transaction_unregister(struct snd_ff *ff);
100101

102+
int snd_ff_create_midi_devices(struct snd_ff *ff);
103+
101104
#endif

0 commit comments

Comments
 (0)