1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * TC Applied Technologies Digital Interface Communications Engine driver |
4 | * |
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
6 | */ |
7 | |
8 | #include "dice.h" |
9 | |
10 | MODULE_DESCRIPTION("DICE driver" ); |
11 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>" ); |
12 | MODULE_LICENSE("GPL" ); |
13 | |
14 | #define OUI_WEISS 0x001c6a |
15 | #define OUI_LOUD 0x000ff2 |
16 | #define OUI_FOCUSRITE 0x00130e |
17 | #define OUI_TCELECTRONIC 0x000166 |
18 | #define OUI_ALESIS 0x000595 |
19 | #define OUI_MAUDIO 0x000d6c |
20 | #define OUI_MYTEK 0x001ee8 |
21 | #define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. |
22 | #define OUI_PRESONUS 0x000a92 |
23 | #define OUI_HARMAN 0x000fd7 |
24 | #define OUI_AVID 0x00a07e |
25 | |
26 | #define DICE_CATEGORY_ID 0x04 |
27 | #define WEISS_CATEGORY_ID 0x00 |
28 | #define LOUD_CATEGORY_ID 0x10 |
29 | #define HARMAN_CATEGORY_ID 0x20 |
30 | |
31 | #define MODEL_ALESIS_IO_BOTH 0x000001 |
32 | |
33 | static int check_dice_category(struct fw_unit *unit) |
34 | { |
35 | struct fw_device *device = fw_parent_device(unit); |
36 | struct fw_csr_iterator it; |
37 | int key, val, vendor = -1, model = -1; |
38 | unsigned int category; |
39 | |
40 | /* |
41 | * Check that GUID and unit directory are constructed according to DICE |
42 | * rules, i.e., that the specifier ID is the GUID's OUI, and that the |
43 | * GUID chip ID consists of the 8-bit category ID, the 10-bit product |
44 | * ID, and a 22-bit serial number. |
45 | */ |
46 | fw_csr_iterator_init(ci: &it, p: unit->directory); |
47 | while (fw_csr_iterator_next(ci: &it, key: &key, value: &val)) { |
48 | switch (key) { |
49 | case CSR_SPECIFIER_ID: |
50 | vendor = val; |
51 | break; |
52 | case CSR_MODEL: |
53 | model = val; |
54 | break; |
55 | } |
56 | } |
57 | |
58 | if (vendor == OUI_WEISS) |
59 | category = WEISS_CATEGORY_ID; |
60 | else if (vendor == OUI_LOUD) |
61 | category = LOUD_CATEGORY_ID; |
62 | else if (vendor == OUI_HARMAN) |
63 | category = HARMAN_CATEGORY_ID; |
64 | else |
65 | category = DICE_CATEGORY_ID; |
66 | if (device->config_rom[3] != ((vendor << 8) | category) || |
67 | device->config_rom[4] >> 22 != model) |
68 | return -ENODEV; |
69 | |
70 | return 0; |
71 | } |
72 | |
73 | static int check_clock_caps(struct snd_dice *dice) |
74 | { |
75 | __be32 value; |
76 | int err; |
77 | |
78 | /* some very old firmwares don't tell about their clock support */ |
79 | if (dice->clock_caps > 0) { |
80 | err = snd_dice_transaction_read_global(dice, |
81 | GLOBAL_CLOCK_CAPABILITIES, |
82 | buf: &value, len: 4); |
83 | if (err < 0) |
84 | return err; |
85 | dice->clock_caps = be32_to_cpu(value); |
86 | } else { |
87 | /* this should be supported by any device */ |
88 | dice->clock_caps = CLOCK_CAP_RATE_44100 | |
89 | CLOCK_CAP_RATE_48000 | |
90 | CLOCK_CAP_SOURCE_ARX1 | |
91 | CLOCK_CAP_SOURCE_INTERNAL; |
92 | } |
93 | |
94 | return 0; |
95 | } |
96 | |
97 | static void dice_card_strings(struct snd_dice *dice) |
98 | { |
99 | struct snd_card *card = dice->card; |
100 | struct fw_device *dev = fw_parent_device(dice->unit); |
101 | char vendor[32], model[32]; |
102 | unsigned int i; |
103 | int err; |
104 | |
105 | strcpy(p: card->driver, q: "DICE" ); |
106 | |
107 | strcpy(p: card->shortname, q: "DICE" ); |
108 | BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); |
109 | err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME, |
110 | buf: card->shortname, |
111 | len: sizeof(card->shortname)); |
112 | if (err >= 0) { |
113 | /* DICE strings are returned in "always-wrong" endianness */ |
114 | BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); |
115 | for (i = 0; i < sizeof(card->shortname); i += 4) |
116 | swab32s(p: (u32 *)&card->shortname[i]); |
117 | card->shortname[sizeof(card->shortname) - 1] = '\0'; |
118 | } |
119 | |
120 | strcpy(p: vendor, q: "?" ); |
121 | fw_csr_string(directory: dev->config_rom + 5, CSR_VENDOR, buf: vendor, size: sizeof(vendor)); |
122 | strcpy(p: model, q: "?" ); |
123 | fw_csr_string(directory: dice->unit->directory, CSR_MODEL, buf: model, size: sizeof(model)); |
124 | snprintf(buf: card->longname, size: sizeof(card->longname), |
125 | fmt: "%s %s (serial %u) at %s, S%d" , |
126 | vendor, model, dev->config_rom[4] & 0x3fffff, |
127 | dev_name(dev: &dice->unit->device), 100 << dev->max_speed); |
128 | |
129 | strcpy(p: card->mixername, q: "DICE" ); |
130 | } |
131 | |
132 | static void dice_card_free(struct snd_card *card) |
133 | { |
134 | struct snd_dice *dice = card->private_data; |
135 | |
136 | snd_dice_stream_destroy_duplex(dice); |
137 | snd_dice_transaction_destroy(dice); |
138 | |
139 | mutex_destroy(lock: &dice->mutex); |
140 | fw_unit_put(unit: dice->unit); |
141 | } |
142 | |
143 | static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) |
144 | { |
145 | struct snd_card *card; |
146 | struct snd_dice *dice; |
147 | snd_dice_detect_formats_t detect_formats; |
148 | int err; |
149 | |
150 | if (!entry->driver_data && entry->vendor_id != OUI_SSL) { |
151 | err = check_dice_category(unit); |
152 | if (err < 0) |
153 | return -ENODEV; |
154 | } |
155 | |
156 | err = snd_card_new(parent: &unit->device, idx: -1, NULL, THIS_MODULE, extra_size: sizeof(*dice), card_ret: &card); |
157 | if (err < 0) |
158 | return err; |
159 | card->private_free = dice_card_free; |
160 | |
161 | dice = card->private_data; |
162 | dice->unit = fw_unit_get(unit); |
163 | dev_set_drvdata(dev: &unit->device, data: dice); |
164 | dice->card = card; |
165 | |
166 | if (!entry->driver_data) |
167 | detect_formats = snd_dice_stream_detect_current_formats; |
168 | else |
169 | detect_formats = (snd_dice_detect_formats_t)entry->driver_data; |
170 | |
171 | // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer |
172 | // frequency. |
173 | // * Avid M-Box 3 Pro |
174 | // * M-Audio Profire 610 |
175 | // * M-Audio Profire 2626 |
176 | if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID) |
177 | dice->disable_double_pcm_frames = true; |
178 | |
179 | spin_lock_init(&dice->lock); |
180 | mutex_init(&dice->mutex); |
181 | init_completion(x: &dice->clock_accepted); |
182 | init_waitqueue_head(&dice->hwdep_wait); |
183 | |
184 | err = snd_dice_transaction_init(dice); |
185 | if (err < 0) |
186 | goto error; |
187 | |
188 | err = check_clock_caps(dice); |
189 | if (err < 0) |
190 | goto error; |
191 | |
192 | dice_card_strings(dice); |
193 | |
194 | err = detect_formats(dice); |
195 | if (err < 0) |
196 | goto error; |
197 | |
198 | err = snd_dice_stream_init_duplex(dice); |
199 | if (err < 0) |
200 | goto error; |
201 | |
202 | snd_dice_create_proc(dice); |
203 | |
204 | err = snd_dice_create_pcm(dice); |
205 | if (err < 0) |
206 | goto error; |
207 | |
208 | err = snd_dice_create_midi(dice); |
209 | if (err < 0) |
210 | goto error; |
211 | |
212 | err = snd_dice_create_hwdep(dice); |
213 | if (err < 0) |
214 | goto error; |
215 | |
216 | err = snd_card_register(card); |
217 | if (err < 0) |
218 | goto error; |
219 | |
220 | return 0; |
221 | error: |
222 | snd_card_free(card); |
223 | return err; |
224 | } |
225 | |
226 | static void dice_remove(struct fw_unit *unit) |
227 | { |
228 | struct snd_dice *dice = dev_get_drvdata(dev: &unit->device); |
229 | |
230 | // Block till all of ALSA character devices are released. |
231 | snd_card_free(card: dice->card); |
232 | } |
233 | |
234 | static void dice_bus_reset(struct fw_unit *unit) |
235 | { |
236 | struct snd_dice *dice = dev_get_drvdata(dev: &unit->device); |
237 | |
238 | /* The handler address register becomes initialized. */ |
239 | snd_dice_transaction_reinit(dice); |
240 | |
241 | mutex_lock(&dice->mutex); |
242 | snd_dice_stream_update_duplex(dice); |
243 | mutex_unlock(lock: &dice->mutex); |
244 | } |
245 | |
246 | #define DICE_INTERFACE 0x000001 |
247 | |
248 | #define DICE_DEV_ENTRY_TYPICAL(vendor, model, data) \ |
249 | { \ |
250 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ |
251 | IEEE1394_MATCH_MODEL_ID | \ |
252 | IEEE1394_MATCH_SPECIFIER_ID | \ |
253 | IEEE1394_MATCH_VERSION, \ |
254 | .vendor_id = (vendor), \ |
255 | .model_id = (model), \ |
256 | .specifier_id = (vendor), \ |
257 | .version = DICE_INTERFACE, \ |
258 | .driver_data = (kernel_ulong_t)(data), \ |
259 | } |
260 | |
261 | static const struct ieee1394_device_id dice_id_table[] = { |
262 | // Avid M-Box 3 Pro. To match in probe function. |
263 | DICE_DEV_ENTRY_TYPICAL(OUI_AVID, 0x000004, snd_dice_detect_extension_formats), |
264 | /* M-Audio Profire 2626 has a different value in version field. */ |
265 | { |
266 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
267 | IEEE1394_MATCH_MODEL_ID, |
268 | .vendor_id = OUI_MAUDIO, |
269 | .model_id = 0x000010, |
270 | .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats, |
271 | }, |
272 | /* M-Audio Profire 610 has a different value in version field. */ |
273 | { |
274 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
275 | IEEE1394_MATCH_MODEL_ID, |
276 | .vendor_id = OUI_MAUDIO, |
277 | .model_id = 0x000011, |
278 | .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats, |
279 | }, |
280 | /* TC Electronic Konnekt 24D. */ |
281 | { |
282 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
283 | IEEE1394_MATCH_MODEL_ID, |
284 | .vendor_id = OUI_TCELECTRONIC, |
285 | .model_id = 0x000020, |
286 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
287 | }, |
288 | /* TC Electronic Konnekt 8. */ |
289 | { |
290 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
291 | IEEE1394_MATCH_MODEL_ID, |
292 | .vendor_id = OUI_TCELECTRONIC, |
293 | .model_id = 0x000021, |
294 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
295 | }, |
296 | /* TC Electronic Studio Konnekt 48. */ |
297 | { |
298 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
299 | IEEE1394_MATCH_MODEL_ID, |
300 | .vendor_id = OUI_TCELECTRONIC, |
301 | .model_id = 0x000022, |
302 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
303 | }, |
304 | /* TC Electronic Konnekt Live. */ |
305 | { |
306 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
307 | IEEE1394_MATCH_MODEL_ID, |
308 | .vendor_id = OUI_TCELECTRONIC, |
309 | .model_id = 0x000023, |
310 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
311 | }, |
312 | /* TC Electronic Desktop Konnekt 6. */ |
313 | { |
314 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
315 | IEEE1394_MATCH_MODEL_ID, |
316 | .vendor_id = OUI_TCELECTRONIC, |
317 | .model_id = 0x000024, |
318 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
319 | }, |
320 | /* TC Electronic Impact Twin. */ |
321 | { |
322 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
323 | IEEE1394_MATCH_MODEL_ID, |
324 | .vendor_id = OUI_TCELECTRONIC, |
325 | .model_id = 0x000027, |
326 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
327 | }, |
328 | /* TC Electronic Digital Konnekt x32. */ |
329 | { |
330 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
331 | IEEE1394_MATCH_MODEL_ID, |
332 | .vendor_id = OUI_TCELECTRONIC, |
333 | .model_id = 0x000030, |
334 | .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, |
335 | }, |
336 | /* Alesis iO14/iO26. */ |
337 | { |
338 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
339 | IEEE1394_MATCH_MODEL_ID, |
340 | .vendor_id = OUI_ALESIS, |
341 | .model_id = MODEL_ALESIS_IO_BOTH, |
342 | .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats, |
343 | }, |
344 | // Alesis MasterControl. |
345 | { |
346 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
347 | IEEE1394_MATCH_MODEL_ID, |
348 | .vendor_id = OUI_ALESIS, |
349 | .model_id = 0x000002, |
350 | .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats, |
351 | }, |
352 | /* Mytek Stereo 192 DSD-DAC. */ |
353 | { |
354 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
355 | IEEE1394_MATCH_MODEL_ID, |
356 | .vendor_id = OUI_MYTEK, |
357 | .model_id = 0x000002, |
358 | .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats, |
359 | }, |
360 | // Solid State Logic, Duende Classic and Mini. |
361 | // NOTE: each field of GUID in config ROM is not compliant to standard |
362 | // DICE scheme. |
363 | { |
364 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
365 | IEEE1394_MATCH_MODEL_ID, |
366 | .vendor_id = OUI_SSL, |
367 | .model_id = 0x000070, |
368 | }, |
369 | // Presonus FireStudio. |
370 | { |
371 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
372 | IEEE1394_MATCH_MODEL_ID, |
373 | .vendor_id = OUI_PRESONUS, |
374 | .model_id = 0x000008, |
375 | .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, |
376 | }, |
377 | // Lexicon I-ONYX FW810S. |
378 | { |
379 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
380 | IEEE1394_MATCH_MODEL_ID, |
381 | .vendor_id = OUI_HARMAN, |
382 | .model_id = 0x000001, |
383 | .driver_data = (kernel_ulong_t)snd_dice_detect_harman_formats, |
384 | }, |
385 | // Focusrite Saffire Pro 40 with TCD3070-CH. |
386 | // The model has quirk in its GUID, in which model field is 0x000013 and different from |
387 | // model ID (0x0000de) in its root/unit directory. |
388 | { |
389 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
390 | IEEE1394_MATCH_MODEL_ID, |
391 | .vendor_id = OUI_FOCUSRITE, |
392 | .model_id = 0x0000de, |
393 | .driver_data = (kernel_ulong_t)snd_dice_detect_focusrite_pro40_tcd3070_formats, |
394 | }, |
395 | // Weiss DAC202: 192kHz 2-channel DAC |
396 | { |
397 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
398 | .vendor_id = OUI_WEISS, |
399 | .model_id = 0x000007, |
400 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
401 | }, |
402 | // Weiss DAC202: 192kHz 2-channel DAC (Maya edition) |
403 | { |
404 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
405 | .vendor_id = OUI_WEISS, |
406 | .model_id = 0x000008, |
407 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
408 | }, |
409 | // Weiss MAN301: 192kHz 2-channel music archive network player |
410 | { |
411 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
412 | .vendor_id = OUI_WEISS, |
413 | .model_id = 0x00000b, |
414 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
415 | }, |
416 | // Weiss INT202: 192kHz unidirectional 2-channel digital Firewire face |
417 | { |
418 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
419 | .vendor_id = OUI_WEISS, |
420 | .model_id = 0x000006, |
421 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
422 | }, |
423 | // Weiss INT203: 192kHz bidirectional 2-channel digital Firewire face |
424 | { |
425 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
426 | .vendor_id = OUI_WEISS, |
427 | .model_id = 0x00000a, |
428 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
429 | }, |
430 | // Weiss ADC2: 192kHz A/D converter with microphone preamps and inputs |
431 | { |
432 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
433 | .vendor_id = OUI_WEISS, |
434 | .model_id = 0x000001, |
435 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
436 | }, |
437 | // Weiss DAC2/Minerva: 192kHz 2-channel DAC |
438 | { |
439 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
440 | .vendor_id = OUI_WEISS, |
441 | .model_id = 0x000003, |
442 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
443 | }, |
444 | // Weiss Vesta: 192kHz 2-channel Firewire to AES/EBU interface |
445 | { |
446 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
447 | .vendor_id = OUI_WEISS, |
448 | .model_id = 0x000002, |
449 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
450 | }, |
451 | // Weiss AFI1: 192kHz 24-channel Firewire to ADAT or AES/EBU face |
452 | { |
453 | .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, |
454 | .vendor_id = OUI_WEISS, |
455 | .model_id = 0x000004, |
456 | .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, |
457 | }, |
458 | { |
459 | .match_flags = IEEE1394_MATCH_VERSION, |
460 | .version = DICE_INTERFACE, |
461 | }, |
462 | { } |
463 | }; |
464 | MODULE_DEVICE_TABLE(ieee1394, dice_id_table); |
465 | |
466 | static struct fw_driver dice_driver = { |
467 | .driver = { |
468 | .owner = THIS_MODULE, |
469 | .name = KBUILD_MODNAME, |
470 | .bus = &fw_bus_type, |
471 | }, |
472 | .probe = dice_probe, |
473 | .update = dice_bus_reset, |
474 | .remove = dice_remove, |
475 | .id_table = dice_id_table, |
476 | }; |
477 | |
478 | static int __init alsa_dice_init(void) |
479 | { |
480 | return driver_register(drv: &dice_driver.driver); |
481 | } |
482 | |
483 | static void __exit alsa_dice_exit(void) |
484 | { |
485 | driver_unregister(drv: &dice_driver.driver); |
486 | } |
487 | |
488 | module_init(alsa_dice_init); |
489 | module_exit(alsa_dice_exit); |
490 | |