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 /* This port is for asynchronous transaction. */
17 if (substream->number == 0)
20 err = snd_dg00x_stream_lock_try(dg00x);
24 mutex_lock(&dg00x->mutex);
25 dg00x->substreams_counter++;
26 err = snd_dg00x_stream_start_duplex(dg00x, 0);
27 mutex_unlock(&dg00x->mutex);
29 snd_dg00x_stream_lock_release(dg00x);
34 static int midi_phys_close(struct snd_rawmidi_substream *substream)
36 struct snd_dg00x *dg00x = substream->rmidi->private_data;
38 /* This port is for asynchronous transaction. */
39 if (substream->number == 0)
42 mutex_lock(&dg00x->mutex);
43 dg00x->substreams_counter--;
44 snd_dg00x_stream_stop_duplex(dg00x);
45 mutex_unlock(&dg00x->mutex);
47 snd_dg00x_stream_lock_release(dg00x);
51 static void midi_phys_capture_trigger(struct snd_rawmidi_substream *substream,
54 struct snd_dg00x *dg00x = substream->rmidi->private_data;
57 spin_lock_irqsave(&dg00x->lock, flags);
59 /* This port is for asynchronous transaction. */
60 if (substream->number == 0) {
62 dg00x->in_control = substream;
64 dg00x->in_control = NULL;
67 amdtp_dot_midi_trigger(&dg00x->tx_stream,
68 substream->number - 1,
71 amdtp_dot_midi_trigger(&dg00x->tx_stream,
72 substream->number - 1, NULL);
75 spin_unlock_irqrestore(&dg00x->lock, flags);
78 static void midi_phys_playback_trigger(struct snd_rawmidi_substream *substream,
81 struct snd_dg00x *dg00x = substream->rmidi->private_data;
84 spin_lock_irqsave(&dg00x->lock, flags);
86 /* This port is for asynchronous transaction. */
87 if (substream->number == 0) {
89 snd_fw_async_midi_port_run(&dg00x->out_control,
93 amdtp_dot_midi_trigger(&dg00x->rx_stream,
94 substream->number - 1,
97 amdtp_dot_midi_trigger(&dg00x->rx_stream,
98 substream->number - 1, NULL);
101 spin_unlock_irqrestore(&dg00x->lock, flags);
104 static struct snd_rawmidi_ops midi_phys_capture_ops = {
105 .open = midi_phys_open,
106 .close = midi_phys_close,
107 .trigger = midi_phys_capture_trigger,
110 static struct snd_rawmidi_ops midi_phys_playback_ops = {
111 .open = midi_phys_open,
112 .close = midi_phys_close,
113 .trigger = midi_phys_playback_trigger,
116 static void set_midi_substream_names(struct snd_dg00x *dg00x,
117 struct snd_rawmidi_str *str)
119 struct snd_rawmidi_substream *subs;
121 list_for_each_entry(subs, &str->substreams, list) {
122 if (subs->number > 0)
123 snprintf(subs->name, sizeof(subs->name),
125 dg00x->card->shortname, subs->number);
127 /* This port is for asynchronous transaction. */
128 snprintf(subs->name, sizeof(subs->name),
130 dg00x->card->shortname);
134 int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
136 struct snd_rawmidi *rmidi;
137 struct snd_rawmidi_str *str;
140 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 0,
141 DOT_MIDI_OUT_PORTS + 1, DOT_MIDI_IN_PORTS + 1, &rmidi);
145 snprintf(rmidi->name, sizeof(rmidi->name),
146 "%s MIDI", dg00x->card->shortname);
147 rmidi->private_data = dg00x;
149 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
150 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
151 &midi_phys_capture_ops);
152 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
153 set_midi_substream_names(dg00x, str);
155 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
156 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
157 &midi_phys_playback_ops);
158 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
159 set_midi_substream_names(dg00x, str);
161 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;