1 // SPDX-License-Identifier: GPL-2.0-only
3 * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
5 * Copyright (c) 2014-2015 Takashi Sakamoto
10 static int midi_open(struct snd_rawmidi_substream
*substream
)
12 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
15 err
= snd_dg00x_stream_lock_try(dg00x
);
19 mutex_lock(&dg00x
->mutex
);
20 err
= snd_dg00x_stream_reserve_duplex(dg00x
, 0, 0, 0);
22 ++dg00x
->substreams_counter
;
23 err
= snd_dg00x_stream_start_duplex(dg00x
);
25 --dg00x
->substreams_counter
;
27 mutex_unlock(&dg00x
->mutex
);
29 snd_dg00x_stream_lock_release(dg00x
);
34 static int midi_close(struct snd_rawmidi_substream
*substream
)
36 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
38 mutex_lock(&dg00x
->mutex
);
39 --dg00x
->substreams_counter
;
40 snd_dg00x_stream_stop_duplex(dg00x
);
41 mutex_unlock(&dg00x
->mutex
);
43 snd_dg00x_stream_lock_release(dg00x
);
47 static void midi_capture_trigger(struct snd_rawmidi_substream
*substream
,
50 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
54 if (substream
->rmidi
->device
== 0)
55 port
= substream
->number
;
59 spin_lock_irqsave(&dg00x
->lock
, flags
);
62 amdtp_dot_midi_trigger(&dg00x
->tx_stream
, port
, substream
);
64 amdtp_dot_midi_trigger(&dg00x
->tx_stream
, port
, NULL
);
66 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
69 static void midi_playback_trigger(struct snd_rawmidi_substream
*substream
,
72 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
76 if (substream
->rmidi
->device
== 0)
77 port
= substream
->number
;
81 spin_lock_irqsave(&dg00x
->lock
, flags
);
84 amdtp_dot_midi_trigger(&dg00x
->rx_stream
, port
, substream
);
86 amdtp_dot_midi_trigger(&dg00x
->rx_stream
, port
, NULL
);
88 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
91 static void set_substream_names(struct snd_dg00x
*dg00x
,
92 struct snd_rawmidi
*rmidi
, bool is_console
)
94 struct snd_rawmidi_substream
*subs
;
95 struct snd_rawmidi_str
*str
;
98 for (i
= 0; i
< 2; ++i
) {
99 str
= &rmidi
->streams
[i
];
101 list_for_each_entry(subs
, &str
->substreams
, list
) {
103 snprintf(subs
->name
, sizeof(subs
->name
),
105 dg00x
->card
->shortname
,
108 snprintf(subs
->name
, sizeof(subs
->name
),
110 dg00x
->card
->shortname
);
116 static int add_substream_pair(struct snd_dg00x
*dg00x
, unsigned int out_ports
,
117 unsigned int in_ports
, bool is_console
)
119 static const struct snd_rawmidi_ops capture_ops
= {
122 .trigger
= midi_capture_trigger
,
124 static const struct snd_rawmidi_ops playback_ops
= {
127 .trigger
= midi_playback_trigger
,
130 struct snd_rawmidi
*rmidi
;
133 /* Add physical midi ports. */
134 err
= snd_rawmidi_new(dg00x
->card
, dg00x
->card
->driver
, is_console
,
135 out_ports
, in_ports
, &rmidi
);
138 rmidi
->private_data
= dg00x
;
141 label
= "%s control";
144 snprintf(rmidi
->name
, sizeof(rmidi
->name
), label
,
145 dg00x
->card
->shortname
);
147 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
, &playback_ops
);
148 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
, &capture_ops
);
150 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
|
151 SNDRV_RAWMIDI_INFO_OUTPUT
|
152 SNDRV_RAWMIDI_INFO_DUPLEX
;
154 set_substream_names(dg00x
, rmidi
, is_console
);
159 int snd_dg00x_create_midi_devices(struct snd_dg00x
*dg00x
)
163 /* Add physical midi ports. */
164 err
= add_substream_pair(dg00x
, DOT_MIDI_OUT_PORTS
, DOT_MIDI_IN_PORTS
,
169 if (dg00x
->is_console
)
170 err
= add_substream_pair(dg00x
, 1, 1, true);