162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * TC Applied Technologies Digital Interface Communications Engine driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "dice.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciMODULE_DESCRIPTION("DICE driver"); 1162306a36Sopenharmony_ciMODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 1262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define OUI_WEISS 0x001c6a 1562306a36Sopenharmony_ci#define OUI_LOUD 0x000ff2 1662306a36Sopenharmony_ci#define OUI_FOCUSRITE 0x00130e 1762306a36Sopenharmony_ci#define OUI_TCELECTRONIC 0x000166 1862306a36Sopenharmony_ci#define OUI_ALESIS 0x000595 1962306a36Sopenharmony_ci#define OUI_MAUDIO 0x000d6c 2062306a36Sopenharmony_ci#define OUI_MYTEK 0x001ee8 2162306a36Sopenharmony_ci#define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. 2262306a36Sopenharmony_ci#define OUI_PRESONUS 0x000a92 2362306a36Sopenharmony_ci#define OUI_HARMAN 0x000fd7 2462306a36Sopenharmony_ci#define OUI_AVID 0x00a07e 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define DICE_CATEGORY_ID 0x04 2762306a36Sopenharmony_ci#define WEISS_CATEGORY_ID 0x00 2862306a36Sopenharmony_ci#define LOUD_CATEGORY_ID 0x10 2962306a36Sopenharmony_ci#define HARMAN_CATEGORY_ID 0x20 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define MODEL_ALESIS_IO_BOTH 0x000001 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int check_dice_category(struct fw_unit *unit) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct fw_device *device = fw_parent_device(unit); 3662306a36Sopenharmony_ci struct fw_csr_iterator it; 3762306a36Sopenharmony_ci int key, val, vendor = -1, model = -1; 3862306a36Sopenharmony_ci unsigned int category; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* 4162306a36Sopenharmony_ci * Check that GUID and unit directory are constructed according to DICE 4262306a36Sopenharmony_ci * rules, i.e., that the specifier ID is the GUID's OUI, and that the 4362306a36Sopenharmony_ci * GUID chip ID consists of the 8-bit category ID, the 10-bit product 4462306a36Sopenharmony_ci * ID, and a 22-bit serial number. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci fw_csr_iterator_init(&it, unit->directory); 4762306a36Sopenharmony_ci while (fw_csr_iterator_next(&it, &key, &val)) { 4862306a36Sopenharmony_ci switch (key) { 4962306a36Sopenharmony_ci case CSR_SPECIFIER_ID: 5062306a36Sopenharmony_ci vendor = val; 5162306a36Sopenharmony_ci break; 5262306a36Sopenharmony_ci case CSR_MODEL: 5362306a36Sopenharmony_ci model = val; 5462306a36Sopenharmony_ci break; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (vendor == OUI_WEISS) 5962306a36Sopenharmony_ci category = WEISS_CATEGORY_ID; 6062306a36Sopenharmony_ci else if (vendor == OUI_LOUD) 6162306a36Sopenharmony_ci category = LOUD_CATEGORY_ID; 6262306a36Sopenharmony_ci else if (vendor == OUI_HARMAN) 6362306a36Sopenharmony_ci category = HARMAN_CATEGORY_ID; 6462306a36Sopenharmony_ci else 6562306a36Sopenharmony_ci category = DICE_CATEGORY_ID; 6662306a36Sopenharmony_ci if (device->config_rom[3] != ((vendor << 8) | category) || 6762306a36Sopenharmony_ci device->config_rom[4] >> 22 != model) 6862306a36Sopenharmony_ci return -ENODEV; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return 0; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int check_clock_caps(struct snd_dice *dice) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci __be32 value; 7662306a36Sopenharmony_ci int err; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* some very old firmwares don't tell about their clock support */ 7962306a36Sopenharmony_ci if (dice->clock_caps > 0) { 8062306a36Sopenharmony_ci err = snd_dice_transaction_read_global(dice, 8162306a36Sopenharmony_ci GLOBAL_CLOCK_CAPABILITIES, 8262306a36Sopenharmony_ci &value, 4); 8362306a36Sopenharmony_ci if (err < 0) 8462306a36Sopenharmony_ci return err; 8562306a36Sopenharmony_ci dice->clock_caps = be32_to_cpu(value); 8662306a36Sopenharmony_ci } else { 8762306a36Sopenharmony_ci /* this should be supported by any device */ 8862306a36Sopenharmony_ci dice->clock_caps = CLOCK_CAP_RATE_44100 | 8962306a36Sopenharmony_ci CLOCK_CAP_RATE_48000 | 9062306a36Sopenharmony_ci CLOCK_CAP_SOURCE_ARX1 | 9162306a36Sopenharmony_ci CLOCK_CAP_SOURCE_INTERNAL; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void dice_card_strings(struct snd_dice *dice) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct snd_card *card = dice->card; 10062306a36Sopenharmony_ci struct fw_device *dev = fw_parent_device(dice->unit); 10162306a36Sopenharmony_ci char vendor[32], model[32]; 10262306a36Sopenharmony_ci unsigned int i; 10362306a36Sopenharmony_ci int err; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci strcpy(card->driver, "DICE"); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci strcpy(card->shortname, "DICE"); 10862306a36Sopenharmony_ci BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); 10962306a36Sopenharmony_ci err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME, 11062306a36Sopenharmony_ci card->shortname, 11162306a36Sopenharmony_ci sizeof(card->shortname)); 11262306a36Sopenharmony_ci if (err >= 0) { 11362306a36Sopenharmony_ci /* DICE strings are returned in "always-wrong" endianness */ 11462306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); 11562306a36Sopenharmony_ci for (i = 0; i < sizeof(card->shortname); i += 4) 11662306a36Sopenharmony_ci swab32s((u32 *)&card->shortname[i]); 11762306a36Sopenharmony_ci card->shortname[sizeof(card->shortname) - 1] = '\0'; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci strcpy(vendor, "?"); 12162306a36Sopenharmony_ci fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor)); 12262306a36Sopenharmony_ci strcpy(model, "?"); 12362306a36Sopenharmony_ci fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model)); 12462306a36Sopenharmony_ci snprintf(card->longname, sizeof(card->longname), 12562306a36Sopenharmony_ci "%s %s (serial %u) at %s, S%d", 12662306a36Sopenharmony_ci vendor, model, dev->config_rom[4] & 0x3fffff, 12762306a36Sopenharmony_ci dev_name(&dice->unit->device), 100 << dev->max_speed); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci strcpy(card->mixername, "DICE"); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void dice_card_free(struct snd_card *card) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct snd_dice *dice = card->private_data; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci snd_dice_stream_destroy_duplex(dice); 13762306a36Sopenharmony_ci snd_dice_transaction_destroy(dice); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci mutex_destroy(&dice->mutex); 14062306a36Sopenharmony_ci fw_unit_put(dice->unit); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct snd_card *card; 14662306a36Sopenharmony_ci struct snd_dice *dice; 14762306a36Sopenharmony_ci snd_dice_detect_formats_t detect_formats; 14862306a36Sopenharmony_ci int err; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (!entry->driver_data && entry->vendor_id != OUI_SSL) { 15162306a36Sopenharmony_ci err = check_dice_category(unit); 15262306a36Sopenharmony_ci if (err < 0) 15362306a36Sopenharmony_ci return -ENODEV; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card); 15762306a36Sopenharmony_ci if (err < 0) 15862306a36Sopenharmony_ci return err; 15962306a36Sopenharmony_ci card->private_free = dice_card_free; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci dice = card->private_data; 16262306a36Sopenharmony_ci dice->unit = fw_unit_get(unit); 16362306a36Sopenharmony_ci dev_set_drvdata(&unit->device, dice); 16462306a36Sopenharmony_ci dice->card = card; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (!entry->driver_data) 16762306a36Sopenharmony_ci detect_formats = snd_dice_stream_detect_current_formats; 16862306a36Sopenharmony_ci else 16962306a36Sopenharmony_ci detect_formats = (snd_dice_detect_formats_t)entry->driver_data; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer 17262306a36Sopenharmony_ci // frequency. 17362306a36Sopenharmony_ci // * Avid M-Box 3 Pro 17462306a36Sopenharmony_ci // * M-Audio Profire 610 17562306a36Sopenharmony_ci // * M-Audio Profire 2626 17662306a36Sopenharmony_ci if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID) 17762306a36Sopenharmony_ci dice->disable_double_pcm_frames = true; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci spin_lock_init(&dice->lock); 18062306a36Sopenharmony_ci mutex_init(&dice->mutex); 18162306a36Sopenharmony_ci init_completion(&dice->clock_accepted); 18262306a36Sopenharmony_ci init_waitqueue_head(&dice->hwdep_wait); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci err = snd_dice_transaction_init(dice); 18562306a36Sopenharmony_ci if (err < 0) 18662306a36Sopenharmony_ci goto error; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci err = check_clock_caps(dice); 18962306a36Sopenharmony_ci if (err < 0) 19062306a36Sopenharmony_ci goto error; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci dice_card_strings(dice); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci err = detect_formats(dice); 19562306a36Sopenharmony_ci if (err < 0) 19662306a36Sopenharmony_ci goto error; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci err = snd_dice_stream_init_duplex(dice); 19962306a36Sopenharmony_ci if (err < 0) 20062306a36Sopenharmony_ci goto error; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci snd_dice_create_proc(dice); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci err = snd_dice_create_pcm(dice); 20562306a36Sopenharmony_ci if (err < 0) 20662306a36Sopenharmony_ci goto error; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci err = snd_dice_create_midi(dice); 20962306a36Sopenharmony_ci if (err < 0) 21062306a36Sopenharmony_ci goto error; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci err = snd_dice_create_hwdep(dice); 21362306a36Sopenharmony_ci if (err < 0) 21462306a36Sopenharmony_ci goto error; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci err = snd_card_register(card); 21762306a36Sopenharmony_ci if (err < 0) 21862306a36Sopenharmony_ci goto error; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_cierror: 22262306a36Sopenharmony_ci snd_card_free(card); 22362306a36Sopenharmony_ci return err; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic void dice_remove(struct fw_unit *unit) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci struct snd_dice *dice = dev_get_drvdata(&unit->device); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci // Block till all of ALSA character devices are released. 23162306a36Sopenharmony_ci snd_card_free(dice->card); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void dice_bus_reset(struct fw_unit *unit) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci struct snd_dice *dice = dev_get_drvdata(&unit->device); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* The handler address register becomes initialized. */ 23962306a36Sopenharmony_ci snd_dice_transaction_reinit(dice); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci mutex_lock(&dice->mutex); 24262306a36Sopenharmony_ci snd_dice_stream_update_duplex(dice); 24362306a36Sopenharmony_ci mutex_unlock(&dice->mutex); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define DICE_INTERFACE 0x000001 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci#define DICE_DEV_ENTRY_TYPICAL(vendor, model, data) \ 24962306a36Sopenharmony_ci { \ 25062306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 25162306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID | \ 25262306a36Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | \ 25362306a36Sopenharmony_ci IEEE1394_MATCH_VERSION, \ 25462306a36Sopenharmony_ci .vendor_id = (vendor), \ 25562306a36Sopenharmony_ci .model_id = (model), \ 25662306a36Sopenharmony_ci .specifier_id = (vendor), \ 25762306a36Sopenharmony_ci .version = DICE_INTERFACE, \ 25862306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)(data), \ 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic const struct ieee1394_device_id dice_id_table[] = { 26262306a36Sopenharmony_ci // Avid M-Box 3 Pro. To match in probe function. 26362306a36Sopenharmony_ci DICE_DEV_ENTRY_TYPICAL(OUI_AVID, 0x000004, snd_dice_detect_extension_formats), 26462306a36Sopenharmony_ci /* M-Audio Profire 2626 has a different value in version field. */ 26562306a36Sopenharmony_ci { 26662306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 26762306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 26862306a36Sopenharmony_ci .vendor_id = OUI_MAUDIO, 26962306a36Sopenharmony_ci .model_id = 0x000010, 27062306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats, 27162306a36Sopenharmony_ci }, 27262306a36Sopenharmony_ci /* M-Audio Profire 610 has a different value in version field. */ 27362306a36Sopenharmony_ci { 27462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 27562306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 27662306a36Sopenharmony_ci .vendor_id = OUI_MAUDIO, 27762306a36Sopenharmony_ci .model_id = 0x000011, 27862306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats, 27962306a36Sopenharmony_ci }, 28062306a36Sopenharmony_ci /* TC Electronic Konnekt 24D. */ 28162306a36Sopenharmony_ci { 28262306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 28362306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 28462306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 28562306a36Sopenharmony_ci .model_id = 0x000020, 28662306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 28762306a36Sopenharmony_ci }, 28862306a36Sopenharmony_ci /* TC Electronic Konnekt 8. */ 28962306a36Sopenharmony_ci { 29062306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 29162306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 29262306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 29362306a36Sopenharmony_ci .model_id = 0x000021, 29462306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 29562306a36Sopenharmony_ci }, 29662306a36Sopenharmony_ci /* TC Electronic Studio Konnekt 48. */ 29762306a36Sopenharmony_ci { 29862306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 29962306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 30062306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 30162306a36Sopenharmony_ci .model_id = 0x000022, 30262306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 30362306a36Sopenharmony_ci }, 30462306a36Sopenharmony_ci /* TC Electronic Konnekt Live. */ 30562306a36Sopenharmony_ci { 30662306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 30762306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 30862306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 30962306a36Sopenharmony_ci .model_id = 0x000023, 31062306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 31162306a36Sopenharmony_ci }, 31262306a36Sopenharmony_ci /* TC Electronic Desktop Konnekt 6. */ 31362306a36Sopenharmony_ci { 31462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 31562306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 31662306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 31762306a36Sopenharmony_ci .model_id = 0x000024, 31862306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 31962306a36Sopenharmony_ci }, 32062306a36Sopenharmony_ci /* TC Electronic Impact Twin. */ 32162306a36Sopenharmony_ci { 32262306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 32362306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 32462306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 32562306a36Sopenharmony_ci .model_id = 0x000027, 32662306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 32762306a36Sopenharmony_ci }, 32862306a36Sopenharmony_ci /* TC Electronic Digital Konnekt x32. */ 32962306a36Sopenharmony_ci { 33062306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 33162306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 33262306a36Sopenharmony_ci .vendor_id = OUI_TCELECTRONIC, 33362306a36Sopenharmony_ci .model_id = 0x000030, 33462306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats, 33562306a36Sopenharmony_ci }, 33662306a36Sopenharmony_ci /* Alesis iO14/iO26. */ 33762306a36Sopenharmony_ci { 33862306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 33962306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 34062306a36Sopenharmony_ci .vendor_id = OUI_ALESIS, 34162306a36Sopenharmony_ci .model_id = MODEL_ALESIS_IO_BOTH, 34262306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats, 34362306a36Sopenharmony_ci }, 34462306a36Sopenharmony_ci // Alesis MasterControl. 34562306a36Sopenharmony_ci { 34662306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 34762306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 34862306a36Sopenharmony_ci .vendor_id = OUI_ALESIS, 34962306a36Sopenharmony_ci .model_id = 0x000002, 35062306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats, 35162306a36Sopenharmony_ci }, 35262306a36Sopenharmony_ci /* Mytek Stereo 192 DSD-DAC. */ 35362306a36Sopenharmony_ci { 35462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 35562306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 35662306a36Sopenharmony_ci .vendor_id = OUI_MYTEK, 35762306a36Sopenharmony_ci .model_id = 0x000002, 35862306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci // Solid State Logic, Duende Classic and Mini. 36162306a36Sopenharmony_ci // NOTE: each field of GUID in config ROM is not compliant to standard 36262306a36Sopenharmony_ci // DICE scheme. 36362306a36Sopenharmony_ci { 36462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 36562306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 36662306a36Sopenharmony_ci .vendor_id = OUI_SSL, 36762306a36Sopenharmony_ci .model_id = 0x000070, 36862306a36Sopenharmony_ci }, 36962306a36Sopenharmony_ci // Presonus FireStudio. 37062306a36Sopenharmony_ci { 37162306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 37262306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 37362306a36Sopenharmony_ci .vendor_id = OUI_PRESONUS, 37462306a36Sopenharmony_ci .model_id = 0x000008, 37562306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, 37662306a36Sopenharmony_ci }, 37762306a36Sopenharmony_ci // Lexicon I-ONYX FW810S. 37862306a36Sopenharmony_ci { 37962306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 38062306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 38162306a36Sopenharmony_ci .vendor_id = OUI_HARMAN, 38262306a36Sopenharmony_ci .model_id = 0x000001, 38362306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_harman_formats, 38462306a36Sopenharmony_ci }, 38562306a36Sopenharmony_ci // Focusrite Saffire Pro 40 with TCD3070-CH. 38662306a36Sopenharmony_ci // The model has quirk in its GUID, in which model field is 0x000013 and different from 38762306a36Sopenharmony_ci // model ID (0x0000de) in its root/unit directory. 38862306a36Sopenharmony_ci { 38962306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 39062306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 39162306a36Sopenharmony_ci .vendor_id = OUI_FOCUSRITE, 39262306a36Sopenharmony_ci .model_id = 0x0000de, 39362306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_focusrite_pro40_tcd3070_formats, 39462306a36Sopenharmony_ci }, 39562306a36Sopenharmony_ci // Weiss DAC202: 192kHz 2-channel DAC 39662306a36Sopenharmony_ci { 39762306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 39862306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 39962306a36Sopenharmony_ci .model_id = 0x000007, 40062306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 40162306a36Sopenharmony_ci }, 40262306a36Sopenharmony_ci // Weiss DAC202: 192kHz 2-channel DAC (Maya edition) 40362306a36Sopenharmony_ci { 40462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 40562306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 40662306a36Sopenharmony_ci .model_id = 0x000008, 40762306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 40862306a36Sopenharmony_ci }, 40962306a36Sopenharmony_ci // Weiss MAN301: 192kHz 2-channel music archive network player 41062306a36Sopenharmony_ci { 41162306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 41262306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 41362306a36Sopenharmony_ci .model_id = 0x00000b, 41462306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 41562306a36Sopenharmony_ci }, 41662306a36Sopenharmony_ci // Weiss INT202: 192kHz unidirectional 2-channel digital Firewire face 41762306a36Sopenharmony_ci { 41862306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 41962306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 42062306a36Sopenharmony_ci .model_id = 0x000006, 42162306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 42262306a36Sopenharmony_ci }, 42362306a36Sopenharmony_ci // Weiss INT203: 192kHz bidirectional 2-channel digital Firewire face 42462306a36Sopenharmony_ci { 42562306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 42662306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 42762306a36Sopenharmony_ci .model_id = 0x00000a, 42862306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 42962306a36Sopenharmony_ci }, 43062306a36Sopenharmony_ci // Weiss ADC2: 192kHz A/D converter with microphone preamps and inputs 43162306a36Sopenharmony_ci { 43262306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 43362306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 43462306a36Sopenharmony_ci .model_id = 0x000001, 43562306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 43662306a36Sopenharmony_ci }, 43762306a36Sopenharmony_ci // Weiss DAC2/Minerva: 192kHz 2-channel DAC 43862306a36Sopenharmony_ci { 43962306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 44062306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 44162306a36Sopenharmony_ci .model_id = 0x000003, 44262306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 44362306a36Sopenharmony_ci }, 44462306a36Sopenharmony_ci // Weiss Vesta: 192kHz 2-channel Firewire to AES/EBU interface 44562306a36Sopenharmony_ci { 44662306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 44762306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 44862306a36Sopenharmony_ci .model_id = 0x000002, 44962306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 45062306a36Sopenharmony_ci }, 45162306a36Sopenharmony_ci // Weiss AFI1: 192kHz 24-channel Firewire to ADAT or AES/EBU face 45262306a36Sopenharmony_ci { 45362306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, 45462306a36Sopenharmony_ci .vendor_id = OUI_WEISS, 45562306a36Sopenharmony_ci .model_id = 0x000004, 45662306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, 45762306a36Sopenharmony_ci }, 45862306a36Sopenharmony_ci { 45962306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VERSION, 46062306a36Sopenharmony_ci .version = DICE_INTERFACE, 46162306a36Sopenharmony_ci }, 46262306a36Sopenharmony_ci { } 46362306a36Sopenharmony_ci}; 46462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, dice_id_table); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic struct fw_driver dice_driver = { 46762306a36Sopenharmony_ci .driver = { 46862306a36Sopenharmony_ci .owner = THIS_MODULE, 46962306a36Sopenharmony_ci .name = KBUILD_MODNAME, 47062306a36Sopenharmony_ci .bus = &fw_bus_type, 47162306a36Sopenharmony_ci }, 47262306a36Sopenharmony_ci .probe = dice_probe, 47362306a36Sopenharmony_ci .update = dice_bus_reset, 47462306a36Sopenharmony_ci .remove = dice_remove, 47562306a36Sopenharmony_ci .id_table = dice_id_table, 47662306a36Sopenharmony_ci}; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic int __init alsa_dice_init(void) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci return driver_register(&dice_driver.driver); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic void __exit alsa_dice_exit(void) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci driver_unregister(&dice_driver.driver); 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cimodule_init(alsa_dice_init); 48962306a36Sopenharmony_cimodule_exit(alsa_dice_exit); 490