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