Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/oxfw/oxfw-midi.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* oxfw_midi.c - a part of driver for OXFW970/971 based devices
4
*
5
* Copyright (c) 2014 Takashi Sakamoto
6
*/
7
8
#include "oxfw.h"
9
10
static int midi_capture_open(struct snd_rawmidi_substream *substream)
11
{
12
struct snd_oxfw *oxfw = substream->rmidi->private_data;
13
int err;
14
15
err = snd_oxfw_stream_lock_try(oxfw);
16
if (err < 0)
17
return err;
18
19
mutex_lock(&oxfw->mutex);
20
21
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0);
22
if (err >= 0) {
23
++oxfw->substreams_count;
24
err = snd_oxfw_stream_start_duplex(oxfw);
25
if (err < 0)
26
--oxfw->substreams_count;
27
}
28
29
mutex_unlock(&oxfw->mutex);
30
31
if (err < 0)
32
snd_oxfw_stream_lock_release(oxfw);
33
34
return err;
35
}
36
37
static int midi_playback_open(struct snd_rawmidi_substream *substream)
38
{
39
struct snd_oxfw *oxfw = substream->rmidi->private_data;
40
int err;
41
42
err = snd_oxfw_stream_lock_try(oxfw);
43
if (err < 0)
44
return err;
45
46
mutex_lock(&oxfw->mutex);
47
48
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0);
49
if (err >= 0) {
50
++oxfw->substreams_count;
51
err = snd_oxfw_stream_start_duplex(oxfw);
52
}
53
54
mutex_unlock(&oxfw->mutex);
55
56
if (err < 0)
57
snd_oxfw_stream_lock_release(oxfw);
58
59
return err;
60
}
61
62
static int midi_capture_close(struct snd_rawmidi_substream *substream)
63
{
64
struct snd_oxfw *oxfw = substream->rmidi->private_data;
65
66
mutex_lock(&oxfw->mutex);
67
68
--oxfw->substreams_count;
69
snd_oxfw_stream_stop_duplex(oxfw);
70
71
mutex_unlock(&oxfw->mutex);
72
73
snd_oxfw_stream_lock_release(oxfw);
74
return 0;
75
}
76
77
static int midi_playback_close(struct snd_rawmidi_substream *substream)
78
{
79
struct snd_oxfw *oxfw = substream->rmidi->private_data;
80
81
mutex_lock(&oxfw->mutex);
82
83
--oxfw->substreams_count;
84
snd_oxfw_stream_stop_duplex(oxfw);
85
86
mutex_unlock(&oxfw->mutex);
87
88
snd_oxfw_stream_lock_release(oxfw);
89
return 0;
90
}
91
92
static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
93
{
94
struct snd_oxfw *oxfw = substrm->rmidi->private_data;
95
unsigned long flags;
96
97
spin_lock_irqsave(&oxfw->lock, flags);
98
99
if (up)
100
amdtp_am824_midi_trigger(&oxfw->tx_stream,
101
substrm->number, substrm);
102
else
103
amdtp_am824_midi_trigger(&oxfw->tx_stream,
104
substrm->number, NULL);
105
106
spin_unlock_irqrestore(&oxfw->lock, flags);
107
}
108
109
static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
110
{
111
struct snd_oxfw *oxfw = substrm->rmidi->private_data;
112
unsigned long flags;
113
114
spin_lock_irqsave(&oxfw->lock, flags);
115
116
if (up)
117
amdtp_am824_midi_trigger(&oxfw->rx_stream,
118
substrm->number, substrm);
119
else
120
amdtp_am824_midi_trigger(&oxfw->rx_stream,
121
substrm->number, NULL);
122
123
spin_unlock_irqrestore(&oxfw->lock, flags);
124
}
125
126
static void set_midi_substream_names(struct snd_oxfw *oxfw,
127
struct snd_rawmidi_str *str)
128
{
129
struct snd_rawmidi_substream *subs;
130
131
list_for_each_entry(subs, &str->substreams, list) {
132
scnprintf(subs->name, sizeof(subs->name),
133
"%s MIDI %d",
134
oxfw->card->shortname, subs->number + 1);
135
}
136
}
137
138
int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
139
{
140
static const struct snd_rawmidi_ops capture_ops = {
141
.open = midi_capture_open,
142
.close = midi_capture_close,
143
.trigger = midi_capture_trigger,
144
};
145
static const struct snd_rawmidi_ops playback_ops = {
146
.open = midi_playback_open,
147
.close = midi_playback_close,
148
.trigger = midi_playback_trigger,
149
};
150
struct snd_rawmidi *rmidi;
151
struct snd_rawmidi_str *str;
152
int err;
153
154
if (oxfw->midi_input_ports == 0 && oxfw->midi_output_ports == 0)
155
return 0;
156
157
/* create midi ports */
158
err = snd_rawmidi_new(oxfw->card, oxfw->card->driver, 0,
159
oxfw->midi_output_ports, oxfw->midi_input_ports,
160
&rmidi);
161
if (err < 0)
162
return err;
163
164
snprintf(rmidi->name, sizeof(rmidi->name),
165
"%s MIDI", oxfw->card->shortname);
166
rmidi->private_data = oxfw;
167
168
if (oxfw->midi_input_ports > 0) {
169
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
170
171
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
172
&capture_ops);
173
174
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
175
176
set_midi_substream_names(oxfw, str);
177
}
178
179
if (oxfw->midi_output_ports > 0) {
180
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
181
182
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
183
&playback_ops);
184
185
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
186
187
set_midi_substream_names(oxfw, str);
188
}
189
190
if ((oxfw->midi_output_ports > 0) && (oxfw->midi_input_ports > 0))
191
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
192
193
return 0;
194
}
195
196