aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/dice/dice.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/dice/dice.c')
-rw-r--r--sound/firewire/dice/dice.c156
1 files changed, 109 insertions, 47 deletions
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 96bb01b6b751..774eb2205668 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -15,40 +15,15 @@ MODULE_LICENSE("GPL v2");
15#define OUI_LOUD 0x000ff2 15#define OUI_LOUD 0x000ff2
16#define OUI_FOCUSRITE 0x00130e 16#define OUI_FOCUSRITE 0x00130e
17#define OUI_TCELECTRONIC 0x000166 17#define OUI_TCELECTRONIC 0x000166
18#define OUI_ALESIS 0x000595
19#define OUI_MAUDIO 0x000d6c
20#define OUI_MYTEK 0x001ee8
18 21
19#define DICE_CATEGORY_ID 0x04 22#define DICE_CATEGORY_ID 0x04
20#define WEISS_CATEGORY_ID 0x00 23#define WEISS_CATEGORY_ID 0x00
21#define LOUD_CATEGORY_ID 0x10 24#define LOUD_CATEGORY_ID 0x10
22 25
23/* 26#define MODEL_ALESIS_IO_BOTH 0x000001
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 */
27static bool force_two_pcm_support(struct fw_unit *unit)
28{
29 static 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 27
53static int check_dice_category(struct fw_unit *unit) 28static int check_dice_category(struct fw_unit *unit)
54{ 29{
@@ -75,11 +50,6 @@ static int check_dice_category(struct fw_unit *unit)
75 } 50 }
76 } 51 }
77 52
78 if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) {
79 if (force_two_pcm_support(unit))
80 return 0;
81 }
82
83 if (vendor == OUI_WEISS) 53 if (vendor == OUI_WEISS)
84 category = WEISS_CATEGORY_ID; 54 category = WEISS_CATEGORY_ID;
85 else if (vendor == OUI_LOUD) 55 else if (vendor == OUI_LOUD)
@@ -186,9 +156,6 @@ static void do_registration(struct work_struct *work)
186 if (err < 0) 156 if (err < 0)
187 return; 157 return;
188 158
189 if (force_two_pcm_support(dice->unit))
190 dice->force_two_pcms = true;
191
192 err = snd_dice_transaction_init(dice); 159 err = snd_dice_transaction_init(dice);
193 if (err < 0) 160 if (err < 0)
194 goto error; 161 goto error;
@@ -199,6 +166,10 @@ static void do_registration(struct work_struct *work)
199 166
200 dice_card_strings(dice); 167 dice_card_strings(dice);
201 168
169 err = dice->detect_formats(dice);
170 if (err < 0)
171 goto error;
172
202 err = snd_dice_stream_init_duplex(dice); 173 err = snd_dice_stream_init_duplex(dice);
203 if (err < 0) 174 if (err < 0)
204 goto error; 175 goto error;
@@ -239,14 +210,17 @@ error:
239 "Sound card registration failed: %d\n", err); 210 "Sound card registration failed: %d\n", err);
240} 211}
241 212
242static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 213static int dice_probe(struct fw_unit *unit,
214 const struct ieee1394_device_id *entry)
243{ 215{
244 struct snd_dice *dice; 216 struct snd_dice *dice;
245 int err; 217 int err;
246 218
247 err = check_dice_category(unit); 219 if (!entry->driver_data) {
248 if (err < 0) 220 err = check_dice_category(unit);
249 return -ENODEV; 221 if (err < 0)
222 return -ENODEV;
223 }
250 224
251 /* Allocate this independent of sound card instance. */ 225 /* Allocate this independent of sound card instance. */
252 dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL); 226 dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL);
@@ -256,6 +230,13 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
256 dice->unit = fw_unit_get(unit); 230 dice->unit = fw_unit_get(unit);
257 dev_set_drvdata(&unit->device, dice); 231 dev_set_drvdata(&unit->device, dice);
258 232
233 if (!entry->driver_data) {
234 dice->detect_formats = snd_dice_stream_detect_current_formats;
235 } else {
236 dice->detect_formats =
237 (snd_dice_detect_formats_t)entry->driver_data;
238 }
239
259 spin_lock_init(&dice->lock); 240 spin_lock_init(&dice->lock);
260 mutex_init(&dice->mutex); 241 mutex_init(&dice->mutex);
261 init_completion(&dice->clock_accepted); 242 init_completion(&dice->clock_accepted);
@@ -313,16 +294,97 @@ static void dice_bus_reset(struct fw_unit *unit)
313#define DICE_INTERFACE 0x000001 294#define DICE_INTERFACE 0x000001
314 295
315static const struct ieee1394_device_id dice_id_table[] = { 296static const struct ieee1394_device_id dice_id_table[] = {
297 /* M-Audio Profire 2626 has a different value in version field. */
316 { 298 {
317 .match_flags = IEEE1394_MATCH_VERSION, 299 .match_flags = IEEE1394_MATCH_VENDOR_ID |
318 .version = DICE_INTERFACE, 300 IEEE1394_MATCH_MODEL_ID,
301 .vendor_id = OUI_MAUDIO,
302 .model_id = 0x000010,
303 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
319 }, 304 },
320 /* M-Audio Profire 610/2626 has a different value in version field. */ 305 /* M-Audio Profire 610 has a different value in version field. */
321 { 306 {
322 .match_flags = IEEE1394_MATCH_VENDOR_ID | 307 .match_flags = IEEE1394_MATCH_VENDOR_ID |
323 IEEE1394_MATCH_SPECIFIER_ID, 308 IEEE1394_MATCH_MODEL_ID,
324 .vendor_id = 0x000d6c, 309 .vendor_id = OUI_MAUDIO,
325 .specifier_id = 0x000d6c, 310 .model_id = 0x000011,
311 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
312 },
313 /* TC Electronic Konnekt 24D. */
314 {
315 .match_flags = IEEE1394_MATCH_VENDOR_ID |
316 IEEE1394_MATCH_MODEL_ID,
317 .vendor_id = OUI_TCELECTRONIC,
318 .model_id = 0x000020,
319 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
320 },
321 /* TC Electronic Konnekt 8. */
322 {
323 .match_flags = IEEE1394_MATCH_VENDOR_ID |
324 IEEE1394_MATCH_MODEL_ID,
325 .vendor_id = OUI_TCELECTRONIC,
326 .model_id = 0x000021,
327 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
328 },
329 /* TC Electronic Studio Konnekt 48. */
330 {
331 .match_flags = IEEE1394_MATCH_VENDOR_ID |
332 IEEE1394_MATCH_MODEL_ID,
333 .vendor_id = OUI_TCELECTRONIC,
334 .model_id = 0x000022,
335 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
336 },
337 /* TC Electronic Konnekt Live. */
338 {
339 .match_flags = IEEE1394_MATCH_VENDOR_ID |
340 IEEE1394_MATCH_MODEL_ID,
341 .vendor_id = OUI_TCELECTRONIC,
342 .model_id = 0x000023,
343 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
344 },
345 /* TC Electronic Desktop Konnekt 6. */
346 {
347 .match_flags = IEEE1394_MATCH_VENDOR_ID |
348 IEEE1394_MATCH_MODEL_ID,
349 .vendor_id = OUI_TCELECTRONIC,
350 .model_id = 0x000024,
351 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
352 },
353 /* TC Electronic Impact Twin. */
354 {
355 .match_flags = IEEE1394_MATCH_VENDOR_ID |
356 IEEE1394_MATCH_MODEL_ID,
357 .vendor_id = OUI_TCELECTRONIC,
358 .model_id = 0x000027,
359 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
360 },
361 /* TC Electronic Digital Konnekt x32. */
362 {
363 .match_flags = IEEE1394_MATCH_VENDOR_ID |
364 IEEE1394_MATCH_MODEL_ID,
365 .vendor_id = OUI_TCELECTRONIC,
366 .model_id = 0x000030,
367 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
368 },
369 /* Alesis iO14/iO26. */
370 {
371 .match_flags = IEEE1394_MATCH_VENDOR_ID |
372 IEEE1394_MATCH_MODEL_ID,
373 .vendor_id = OUI_ALESIS,
374 .model_id = MODEL_ALESIS_IO_BOTH,
375 .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
376 },
377 /* Mytek Stereo 192 DSD-DAC. */
378 {
379 .match_flags = IEEE1394_MATCH_VENDOR_ID |
380 IEEE1394_MATCH_MODEL_ID,
381 .vendor_id = OUI_MYTEK,
382 .model_id = 0x000002,
383 .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
384 },
385 {
386 .match_flags = IEEE1394_MATCH_VERSION,
387 .version = DICE_INTERFACE,
326 }, 388 },
327 { } 389 { }
328}; 390};