2 * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
4 * Copyright (c) 2014-2015 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 static int midi_phys_open(struct snd_rawmidi_substream
*substream
)
13 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
16 err
= snd_dg00x_stream_lock_try(dg00x
);
20 mutex_lock(&dg00x
->mutex
);
21 dg00x
->substreams_counter
++;
22 err
= snd_dg00x_stream_start_duplex(dg00x
, 0);
23 mutex_unlock(&dg00x
->mutex
);
25 snd_dg00x_stream_lock_release(dg00x
);
30 static int midi_phys_close(struct snd_rawmidi_substream
*substream
)
32 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
34 mutex_lock(&dg00x
->mutex
);
35 dg00x
->substreams_counter
--;
36 snd_dg00x_stream_stop_duplex(dg00x
);
37 mutex_unlock(&dg00x
->mutex
);
39 snd_dg00x_stream_lock_release(dg00x
);
43 static void midi_phys_capture_trigger(struct snd_rawmidi_substream
*substream
,
46 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
49 spin_lock_irqsave(&dg00x
->lock
, flags
);
52 amdtp_dot_midi_trigger(&dg00x
->tx_stream
, substream
->number
,
55 amdtp_dot_midi_trigger(&dg00x
->tx_stream
, substream
->number
,
58 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
61 static void midi_phys_playback_trigger(struct snd_rawmidi_substream
*substream
,
64 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
67 spin_lock_irqsave(&dg00x
->lock
, flags
);
70 amdtp_dot_midi_trigger(&dg00x
->rx_stream
, substream
->number
,
73 amdtp_dot_midi_trigger(&dg00x
->rx_stream
, substream
->number
,
76 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
79 static struct snd_rawmidi_ops midi_phys_capture_ops
= {
80 .open
= midi_phys_open
,
81 .close
= midi_phys_close
,
82 .trigger
= midi_phys_capture_trigger
,
85 static struct snd_rawmidi_ops midi_phys_playback_ops
= {
86 .open
= midi_phys_open
,
87 .close
= midi_phys_close
,
88 .trigger
= midi_phys_playback_trigger
,
91 static int midi_ctl_open(struct snd_rawmidi_substream
*substream
)
97 static int midi_ctl_capture_close(struct snd_rawmidi_substream
*substream
)
103 static int midi_ctl_playback_close(struct snd_rawmidi_substream
*substream
)
105 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
107 snd_fw_async_midi_port_finish(&dg00x
->out_control
);
112 static void midi_ctl_capture_trigger(struct snd_rawmidi_substream
*substream
,
115 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
118 spin_lock_irqsave(&dg00x
->lock
, flags
);
121 dg00x
->in_control
= substream
;
123 dg00x
->in_control
= NULL
;
125 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
128 static void midi_ctl_playback_trigger(struct snd_rawmidi_substream
*substream
,
131 struct snd_dg00x
*dg00x
= substream
->rmidi
->private_data
;
134 spin_lock_irqsave(&dg00x
->lock
, flags
);
137 snd_fw_async_midi_port_run(&dg00x
->out_control
, substream
);
139 spin_unlock_irqrestore(&dg00x
->lock
, flags
);
142 static struct snd_rawmidi_ops midi_ctl_capture_ops
= {
143 .open
= midi_ctl_open
,
144 .close
= midi_ctl_capture_close
,
145 .trigger
= midi_ctl_capture_trigger
,
148 static struct snd_rawmidi_ops midi_ctl_playback_ops
= {
149 .open
= midi_ctl_open
,
150 .close
= midi_ctl_playback_close
,
151 .trigger
= midi_ctl_playback_trigger
,
154 static void set_midi_substream_names(struct snd_dg00x
*dg00x
,
155 struct snd_rawmidi_str
*str
,
158 struct snd_rawmidi_substream
*subs
;
160 list_for_each_entry(subs
, &str
->substreams
, list
) {
162 snprintf(subs
->name
, sizeof(subs
->name
),
164 dg00x
->card
->shortname
, subs
->number
+ 1);
166 /* This port is for asynchronous transaction. */
167 snprintf(subs
->name
, sizeof(subs
->name
),
169 dg00x
->card
->shortname
);
173 int snd_dg00x_create_midi_devices(struct snd_dg00x
*dg00x
)
175 struct snd_rawmidi
*rmidi
[2];
176 struct snd_rawmidi_str
*str
;
180 /* Add physical midi ports. */
181 err
= snd_rawmidi_new(dg00x
->card
, dg00x
->card
->driver
, 0,
182 DOT_MIDI_OUT_PORTS
, DOT_MIDI_IN_PORTS
, &rmidi
[0]);
186 snprintf(rmidi
[0]->name
, sizeof(rmidi
[0]->name
),
187 "%s MIDI", dg00x
->card
->shortname
);
189 snd_rawmidi_set_ops(rmidi
[0], SNDRV_RAWMIDI_STREAM_INPUT
,
190 &midi_phys_capture_ops
);
191 snd_rawmidi_set_ops(rmidi
[0], SNDRV_RAWMIDI_STREAM_OUTPUT
,
192 &midi_phys_playback_ops
);
194 /* Add a pair of control midi ports. */
195 err
= snd_rawmidi_new(dg00x
->card
, dg00x
->card
->driver
, 1,
200 snprintf(rmidi
[1]->name
, sizeof(rmidi
[1]->name
),
201 "%s control", dg00x
->card
->shortname
);
203 snd_rawmidi_set_ops(rmidi
[1], SNDRV_RAWMIDI_STREAM_INPUT
,
204 &midi_ctl_capture_ops
);
205 snd_rawmidi_set_ops(rmidi
[1], SNDRV_RAWMIDI_STREAM_OUTPUT
,
206 &midi_ctl_playback_ops
);
208 for (i
= 0; i
< ARRAY_SIZE(rmidi
); i
++) {
209 rmidi
[i
]->private_data
= dg00x
;
211 rmidi
[i
]->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
212 str
= &rmidi
[i
]->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
213 set_midi_substream_names(dg00x
, str
, i
);
215 rmidi
[i
]->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
216 str
= &rmidi
[i
]->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
217 set_midi_substream_names(dg00x
, str
, i
);
219 rmidi
[i
]->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;