1 // SPDX-License-Identifier: GPL-2.0-only
3 * fireworks_midi.c - a part of driver for Fireworks based devices
5 * Copyright (c) 2009-2010 Clemens Ladisch
6 * Copyright (c) 2013-2014 Takashi Sakamoto
10 static int midi_open(struct snd_rawmidi_substream
*substream
)
12 struct snd_efw
*efw
= substream
->rmidi
->private_data
;
15 err
= snd_efw_stream_lock_try(efw
);
19 mutex_lock(&efw
->mutex
);
20 err
= snd_efw_stream_reserve_duplex(efw
, 0, 0, 0);
22 ++efw
->substreams_counter
;
23 err
= snd_efw_stream_start_duplex(efw
);
25 --efw
->substreams_counter
;
27 mutex_unlock(&efw
->mutex
);
29 snd_efw_stream_lock_release(efw
);
34 static int midi_close(struct snd_rawmidi_substream
*substream
)
36 struct snd_efw
*efw
= substream
->rmidi
->private_data
;
38 mutex_lock(&efw
->mutex
);
39 --efw
->substreams_counter
;
40 snd_efw_stream_stop_duplex(efw
);
41 mutex_unlock(&efw
->mutex
);
43 snd_efw_stream_lock_release(efw
);
47 static void midi_capture_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
49 struct snd_efw
*efw
= substrm
->rmidi
->private_data
;
52 spin_lock_irqsave(&efw
->lock
, flags
);
55 amdtp_am824_midi_trigger(&efw
->tx_stream
,
56 substrm
->number
, substrm
);
58 amdtp_am824_midi_trigger(&efw
->tx_stream
,
59 substrm
->number
, NULL
);
61 spin_unlock_irqrestore(&efw
->lock
, flags
);
64 static void midi_playback_trigger(struct snd_rawmidi_substream
*substrm
, int up
)
66 struct snd_efw
*efw
= substrm
->rmidi
->private_data
;
69 spin_lock_irqsave(&efw
->lock
, flags
);
72 amdtp_am824_midi_trigger(&efw
->rx_stream
,
73 substrm
->number
, substrm
);
75 amdtp_am824_midi_trigger(&efw
->rx_stream
,
76 substrm
->number
, NULL
);
78 spin_unlock_irqrestore(&efw
->lock
, flags
);
81 static void set_midi_substream_names(struct snd_efw
*efw
,
82 struct snd_rawmidi_str
*str
)
84 struct snd_rawmidi_substream
*subs
;
86 list_for_each_entry(subs
, &str
->substreams
, list
) {
87 scnprintf(subs
->name
, sizeof(subs
->name
),
88 "%s MIDI %d", efw
->card
->shortname
, subs
->number
+ 1);
92 int snd_efw_create_midi_devices(struct snd_efw
*efw
)
94 static const struct snd_rawmidi_ops capture_ops
= {
97 .trigger
= midi_capture_trigger
,
99 static const struct snd_rawmidi_ops playback_ops
= {
102 .trigger
= midi_playback_trigger
,
104 struct snd_rawmidi
*rmidi
;
105 struct snd_rawmidi_str
*str
;
108 /* create midi ports */
109 err
= snd_rawmidi_new(efw
->card
, efw
->card
->driver
, 0,
110 efw
->midi_out_ports
, efw
->midi_in_ports
,
115 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
116 "%s MIDI", efw
->card
->shortname
);
117 rmidi
->private_data
= efw
;
119 if (efw
->midi_in_ports
> 0) {
120 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
122 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
125 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
127 set_midi_substream_names(efw
, str
);
130 if (efw
->midi_out_ports
> 0) {
131 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
133 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
136 str
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
138 set_midi_substream_names(efw
, str
);
141 if ((efw
->midi_out_ports
> 0) && (efw
->midi_in_ports
> 0))
142 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;