1 // SPDX-License-Identifier: GPL-2.0-only
3 * bebob_midi.c - a part of driver for BeBoB based devices
5 * Copyright (c) 2013-2014 Takashi Sakamoto
10 static int midi_open(struct snd_rawmidi_substream
*substream
)
12 struct snd_bebob
*bebob
= substream
->rmidi
->private_data
;
15 err
= snd_bebob_stream_lock_try(bebob
);
19 mutex_lock(&bebob
->mutex
);
20 err
= snd_bebob_stream_reserve_duplex(bebob
, 0, 0, 0);
22 ++bebob
->substreams_counter
;
23 err
= snd_bebob_stream_start_duplex(bebob
);
25 --bebob
->substreams_counter
;
27 mutex_unlock(&bebob
->mutex
);
29 snd_bebob_stream_lock_release(bebob
);
34 static int midi_close(struct snd_rawmidi_substream
*substream
)
36 struct snd_bebob
*bebob
= substream
->rmidi
->private_data
;
38 mutex_lock(&bebob
->mutex
);
39 bebob
->substreams_counter
--;
40 snd_bebob_stream_stop_duplex(bebob
);
41 mutex_unlock(&bebob
->mutex
);
43 snd_bebob_stream_lock_release(bebob
);
47 static void midi_capture_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
49 struct snd_bebob
*bebob
= substrm
->rmidi
->private_data
;
52 spin_lock_irqsave(&bebob
->lock
, flags
);
55 amdtp_am824_midi_trigger(&bebob
->tx_stream
,
56 substrm
->number
, substrm
);
58 amdtp_am824_midi_trigger(&bebob
->tx_stream
,
59 substrm
->number
, NULL
);
61 spin_unlock_irqrestore(&bebob
->lock
, flags
);
64 static void midi_playback_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
66 struct snd_bebob
*bebob
= substrm
->rmidi
->private_data
;
69 spin_lock_irqsave(&bebob
->lock
, flags
);
72 amdtp_am824_midi_trigger(&bebob
->rx_stream
,
73 substrm
->number
, substrm
);
75 amdtp_am824_midi_trigger(&bebob
->rx_stream
,
76 substrm
->number
, NULL
);
78 spin_unlock_irqrestore(&bebob
->lock
, flags
);
81 static void set_midi_substream_names(struct snd_bebob
*bebob
,
82 struct snd_rawmidi_str
*str
)
84 struct snd_rawmidi_substream
*subs
;
86 list_for_each_entry(subs
, &str
->substreams
, list
) {
87 snprintf(subs
->name
, sizeof(subs
->name
),
89 bebob
->card
->shortname
, subs
->number
+ 1);
93 int snd_bebob_create_midi_devices(struct snd_bebob
*bebob
)
95 static const struct snd_rawmidi_ops capture_ops
= {
98 .trigger
= midi_capture_trigger
,
100 static const struct snd_rawmidi_ops playback_ops
= {
103 .trigger
= midi_playback_trigger
,
105 struct snd_rawmidi
*rmidi
;
106 struct snd_rawmidi_str
*str
;
109 /* create midi ports */
110 err
= snd_rawmidi_new(bebob
->card
, bebob
->card
->driver
, 0,
111 bebob
->midi_output_ports
, bebob
->midi_input_ports
,
116 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
117 "%s MIDI", bebob
->card
->shortname
);
118 rmidi
->private_data
= bebob
;
120 if (bebob
->midi_input_ports
> 0) {
121 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
123 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
126 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
128 set_midi_substream_names(bebob
, str
);
131 if (bebob
->midi_output_ports
> 0) {
132 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
134 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
137 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
139 set_midi_substream_names(bebob
, str
);
142 if ((bebob
->midi_output_ports
> 0) && (bebob
->midi_input_ports
> 0))
143 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;