Commit | Line | Data |
---|---|---|
82fbb4f7 CL |
1 | /* |
2 | * TC Applied Technologies Digital Interface Communications Engine driver | |
3 | * | |
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | |
5 | * Licensed under the terms of the GNU General Public License, version 2. | |
6 | */ | |
7 | ||
7c2d4c0c | 8 | #include "dice.h" |
82fbb4f7 CL |
9 | |
10 | MODULE_DESCRIPTION("DICE driver"); | |
11 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | |
12 | MODULE_LICENSE("GPL v2"); | |
13 | ||
a471fcde | 14 | #define OUI_WEISS 0x001c6a |
5d5563b1 | 15 | #define OUI_LOUD 0x000ff2 |
7cafc65b TS |
16 | #define OUI_FOCUSRITE 0x00130e |
17 | #define OUI_TCELECTRONIC 0x001486 | |
a471fcde CL |
18 | |
19 | #define DICE_CATEGORY_ID 0x04 | |
20 | #define WEISS_CATEGORY_ID 0x00 | |
5d5563b1 | 21 | #define LOUD_CATEGORY_ID 0x10 |
cbab328d | 22 | |
7cafc65b TS |
23 | /* |
24 | * Some models support several isochronous channels, while these streams are not | |
25 | * always available. In this case, add the model name to this list. | |
26 | */ | |
27 | static bool force_two_pcm_support(struct fw_unit *unit) | |
28 | { | |
29 | const char *const models[] = { | |
30 | /* TC Electronic models. */ | |
31 | "StudioKonnekt48", | |
32 | /* Focusrite models. */ | |
33 | "SAFFIRE_PRO_40", | |
34 | "LIQUID_SAFFIRE_56", | |
35 | "SAFFIRE_PRO_40_1", | |
36 | }; | |
37 | char model[32]; | |
38 | unsigned int i; | |
39 | int err; | |
40 | ||
41 | err = fw_csr_string(unit->directory, CSR_MODEL, model, sizeof(model)); | |
42 | if (err < 0) | |
43 | return false; | |
44 | ||
45 | for (i = 0; i < ARRAY_SIZE(models); i++) { | |
46 | if (strcmp(models[i], model) == 0) | |
47 | break; | |
48 | } | |
49 | ||
50 | return i < ARRAY_SIZE(models); | |
51 | } | |
52 | ||
4a47a87d | 53 | static int check_dice_category(struct fw_unit *unit) |
cbab328d | 54 | { |
cbab328d CL |
55 | struct fw_device *device = fw_parent_device(unit); |
56 | struct fw_csr_iterator it; | |
4a47a87d TS |
57 | int key, val, vendor = -1, model = -1; |
58 | unsigned int category; | |
7c2d4c0c | 59 | |
cbab328d CL |
60 | /* |
61 | * Check that GUID and unit directory are constructed according to DICE | |
62 | * rules, i.e., that the specifier ID is the GUID's OUI, and that the | |
a471fcde CL |
63 | * GUID chip ID consists of the 8-bit category ID, the 10-bit product |
64 | * ID, and a 22-bit serial number. | |
cbab328d CL |
65 | */ |
66 | fw_csr_iterator_init(&it, unit->directory); | |
7c2d4c0c | 67 | while (fw_csr_iterator_next(&it, &key, &val)) { |
cbab328d CL |
68 | switch (key) { |
69 | case CSR_SPECIFIER_ID: | |
7c2d4c0c | 70 | vendor = val; |
cbab328d CL |
71 | break; |
72 | case CSR_MODEL: | |
7c2d4c0c | 73 | model = val; |
cbab328d CL |
74 | break; |
75 | } | |
76 | } | |
7cafc65b TS |
77 | |
78 | if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) { | |
79 | if (force_two_pcm_support(unit)) | |
80 | return 0; | |
81 | } | |
82 | ||
a471fcde CL |
83 | if (vendor == OUI_WEISS) |
84 | category = WEISS_CATEGORY_ID; | |
5d5563b1 TS |
85 | else if (vendor == OUI_LOUD) |
86 | category = LOUD_CATEGORY_ID; | |
a471fcde CL |
87 | else |
88 | category = DICE_CATEGORY_ID; | |
89 | if (device->config_rom[3] != ((vendor << 8) | category) || | |
4a47a87d TS |
90 | device->config_rom[4] >> 22 != model) |
91 | return -ENODEV; | |
cbab328d | 92 | |
4a47a87d | 93 | return 0; |
cbab328d CL |
94 | } |
95 | ||
6f688268 | 96 | static int check_clock_caps(struct snd_dice *dice) |
82fbb4f7 | 97 | { |
a0301998 | 98 | __be32 value; |
6f688268 | 99 | int err; |
82fbb4f7 | 100 | |
a0301998 | 101 | /* some very old firmwares don't tell about their clock support */ |
7c2d4c0c TS |
102 | if (dice->clock_caps > 0) { |
103 | err = snd_dice_transaction_read_global(dice, | |
104 | GLOBAL_CLOCK_CAPABILITIES, | |
105 | &value, 4); | |
a0301998 CL |
106 | if (err < 0) |
107 | return err; | |
108 | dice->clock_caps = be32_to_cpu(value); | |
109 | } else { | |
110 | /* this should be supported by any device */ | |
111 | dice->clock_caps = CLOCK_CAP_RATE_44100 | | |
112 | CLOCK_CAP_RATE_48000 | | |
113 | CLOCK_CAP_SOURCE_ARX1 | | |
114 | CLOCK_CAP_SOURCE_INTERNAL; | |
115 | } | |
116 | ||
82fbb4f7 CL |
117 | return 0; |
118 | } | |
119 | ||
732d153f | 120 | static void dice_card_strings(struct snd_dice *dice) |
82fbb4f7 CL |
121 | { |
122 | struct snd_card *card = dice->card; | |
123 | struct fw_device *dev = fw_parent_device(dice->unit); | |
124 | char vendor[32], model[32]; | |
125 | unsigned int i; | |
126 | int err; | |
127 | ||
128 | strcpy(card->driver, "DICE"); | |
129 | ||
130 | strcpy(card->shortname, "DICE"); | |
131 | BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); | |
7c2d4c0c TS |
132 | err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME, |
133 | card->shortname, | |
134 | sizeof(card->shortname)); | |
82fbb4f7 CL |
135 | if (err >= 0) { |
136 | /* DICE strings are returned in "always-wrong" endianness */ | |
137 | BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); | |
138 | for (i = 0; i < sizeof(card->shortname); i += 4) | |
139 | swab32s((u32 *)&card->shortname[i]); | |
140 | card->shortname[sizeof(card->shortname) - 1] = '\0'; | |
141 | } | |
142 | ||
143 | strcpy(vendor, "?"); | |
144 | fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor)); | |
145 | strcpy(model, "?"); | |
146 | fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model)); | |
147 | snprintf(card->longname, sizeof(card->longname), | |
cbab328d CL |
148 | "%s %s (serial %u) at %s, S%d", |
149 | vendor, model, dev->config_rom[4] & 0x3fffff, | |
82fbb4f7 CL |
150 | dev_name(&dice->unit->device), 100 << dev->max_speed); |
151 | ||
152 | strcpy(card->mixername, "DICE"); | |
153 | } | |
154 | ||
b59fb190 TS |
155 | static void dice_free(struct snd_dice *dice) |
156 | { | |
157 | snd_dice_stream_destroy_duplex(dice); | |
158 | snd_dice_transaction_destroy(dice); | |
159 | fw_unit_put(dice->unit); | |
160 | ||
161 | mutex_destroy(&dice->mutex); | |
162 | kfree(dice); | |
163 | } | |
164 | ||
12ed7192 TS |
165 | /* |
166 | * This module releases the FireWire unit data after all ALSA character devices | |
167 | * are released by applications. This is for releasing stream data or finishing | |
168 | * transactions safely. Thus at returning from .remove(), this module still keep | |
169 | * references for the unit. | |
170 | */ | |
7c2d4c0c TS |
171 | static void dice_card_free(struct snd_card *card) |
172 | { | |
b59fb190 | 173 | dice_free(card->private_data); |
7c2d4c0c TS |
174 | } |
175 | ||
b59fb190 | 176 | static void do_registration(struct work_struct *work) |
82fbb4f7 | 177 | { |
b59fb190 | 178 | struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work); |
82fbb4f7 CL |
179 | int err; |
180 | ||
b59fb190 TS |
181 | if (dice->registered) |
182 | return; | |
cbab328d | 183 | |
b59fb190 TS |
184 | err = snd_card_new(&dice->unit->device, -1, NULL, THIS_MODULE, 0, |
185 | &dice->card); | |
82fbb4f7 | 186 | if (err < 0) |
b59fb190 | 187 | return; |
82fbb4f7 | 188 | |
7cafc65b TS |
189 | if (force_two_pcm_support(dice->unit)) |
190 | dice->force_two_pcms = true; | |
191 | ||
7c2d4c0c | 192 | err = snd_dice_transaction_init(dice); |
82fbb4f7 | 193 | if (err < 0) |
7c2d4c0c | 194 | goto error; |
5ea4018e | 195 | |
6f688268 | 196 | err = check_clock_caps(dice); |
5ea4018e | 197 | if (err < 0) |
7c2d4c0c | 198 | goto error; |
82fbb4f7 CL |
199 | |
200 | dice_card_strings(dice); | |
201 | ||
0eced45c TS |
202 | err = snd_dice_stream_init_duplex(dice); |
203 | if (err < 0) | |
204 | goto error; | |
205 | ||
b59fb190 TS |
206 | snd_dice_create_proc(dice); |
207 | ||
c50fb91f | 208 | err = snd_dice_create_pcm(dice); |
82fbb4f7 CL |
209 | if (err < 0) |
210 | goto error; | |
211 | ||
b59fb190 | 212 | err = snd_dice_create_midi(dice); |
82fbb4f7 CL |
213 | if (err < 0) |
214 | goto error; | |
215 | ||
b59fb190 | 216 | err = snd_dice_create_hwdep(dice); |
a113ff88 TS |
217 | if (err < 0) |
218 | goto error; | |
219 | ||
b59fb190 | 220 | err = snd_card_register(dice->card); |
82fbb4f7 CL |
221 | if (err < 0) |
222 | goto error; | |
82fbb4f7 | 223 | |
b59fb190 TS |
224 | /* |
225 | * After registered, dice instance can be released corresponding to | |
226 | * releasing the sound card instance. | |
227 | */ | |
228 | dice->card->private_free = dice_card_free; | |
229 | dice->card->private_data = dice; | |
230 | dice->registered = true; | |
231 | ||
232 | return; | |
233 | error: | |
0eced45c | 234 | snd_dice_stream_destroy_duplex(dice); |
b59fb190 | 235 | snd_dice_transaction_destroy(dice); |
923f92eb | 236 | snd_dice_stream_destroy_duplex(dice); |
b59fb190 TS |
237 | snd_card_free(dice->card); |
238 | dev_info(&dice->unit->device, | |
239 | "Sound card registration failed: %d\n", err); | |
240 | } | |
241 | ||
b59fb190 TS |
242 | static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) |
243 | { | |
244 | struct snd_dice *dice; | |
245 | int err; | |
246 | ||
247 | err = check_dice_category(unit); | |
248 | if (err < 0) | |
249 | return -ENODEV; | |
250 | ||
251 | /* Allocate this independent of sound card instance. */ | |
252 | dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL); | |
253 | if (dice == NULL) | |
254 | return -ENOMEM; | |
255 | ||
256 | dice->unit = fw_unit_get(unit); | |
257 | dev_set_drvdata(&unit->device, dice); | |
258 | ||
259 | spin_lock_init(&dice->lock); | |
260 | mutex_init(&dice->mutex); | |
261 | init_completion(&dice->clock_accepted); | |
262 | init_waitqueue_head(&dice->hwdep_wait); | |
263 | ||
b59fb190 TS |
264 | /* Allocate and register this sound card later. */ |
265 | INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); | |
923f92eb | 266 | snd_fw_schedule_registration(unit, &dice->dwork); |
b59fb190 TS |
267 | |
268 | return 0; | |
82fbb4f7 CL |
269 | } |
270 | ||
271 | static void dice_remove(struct fw_unit *unit) | |
272 | { | |
732d153f | 273 | struct snd_dice *dice = dev_get_drvdata(&unit->device); |
82fbb4f7 | 274 | |
b59fb190 TS |
275 | /* |
276 | * Confirm to stop the work for registration before the sound card is | |
277 | * going to be released. The work is not scheduled again because bus | |
278 | * reset handler is not called anymore. | |
279 | */ | |
280 | cancel_delayed_work_sync(&dice->dwork); | |
281 | ||
282 | if (dice->registered) { | |
283 | /* No need to wait for releasing card object in this context. */ | |
284 | snd_card_free_when_closed(dice->card); | |
285 | } else { | |
286 | /* Don't forget this case. */ | |
287 | dice_free(dice); | |
288 | } | |
82fbb4f7 CL |
289 | } |
290 | ||
291 | static void dice_bus_reset(struct fw_unit *unit) | |
292 | { | |
732d153f | 293 | struct snd_dice *dice = dev_get_drvdata(&unit->device); |
82fbb4f7 | 294 | |
b59fb190 TS |
295 | /* Postpone a workqueue for deferred registration. */ |
296 | if (!dice->registered) | |
923f92eb | 297 | snd_fw_schedule_registration(unit, &dice->dwork); |
b59fb190 | 298 | |
7c2d4c0c TS |
299 | /* The handler address register becomes initialized. */ |
300 | snd_dice_transaction_reinit(dice); | |
301 | ||
b59fb190 TS |
302 | /* |
303 | * After registration, userspace can start packet streaming, then this | |
304 | * code block works fine. | |
305 | */ | |
306 | if (dice->registered) { | |
307 | mutex_lock(&dice->mutex); | |
308 | snd_dice_stream_update_duplex(dice); | |
309 | mutex_unlock(&dice->mutex); | |
310 | } | |
82fbb4f7 CL |
311 | } |
312 | ||
82fbb4f7 CL |
313 | #define DICE_INTERFACE 0x000001 |
314 | ||
315 | static const struct ieee1394_device_id dice_id_table[] = { | |
316 | { | |
cbab328d CL |
317 | .match_flags = IEEE1394_MATCH_VERSION, |
318 | .version = DICE_INTERFACE, | |
82fbb4f7 | 319 | }, |
f8ff65bc TS |
320 | /* M-Audio Profire 610/2626 has a different value in version field. */ |
321 | { | |
322 | .match_flags = IEEE1394_MATCH_VENDOR_ID | | |
323 | IEEE1394_MATCH_SPECIFIER_ID, | |
324 | .vendor_id = 0x000d6c, | |
325 | .specifier_id = 0x000d6c, | |
326 | }, | |
82fbb4f7 CL |
327 | { } |
328 | }; | |
329 | MODULE_DEVICE_TABLE(ieee1394, dice_id_table); | |
330 | ||
331 | static struct fw_driver dice_driver = { | |
332 | .driver = { | |
333 | .owner = THIS_MODULE, | |
334 | .name = KBUILD_MODNAME, | |
335 | .bus = &fw_bus_type, | |
336 | }, | |
337 | .probe = dice_probe, | |
338 | .update = dice_bus_reset, | |
339 | .remove = dice_remove, | |
340 | .id_table = dice_id_table, | |
341 | }; | |
342 | ||
343 | static int __init alsa_dice_init(void) | |
344 | { | |
345 | return driver_register(&dice_driver.driver); | |
346 | } | |
347 | ||
348 | static void __exit alsa_dice_exit(void) | |
349 | { | |
350 | driver_unregister(&dice_driver.driver); | |
351 | } | |
352 | ||
353 | module_init(alsa_dice_init); | |
354 | module_exit(alsa_dice_exit); |