Commit | Line | Data |
---|---|---|
da607e19 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
9fbfd38b TS |
2 | /* |
3 | * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family | |
4 | * | |
5 | * Copyright (c) 2014-2015 Takashi Sakamoto | |
9fbfd38b TS |
6 | */ |
7 | ||
8 | #include "digi00x.h" | |
9 | ||
0c3f15f3 | 10 | static int midi_open(struct snd_rawmidi_substream *substream) |
9fbfd38b TS |
11 | { |
12 | struct snd_dg00x *dg00x = substream->rmidi->private_data; | |
13 | int err; | |
14 | ||
15 | err = snd_dg00x_stream_lock_try(dg00x); | |
16 | if (err < 0) | |
17 | return err; | |
18 | ||
19 | mutex_lock(&dg00x->mutex); | |
76c4ecbe | 20 | err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0); |
ae8ffbb2 TS |
21 | if (err >= 0) { |
22 | ++dg00x->substreams_counter; | |
23 | err = snd_dg00x_stream_start_duplex(dg00x); | |
64582c56 TS |
24 | if (err < 0) |
25 | --dg00x->substreams_counter; | |
ae8ffbb2 | 26 | } |
9fbfd38b TS |
27 | mutex_unlock(&dg00x->mutex); |
28 | if (err < 0) | |
29 | snd_dg00x_stream_lock_release(dg00x); | |
30 | ||
31 | return err; | |
32 | } | |
33 | ||
0c3f15f3 | 34 | static int midi_close(struct snd_rawmidi_substream *substream) |
9fbfd38b TS |
35 | { |
36 | struct snd_dg00x *dg00x = substream->rmidi->private_data; | |
37 | ||
38 | mutex_lock(&dg00x->mutex); | |
ae8ffbb2 | 39 | --dg00x->substreams_counter; |
9fbfd38b TS |
40 | snd_dg00x_stream_stop_duplex(dg00x); |
41 | mutex_unlock(&dg00x->mutex); | |
42 | ||
43 | snd_dg00x_stream_lock_release(dg00x); | |
44 | return 0; | |
45 | } | |
46 | ||
0c3f15f3 TS |
47 | static void midi_capture_trigger(struct snd_rawmidi_substream *substream, |
48 | int up) | |
9fbfd38b | 49 | { |
5918f962 | 50 | struct snd_dg00x *dg00x = substream->rmidi->private_data; |
0c3f15f3 | 51 | unsigned int port; |
9fbfd38b TS |
52 | unsigned long flags; |
53 | ||
0c3f15f3 TS |
54 | if (substream->rmidi->device == 0) |
55 | port = substream->number; | |
d1482fb3 | 56 | else |
0c3f15f3 | 57 | port = 2; |
9fbfd38b TS |
58 | |
59 | spin_lock_irqsave(&dg00x->lock, flags); | |
60 | ||
d1482fb3 | 61 | if (up) |
0c3f15f3 | 62 | amdtp_dot_midi_trigger(&dg00x->tx_stream, port, substream); |
d1482fb3 | 63 | else |
0c3f15f3 | 64 | amdtp_dot_midi_trigger(&dg00x->tx_stream, port, NULL); |
9fbfd38b TS |
65 | |
66 | spin_unlock_irqrestore(&dg00x->lock, flags); | |
67 | } | |
68 | ||
0c3f15f3 TS |
69 | static void midi_playback_trigger(struct snd_rawmidi_substream *substream, |
70 | int up) | |
c5fcee03 TS |
71 | { |
72 | struct snd_dg00x *dg00x = substream->rmidi->private_data; | |
0c3f15f3 | 73 | unsigned int port; |
c5fcee03 TS |
74 | unsigned long flags; |
75 | ||
0c3f15f3 TS |
76 | if (substream->rmidi->device == 0) |
77 | port = substream->number; | |
c5fcee03 | 78 | else |
0c3f15f3 | 79 | port = 2; |
c5fcee03 TS |
80 | |
81 | spin_lock_irqsave(&dg00x->lock, flags); | |
82 | ||
83 | if (up) | |
0c3f15f3 TS |
84 | amdtp_dot_midi_trigger(&dg00x->rx_stream, port, substream); |
85 | else | |
86 | amdtp_dot_midi_trigger(&dg00x->rx_stream, port, NULL); | |
c5fcee03 TS |
87 | |
88 | spin_unlock_irqrestore(&dg00x->lock, flags); | |
89 | } | |
90 | ||
0c3f15f3 TS |
91 | static void set_substream_names(struct snd_dg00x *dg00x, |
92 | struct snd_rawmidi *rmidi, bool is_console) | |
9fbfd38b TS |
93 | { |
94 | struct snd_rawmidi_substream *subs; | |
0c3f15f3 TS |
95 | struct snd_rawmidi_str *str; |
96 | int i; | |
97 | ||
98 | for (i = 0; i < 2; ++i) { | |
99 | str = &rmidi->streams[i]; | |
100 | ||
101 | list_for_each_entry(subs, &str->substreams, list) { | |
102 | if (!is_console) { | |
103 | snprintf(subs->name, sizeof(subs->name), | |
104 | "%s MIDI %d", | |
105 | dg00x->card->shortname, | |
106 | subs->number + 1); | |
107 | } else { | |
108 | snprintf(subs->name, sizeof(subs->name), | |
109 | "%s control", | |
110 | dg00x->card->shortname); | |
111 | } | |
112 | } | |
9fbfd38b TS |
113 | } |
114 | } | |
115 | ||
0c3f15f3 TS |
116 | static int add_substream_pair(struct snd_dg00x *dg00x, unsigned int out_ports, |
117 | unsigned int in_ports, bool is_console) | |
9fbfd38b | 118 | { |
0c3f15f3 TS |
119 | static const struct snd_rawmidi_ops capture_ops = { |
120 | .open = midi_open, | |
121 | .close = midi_close, | |
122 | .trigger = midi_capture_trigger, | |
a4e86cba | 123 | }; |
0c3f15f3 TS |
124 | static const struct snd_rawmidi_ops playback_ops = { |
125 | .open = midi_open, | |
126 | .close = midi_close, | |
127 | .trigger = midi_playback_trigger, | |
a4e86cba | 128 | }; |
0c3f15f3 TS |
129 | const char *label; |
130 | struct snd_rawmidi *rmidi; | |
9fbfd38b TS |
131 | int err; |
132 | ||
d1482fb3 | 133 | /* Add physical midi ports. */ |
0c3f15f3 TS |
134 | err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, is_console, |
135 | out_ports, in_ports, &rmidi); | |
9fbfd38b TS |
136 | if (err < 0) |
137 | return err; | |
0c3f15f3 | 138 | rmidi->private_data = dg00x; |
9fbfd38b | 139 | |
0c3f15f3 TS |
140 | if (!is_console) |
141 | label = "%s control"; | |
142 | else | |
143 | label = "%s MIDI"; | |
144 | snprintf(rmidi->name, sizeof(rmidi->name), label, | |
145 | dg00x->card->shortname); | |
9fbfd38b | 146 | |
0c3f15f3 TS |
147 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &playback_ops); |
148 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &capture_ops); | |
d1482fb3 | 149 | |
0c3f15f3 TS |
150 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT | |
151 | SNDRV_RAWMIDI_INFO_OUTPUT | | |
152 | SNDRV_RAWMIDI_INFO_DUPLEX; | |
d1482fb3 | 153 | |
0c3f15f3 | 154 | set_substream_names(dg00x, rmidi, is_console); |
d1482fb3 | 155 | |
0c3f15f3 TS |
156 | return 0; |
157 | } | |
d1482fb3 | 158 | |
0c3f15f3 TS |
159 | int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x) |
160 | { | |
161 | int err; | |
d1482fb3 | 162 | |
0c3f15f3 TS |
163 | /* Add physical midi ports. */ |
164 | err = add_substream_pair(dg00x, DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS, | |
165 | false); | |
166 | if (err < 0) | |
167 | return err; | |
d1482fb3 | 168 | |
0c3f15f3 TS |
169 | if (dg00x->is_console) |
170 | err = add_substream_pair(dg00x, 1, 1, true); | |
9fbfd38b | 171 | |
0c3f15f3 | 172 | return err; |
9fbfd38b | 173 | } |