1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ff.c - a part of driver for RME Fireface series |
4 | * |
5 | * Copyright (c) 2015-2017 Takashi Sakamoto |
6 | */ |
7 | |
8 | #include "ff.h" |
9 | |
10 | #define OUI_RME 0x000a35 |
11 | |
12 | MODULE_DESCRIPTION("RME Fireface series Driver" ); |
13 | MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>" ); |
14 | MODULE_LICENSE("GPL" ); |
15 | |
16 | static void name_card(struct snd_ff *ff) |
17 | { |
18 | struct fw_device *fw_dev = fw_parent_device(ff->unit); |
19 | static const char *const names[] = { |
20 | [SND_FF_UNIT_VERSION_FF800] = "Fireface800" , |
21 | [SND_FF_UNIT_VERSION_FF400] = "Fireface400" , |
22 | [SND_FF_UNIT_VERSION_UFX] = "FirefaceUFX" , |
23 | [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX" , |
24 | [SND_FF_UNIT_VERSION_802] = "Fireface802" , |
25 | }; |
26 | const char *name; |
27 | |
28 | name = names[ff->unit_version]; |
29 | |
30 | strcpy(p: ff->card->driver, q: "Fireface" ); |
31 | strcpy(p: ff->card->shortname, q: name); |
32 | strcpy(p: ff->card->mixername, q: name); |
33 | snprintf(buf: ff->card->longname, size: sizeof(ff->card->longname), |
34 | fmt: "RME %s, GUID %08x%08x at %s, S%d" , name, |
35 | fw_dev->config_rom[3], fw_dev->config_rom[4], |
36 | dev_name(dev: &ff->unit->device), 100 << fw_dev->max_speed); |
37 | } |
38 | |
39 | static void ff_card_free(struct snd_card *card) |
40 | { |
41 | struct snd_ff *ff = card->private_data; |
42 | |
43 | snd_ff_stream_destroy_duplex(ff); |
44 | snd_ff_transaction_unregister(ff); |
45 | |
46 | kfree(objp: ff->msg_parser); |
47 | |
48 | mutex_destroy(lock: &ff->mutex); |
49 | fw_unit_put(unit: ff->unit); |
50 | } |
51 | |
52 | static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) |
53 | { |
54 | struct snd_card *card; |
55 | struct snd_ff *ff; |
56 | int err; |
57 | |
58 | err = snd_card_new(parent: &unit->device, idx: -1, NULL, THIS_MODULE, extra_size: sizeof(*ff), card_ret: &card); |
59 | if (err < 0) |
60 | return err; |
61 | card->private_free = ff_card_free; |
62 | |
63 | ff = card->private_data; |
64 | ff->unit = fw_unit_get(unit); |
65 | dev_set_drvdata(dev: &unit->device, data: ff); |
66 | ff->card = card; |
67 | |
68 | mutex_init(&ff->mutex); |
69 | spin_lock_init(&ff->lock); |
70 | init_waitqueue_head(&ff->hwdep_wait); |
71 | |
72 | ff->unit_version = entry->version; |
73 | ff->spec = (const struct snd_ff_spec *)entry->driver_data; |
74 | |
75 | err = snd_ff_transaction_register(ff); |
76 | if (err < 0) |
77 | goto error; |
78 | |
79 | name_card(ff); |
80 | |
81 | err = snd_ff_stream_init_duplex(ff); |
82 | if (err < 0) |
83 | goto error; |
84 | |
85 | snd_ff_proc_init(ff); |
86 | |
87 | err = snd_ff_create_midi_devices(ff); |
88 | if (err < 0) |
89 | goto error; |
90 | |
91 | err = snd_ff_create_pcm_devices(ff); |
92 | if (err < 0) |
93 | goto error; |
94 | |
95 | err = snd_ff_create_hwdep_devices(ff); |
96 | if (err < 0) |
97 | goto error; |
98 | |
99 | if (ff->spec->protocol->msg_parser_size > 0) { |
100 | ff->msg_parser = kzalloc(size: ff->spec->protocol->msg_parser_size, GFP_KERNEL); |
101 | if (!ff->msg_parser) { |
102 | err = -ENOMEM; |
103 | goto error; |
104 | } |
105 | } |
106 | |
107 | err = snd_card_register(card); |
108 | if (err < 0) |
109 | goto error; |
110 | |
111 | return 0; |
112 | error: |
113 | snd_card_free(card); |
114 | return err; |
115 | } |
116 | |
117 | static void snd_ff_update(struct fw_unit *unit) |
118 | { |
119 | struct snd_ff *ff = dev_get_drvdata(dev: &unit->device); |
120 | |
121 | snd_ff_transaction_reregister(ff); |
122 | |
123 | snd_ff_stream_update_duplex(ff); |
124 | } |
125 | |
126 | static void snd_ff_remove(struct fw_unit *unit) |
127 | { |
128 | struct snd_ff *ff = dev_get_drvdata(dev: &unit->device); |
129 | |
130 | // Block till all of ALSA character devices are released. |
131 | snd_card_free(card: ff->card); |
132 | } |
133 | |
134 | static const struct snd_ff_spec spec_ff800 = { |
135 | .pcm_capture_channels = {28, 20, 12}, |
136 | .pcm_playback_channels = {28, 20, 12}, |
137 | .midi_in_ports = 1, |
138 | .midi_out_ports = 1, |
139 | .protocol = &snd_ff_protocol_ff800, |
140 | .midi_high_addr = 0x000200000320ull, |
141 | .midi_addr_range = 12, |
142 | .midi_rx_addrs = {0x000080180000ull, 0}, |
143 | }; |
144 | |
145 | static const struct snd_ff_spec spec_ff400 = { |
146 | .pcm_capture_channels = {18, 14, 10}, |
147 | .pcm_playback_channels = {18, 14, 10}, |
148 | .midi_in_ports = 2, |
149 | .midi_out_ports = 2, |
150 | .protocol = &snd_ff_protocol_ff400, |
151 | .midi_high_addr = 0x0000801003f4ull, |
152 | .midi_addr_range = SND_FF_MAXIMIM_MIDI_QUADS * 4, |
153 | .midi_rx_addrs = {0x000080180000ull, 0x000080190000ull}, |
154 | }; |
155 | |
156 | static const struct snd_ff_spec spec_ucx = { |
157 | .pcm_capture_channels = {18, 14, 12}, |
158 | .pcm_playback_channels = {18, 14, 12}, |
159 | .midi_in_ports = 2, |
160 | .midi_out_ports = 2, |
161 | .protocol = &snd_ff_protocol_latter, |
162 | .midi_high_addr = 0xffff00000034ull, |
163 | .midi_addr_range = 0x80, |
164 | .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, |
165 | }; |
166 | |
167 | static const struct snd_ff_spec spec_ufx_802 = { |
168 | .pcm_capture_channels = {30, 22, 14}, |
169 | .pcm_playback_channels = {30, 22, 14}, |
170 | .midi_in_ports = 1, |
171 | .midi_out_ports = 1, |
172 | .protocol = &snd_ff_protocol_latter, |
173 | .midi_high_addr = 0xffff00000034ull, |
174 | .midi_addr_range = 0x80, |
175 | .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, |
176 | }; |
177 | |
178 | static const struct ieee1394_device_id snd_ff_id_table[] = { |
179 | /* Fireface 800 */ |
180 | { |
181 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
182 | IEEE1394_MATCH_SPECIFIER_ID | |
183 | IEEE1394_MATCH_VERSION | |
184 | IEEE1394_MATCH_MODEL_ID, |
185 | .vendor_id = OUI_RME, |
186 | .specifier_id = OUI_RME, |
187 | .version = SND_FF_UNIT_VERSION_FF800, |
188 | .model_id = 0x101800, |
189 | .driver_data = (kernel_ulong_t)&spec_ff800, |
190 | }, |
191 | /* Fireface 400 */ |
192 | { |
193 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
194 | IEEE1394_MATCH_SPECIFIER_ID | |
195 | IEEE1394_MATCH_VERSION | |
196 | IEEE1394_MATCH_MODEL_ID, |
197 | .vendor_id = OUI_RME, |
198 | .specifier_id = OUI_RME, |
199 | .version = SND_FF_UNIT_VERSION_FF400, |
200 | .model_id = 0x101800, |
201 | .driver_data = (kernel_ulong_t)&spec_ff400, |
202 | }, |
203 | // Fireface UFX. |
204 | { |
205 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
206 | IEEE1394_MATCH_SPECIFIER_ID | |
207 | IEEE1394_MATCH_VERSION | |
208 | IEEE1394_MATCH_MODEL_ID, |
209 | .vendor_id = OUI_RME, |
210 | .specifier_id = OUI_RME, |
211 | .version = SND_FF_UNIT_VERSION_UFX, |
212 | .model_id = 0x101800, |
213 | .driver_data = (kernel_ulong_t)&spec_ufx_802, |
214 | }, |
215 | // Fireface UCX. |
216 | { |
217 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
218 | IEEE1394_MATCH_SPECIFIER_ID | |
219 | IEEE1394_MATCH_VERSION | |
220 | IEEE1394_MATCH_MODEL_ID, |
221 | .vendor_id = OUI_RME, |
222 | .specifier_id = OUI_RME, |
223 | .version = SND_FF_UNIT_VERSION_UCX, |
224 | .model_id = 0x101800, |
225 | .driver_data = (kernel_ulong_t)&spec_ucx, |
226 | }, |
227 | // Fireface 802. |
228 | { |
229 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
230 | IEEE1394_MATCH_SPECIFIER_ID | |
231 | IEEE1394_MATCH_VERSION | |
232 | IEEE1394_MATCH_MODEL_ID, |
233 | .vendor_id = OUI_RME, |
234 | .specifier_id = OUI_RME, |
235 | .version = SND_FF_UNIT_VERSION_802, |
236 | .model_id = 0x101800, |
237 | .driver_data = (kernel_ulong_t)&spec_ufx_802, |
238 | }, |
239 | {} |
240 | }; |
241 | MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table); |
242 | |
243 | static struct fw_driver ff_driver = { |
244 | .driver = { |
245 | .owner = THIS_MODULE, |
246 | .name = KBUILD_MODNAME, |
247 | .bus = &fw_bus_type, |
248 | }, |
249 | .probe = snd_ff_probe, |
250 | .update = snd_ff_update, |
251 | .remove = snd_ff_remove, |
252 | .id_table = snd_ff_id_table, |
253 | }; |
254 | |
255 | static int __init snd_ff_init(void) |
256 | { |
257 | return driver_register(drv: &ff_driver.driver); |
258 | } |
259 | |
260 | static void __exit snd_ff_exit(void) |
261 | { |
262 | driver_unregister(drv: &ff_driver.driver); |
263 | } |
264 | |
265 | module_init(snd_ff_init); |
266 | module_exit(snd_ff_exit); |
267 | |