Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/digi00x/digi00x-midi.c
29266 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
4
*
5
* Copyright (c) 2014-2015 Takashi Sakamoto
6
*/
7
8
#include "digi00x.h"
9
10
static int midi_open(struct snd_rawmidi_substream *substream)
11
{
12
struct snd_dg00x *dg00x = substream->rmidi->private_data;
13
int err;
14
15
err = snd_dg00x_stream_lock_try(dg00x);
16
if (err < 0)
17
return err;
18
19
scoped_guard(mutex, &dg00x->mutex) {
20
err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0);
21
if (err >= 0) {
22
++dg00x->substreams_counter;
23
err = snd_dg00x_stream_start_duplex(dg00x);
24
if (err < 0)
25
--dg00x->substreams_counter;
26
}
27
}
28
if (err < 0)
29
snd_dg00x_stream_lock_release(dg00x);
30
31
return err;
32
}
33
34
static int midi_close(struct snd_rawmidi_substream *substream)
35
{
36
struct snd_dg00x *dg00x = substream->rmidi->private_data;
37
38
scoped_guard(mutex, &dg00x->mutex) {
39
--dg00x->substreams_counter;
40
snd_dg00x_stream_stop_duplex(dg00x);
41
}
42
43
snd_dg00x_stream_lock_release(dg00x);
44
return 0;
45
}
46
47
static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
48
int up)
49
{
50
struct snd_dg00x *dg00x = substream->rmidi->private_data;
51
unsigned int port;
52
53
if (substream->rmidi->device == 0)
54
port = substream->number;
55
else
56
port = 2;
57
58
guard(spinlock_irqsave)(&dg00x->lock);
59
60
if (up)
61
amdtp_dot_midi_trigger(&dg00x->tx_stream, port, substream);
62
else
63
amdtp_dot_midi_trigger(&dg00x->tx_stream, port, NULL);
64
}
65
66
static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
67
int up)
68
{
69
struct snd_dg00x *dg00x = substream->rmidi->private_data;
70
unsigned int port;
71
72
if (substream->rmidi->device == 0)
73
port = substream->number;
74
else
75
port = 2;
76
77
guard(spinlock_irqsave)(&dg00x->lock);
78
79
if (up)
80
amdtp_dot_midi_trigger(&dg00x->rx_stream, port, substream);
81
else
82
amdtp_dot_midi_trigger(&dg00x->rx_stream, port, NULL);
83
}
84
85
static void set_substream_names(struct snd_dg00x *dg00x,
86
struct snd_rawmidi *rmidi, bool is_console)
87
{
88
struct snd_rawmidi_substream *subs;
89
struct snd_rawmidi_str *str;
90
int i;
91
92
for (i = 0; i < 2; ++i) {
93
str = &rmidi->streams[i];
94
95
list_for_each_entry(subs, &str->substreams, list) {
96
if (!is_console) {
97
scnprintf(subs->name, sizeof(subs->name),
98
"%s MIDI %d",
99
dg00x->card->shortname,
100
subs->number + 1);
101
} else {
102
scnprintf(subs->name, sizeof(subs->name),
103
"%s control",
104
dg00x->card->shortname);
105
}
106
}
107
}
108
}
109
110
static int add_substream_pair(struct snd_dg00x *dg00x, unsigned int out_ports,
111
unsigned int in_ports, bool is_console)
112
{
113
static const struct snd_rawmidi_ops capture_ops = {
114
.open = midi_open,
115
.close = midi_close,
116
.trigger = midi_capture_trigger,
117
};
118
static const struct snd_rawmidi_ops playback_ops = {
119
.open = midi_open,
120
.close = midi_close,
121
.trigger = midi_playback_trigger,
122
};
123
const char *label;
124
struct snd_rawmidi *rmidi;
125
int err;
126
127
/* Add physical midi ports. */
128
err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, is_console,
129
out_ports, in_ports, &rmidi);
130
if (err < 0)
131
return err;
132
rmidi->private_data = dg00x;
133
134
if (!is_console)
135
label = "%s control";
136
else
137
label = "%s MIDI";
138
snprintf(rmidi->name, sizeof(rmidi->name), label,
139
dg00x->card->shortname);
140
141
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &playback_ops);
142
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &capture_ops);
143
144
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
145
SNDRV_RAWMIDI_INFO_OUTPUT |
146
SNDRV_RAWMIDI_INFO_DUPLEX;
147
148
set_substream_names(dg00x, rmidi, is_console);
149
150
return 0;
151
}
152
153
int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
154
{
155
int err;
156
157
/* Add physical midi ports. */
158
err = add_substream_pair(dg00x, DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS,
159
false);
160
if (err < 0)
161
return err;
162
163
if (dg00x->is_console)
164
err = add_substream_pair(dg00x, 1, 1, true);
165
166
return err;
167
}
168
169