Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/motu/motu-midi.c
29266 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* motu-midi.h - a part of driver for MOTU FireWire series
4
*
5
* Copyright (c) 2015-2017 Takashi Sakamoto <[email protected]>
6
*/
7
#include "motu.h"
8
9
static int midi_open(struct snd_rawmidi_substream *substream)
10
{
11
struct snd_motu *motu = substream->rmidi->private_data;
12
int err;
13
14
err = snd_motu_stream_lock_try(motu);
15
if (err < 0)
16
return err;
17
18
scoped_guard(mutex, &motu->mutex) {
19
err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0);
20
if (err >= 0) {
21
++motu->substreams_counter;
22
err = snd_motu_stream_start_duplex(motu);
23
if (err < 0)
24
--motu->substreams_counter;
25
}
26
}
27
28
if (err < 0)
29
snd_motu_stream_lock_release(motu);
30
31
return err;
32
}
33
34
static int midi_close(struct snd_rawmidi_substream *substream)
35
{
36
struct snd_motu *motu = substream->rmidi->private_data;
37
38
scoped_guard(mutex, &motu->mutex) {
39
--motu->substreams_counter;
40
snd_motu_stream_stop_duplex(motu);
41
}
42
43
snd_motu_stream_lock_release(motu);
44
return 0;
45
}
46
47
static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
48
{
49
struct snd_motu *motu = substrm->rmidi->private_data;
50
51
guard(spinlock_irqsave)(&motu->lock);
52
53
if (up)
54
amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
55
substrm);
56
else
57
amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
58
NULL);
59
}
60
61
static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
62
{
63
struct snd_motu *motu = substrm->rmidi->private_data;
64
65
guard(spinlock_irqsave)(&motu->lock);
66
67
if (up)
68
amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
69
substrm);
70
else
71
amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
72
NULL);
73
}
74
75
static void set_midi_substream_names(struct snd_motu *motu,
76
struct snd_rawmidi_str *str)
77
{
78
struct snd_rawmidi_substream *subs;
79
80
list_for_each_entry(subs, &str->substreams, list) {
81
scnprintf(subs->name, sizeof(subs->name),
82
"%s MIDI %d", motu->card->shortname, subs->number + 1);
83
}
84
}
85
86
int snd_motu_create_midi_devices(struct snd_motu *motu)
87
{
88
static const struct snd_rawmidi_ops capture_ops = {
89
.open = midi_open,
90
.close = midi_close,
91
.trigger = midi_capture_trigger,
92
};
93
static const struct snd_rawmidi_ops playback_ops = {
94
.open = midi_open,
95
.close = midi_close,
96
.trigger = midi_playback_trigger,
97
};
98
struct snd_rawmidi *rmidi;
99
struct snd_rawmidi_str *str;
100
int err;
101
102
/* create midi ports */
103
err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
104
if (err < 0)
105
return err;
106
107
snprintf(rmidi->name, sizeof(rmidi->name),
108
"%s MIDI", motu->card->shortname);
109
rmidi->private_data = motu;
110
111
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
112
SNDRV_RAWMIDI_INFO_OUTPUT |
113
SNDRV_RAWMIDI_INFO_DUPLEX;
114
115
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
116
&capture_ops);
117
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
118
set_midi_substream_names(motu, str);
119
120
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
121
&playback_ops);
122
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
123
set_midi_substream_names(motu, str);
124
125
return 0;
126
}
127
128