Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/motu/motu-midi.c
26424 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
mutex_lock(&motu->mutex);
19
20
err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0);
21
if (err >= 0) {
22
++motu->substreams_counter;
23
err = snd_motu_stream_start_duplex(motu);
24
if (err < 0)
25
--motu->substreams_counter;
26
}
27
28
mutex_unlock(&motu->mutex);
29
30
if (err < 0)
31
snd_motu_stream_lock_release(motu);
32
33
return err;
34
}
35
36
static int midi_close(struct snd_rawmidi_substream *substream)
37
{
38
struct snd_motu *motu = substream->rmidi->private_data;
39
40
mutex_lock(&motu->mutex);
41
42
--motu->substreams_counter;
43
snd_motu_stream_stop_duplex(motu);
44
45
mutex_unlock(&motu->mutex);
46
47
snd_motu_stream_lock_release(motu);
48
return 0;
49
}
50
51
static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
52
{
53
struct snd_motu *motu = substrm->rmidi->private_data;
54
unsigned long flags;
55
56
spin_lock_irqsave(&motu->lock, flags);
57
58
if (up)
59
amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
60
substrm);
61
else
62
amdtp_motu_midi_trigger(&motu->tx_stream, substrm->number,
63
NULL);
64
65
spin_unlock_irqrestore(&motu->lock, flags);
66
}
67
68
static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
69
{
70
struct snd_motu *motu = substrm->rmidi->private_data;
71
unsigned long flags;
72
73
spin_lock_irqsave(&motu->lock, flags);
74
75
if (up)
76
amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
77
substrm);
78
else
79
amdtp_motu_midi_trigger(&motu->rx_stream, substrm->number,
80
NULL);
81
82
spin_unlock_irqrestore(&motu->lock, flags);
83
}
84
85
static void set_midi_substream_names(struct snd_motu *motu,
86
struct snd_rawmidi_str *str)
87
{
88
struct snd_rawmidi_substream *subs;
89
90
list_for_each_entry(subs, &str->substreams, list) {
91
scnprintf(subs->name, sizeof(subs->name),
92
"%s MIDI %d", motu->card->shortname, subs->number + 1);
93
}
94
}
95
96
int snd_motu_create_midi_devices(struct snd_motu *motu)
97
{
98
static const struct snd_rawmidi_ops capture_ops = {
99
.open = midi_open,
100
.close = midi_close,
101
.trigger = midi_capture_trigger,
102
};
103
static const struct snd_rawmidi_ops playback_ops = {
104
.open = midi_open,
105
.close = midi_close,
106
.trigger = midi_playback_trigger,
107
};
108
struct snd_rawmidi *rmidi;
109
struct snd_rawmidi_str *str;
110
int err;
111
112
/* create midi ports */
113
err = snd_rawmidi_new(motu->card, motu->card->driver, 0, 1, 1, &rmidi);
114
if (err < 0)
115
return err;
116
117
snprintf(rmidi->name, sizeof(rmidi->name),
118
"%s MIDI", motu->card->shortname);
119
rmidi->private_data = motu;
120
121
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
122
SNDRV_RAWMIDI_INFO_OUTPUT |
123
SNDRV_RAWMIDI_INFO_DUPLEX;
124
125
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
126
&capture_ops);
127
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
128
set_midi_substream_names(motu, str);
129
130
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
131
&playback_ops);
132
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
133
set_midi_substream_names(motu, str);
134
135
return 0;
136
}
137
138