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 err
= snd_oxfw_stream_reserve_duplex(oxfw
, &oxfw
->tx_stream
, 0, 0, 0, 0);
23 ++oxfw
->substreams_count
;
24 err
= snd_oxfw_stream_start_duplex(oxfw
);
26 --oxfw
->substreams_count
;
29 mutex_unlock(&oxfw
->mutex
);
32 snd_oxfw_stream_lock_release(oxfw
);
37 static int midi_playback_open(struct snd_rawmidi_substream
*substream
)
39 struct snd_oxfw
*oxfw
= substream
->rmidi
->private_data
;
42 err
= snd_oxfw_stream_lock_try(oxfw
);
46 mutex_lock(&oxfw
->mutex
);
48 err
= snd_oxfw_stream_reserve_duplex(oxfw
, &oxfw
->rx_stream
, 0, 0, 0, 0);
50 ++oxfw
->substreams_count
;
51 err
= snd_oxfw_stream_start_duplex(oxfw
);
54 mutex_unlock(&oxfw
->mutex
);
57 snd_oxfw_stream_lock_release(oxfw
);
62 static int midi_capture_close(struct snd_rawmidi_substream
*substream
)
64 struct snd_oxfw
*oxfw
= substream
->rmidi
->private_data
;
66 mutex_lock(&oxfw
->mutex
);
68 --oxfw
->substreams_count
;
69 snd_oxfw_stream_stop_duplex(oxfw
);
71 mutex_unlock(&oxfw
->mutex
);
73 snd_oxfw_stream_lock_release(oxfw
);
77 static int midi_playback_close(struct snd_rawmidi_substream
*substream
)
79 struct snd_oxfw
*oxfw
= substream
->rmidi
->private_data
;
81 mutex_lock(&oxfw
->mutex
);
83 --oxfw
->substreams_count
;
84 snd_oxfw_stream_stop_duplex(oxfw
);
86 mutex_unlock(&oxfw
->mutex
);
88 snd_oxfw_stream_lock_release(oxfw
);
92 static void midi_capture_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
94 struct snd_oxfw
*oxfw
= substrm
->rmidi
->private_data
;
97 spin_lock_irqsave(&oxfw
->lock
, flags
);
100 amdtp_am824_midi_trigger(&oxfw
->tx_stream
,
101 substrm
->number
, substrm
);
103 amdtp_am824_midi_trigger(&oxfw
->tx_stream
,
104 substrm
->number
, NULL
);
106 spin_unlock_irqrestore(&oxfw
->lock
, flags
);
109 static void midi_playback_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
111 struct snd_oxfw
*oxfw
= substrm
->rmidi
->private_data
;
114 spin_lock_irqsave(&oxfw
->lock
, flags
);
117 amdtp_am824_midi_trigger(&oxfw
->rx_stream
,
118 substrm
->number
, substrm
);
120 amdtp_am824_midi_trigger(&oxfw
->rx_stream
,
121 substrm
->number
, NULL
);
123 spin_unlock_irqrestore(&oxfw
->lock
, flags
);
126 static void set_midi_substream_names(struct snd_oxfw
*oxfw
,
127 struct snd_rawmidi_str
*str
)
129 struct snd_rawmidi_substream
*subs
;
131 list_for_each_entry(subs
, &str
->substreams
, list
) {
132 snprintf(subs
->name
, sizeof(subs
->name
),
134 oxfw
->card
->shortname
, subs
->number
+ 1);
138 int snd_oxfw_create_midi(struct snd_oxfw
*oxfw
)
140 static const struct snd_rawmidi_ops capture_ops
= {
141 .open
= midi_capture_open
,
142 .close
= midi_capture_close
,
143 .trigger
= midi_capture_trigger
,
145 static const struct snd_rawmidi_ops playback_ops
= {
146 .open
= midi_playback_open
,
147 .close
= midi_playback_close
,
148 .trigger
= midi_playback_trigger
,
150 struct snd_rawmidi
*rmidi
;
151 struct snd_rawmidi_str
*str
;
154 if (oxfw
->midi_input_ports
== 0 && oxfw
->midi_output_ports
== 0)
157 /* create midi ports */
158 err
= snd_rawmidi_new(oxfw
->card
, oxfw
->card
->driver
, 0,
159 oxfw
->midi_output_ports
, oxfw
->midi_input_ports
,
164 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
165 "%s MIDI", oxfw
->card
->shortname
);
166 rmidi
->private_data
= oxfw
;
168 if (oxfw
->midi_input_ports
> 0) {
169 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
171 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
174 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
176 set_midi_substream_names(oxfw
, str
);
179 if (oxfw
->midi_output_ports
> 0) {
180 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
182 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
185 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
187 set_midi_substream_names(oxfw
, str
);
190 if ((oxfw
->midi_output_ports
> 0) && (oxfw
->midi_input_ports
> 0))
191 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;