1 // SPDX-License-Identifier: GPL-2.0-only
3 * oxfw_midi.c - a part of driver for OXFW970/971 based devices
5 * Copyright (c) 2014 Takashi Sakamoto
10 static int midi_capture_open(struct snd_rawmidi_substream *substream)
12 struct snd_oxfw *oxfw = substream->rmidi->private_data;
15 err = snd_oxfw_stream_lock_try(oxfw);
19 mutex_lock(&oxfw->mutex);
21 oxfw->capture_substreams++;
22 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 0, 0);
24 mutex_unlock(&oxfw->mutex);
27 snd_oxfw_stream_lock_release(oxfw);
32 static int midi_playback_open(struct snd_rawmidi_substream *substream)
34 struct snd_oxfw *oxfw = substream->rmidi->private_data;
37 err = snd_oxfw_stream_lock_try(oxfw);
41 mutex_lock(&oxfw->mutex);
43 oxfw->playback_substreams++;
44 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 0, 0);
46 mutex_unlock(&oxfw->mutex);
49 snd_oxfw_stream_lock_release(oxfw);
54 static int midi_capture_close(struct snd_rawmidi_substream *substream)
56 struct snd_oxfw *oxfw = substream->rmidi->private_data;
58 mutex_lock(&oxfw->mutex);
60 oxfw->capture_substreams--;
61 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream);
63 mutex_unlock(&oxfw->mutex);
65 snd_oxfw_stream_lock_release(oxfw);
69 static int midi_playback_close(struct snd_rawmidi_substream *substream)
71 struct snd_oxfw *oxfw = substream->rmidi->private_data;
73 mutex_lock(&oxfw->mutex);
75 oxfw->playback_substreams--;
76 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream);
78 mutex_unlock(&oxfw->mutex);
80 snd_oxfw_stream_lock_release(oxfw);
84 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
86 struct snd_oxfw *oxfw = substrm->rmidi->private_data;
89 spin_lock_irqsave(&oxfw->lock, flags);
92 amdtp_am824_midi_trigger(&oxfw->tx_stream,
93 substrm->number, substrm);
95 amdtp_am824_midi_trigger(&oxfw->tx_stream,
96 substrm->number, NULL);
98 spin_unlock_irqrestore(&oxfw->lock, flags);
101 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
103 struct snd_oxfw *oxfw = substrm->rmidi->private_data;
106 spin_lock_irqsave(&oxfw->lock, flags);
109 amdtp_am824_midi_trigger(&oxfw->rx_stream,
110 substrm->number, substrm);
112 amdtp_am824_midi_trigger(&oxfw->rx_stream,
113 substrm->number, NULL);
115 spin_unlock_irqrestore(&oxfw->lock, flags);
118 static void set_midi_substream_names(struct snd_oxfw *oxfw,
119 struct snd_rawmidi_str *str)
121 struct snd_rawmidi_substream *subs;
123 list_for_each_entry(subs, &str->substreams, list) {
124 snprintf(subs->name, sizeof(subs->name),
126 oxfw->card->shortname, subs->number + 1);
130 int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
132 static const struct snd_rawmidi_ops capture_ops = {
133 .open = midi_capture_open,
134 .close = midi_capture_close,
135 .trigger = midi_capture_trigger,
137 static const struct snd_rawmidi_ops playback_ops = {
138 .open = midi_playback_open,
139 .close = midi_playback_close,
140 .trigger = midi_playback_trigger,
142 struct snd_rawmidi *rmidi;
143 struct snd_rawmidi_str *str;
146 if (oxfw->midi_input_ports == 0 && oxfw->midi_output_ports == 0)
149 /* create midi ports */
150 err = snd_rawmidi_new(oxfw->card, oxfw->card->driver, 0,
151 oxfw->midi_output_ports, oxfw->midi_input_ports,
156 snprintf(rmidi->name, sizeof(rmidi->name),
157 "%s MIDI", oxfw->card->shortname);
158 rmidi->private_data = oxfw;
160 if (oxfw->midi_input_ports > 0) {
161 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
163 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
166 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
168 set_midi_substream_names(oxfw, str);
171 if (oxfw->midi_output_ports > 0) {
172 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
174 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
177 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
179 set_midi_substream_names(oxfw, str);
182 if ((oxfw->midi_output_ports > 0) && (oxfw->midi_input_ports > 0))
183 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;