162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * bebob.c - a part of driver for BeBoB based devices 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2013-2014 Takashi Sakamoto 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * BeBoB is 'BridgeCo enhanced Breakout Box'. This is installed to firewire 1062306a36Sopenharmony_ci * devices with DM1000/DM1100/DM1500 chipset. It gives common way for host 1162306a36Sopenharmony_ci * system to handle BeBoB based devices. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "bebob.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciMODULE_DESCRIPTION("BridgeCo BeBoB driver"); 1762306a36Sopenharmony_ciMODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>"); 1862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 2162306a36Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 2262306a36Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 2562306a36Sopenharmony_ciMODULE_PARM_DESC(index, "card index"); 2662306a36Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 2762306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string"); 2862306a36Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 2962306a36Sopenharmony_ciMODULE_PARM_DESC(enable, "enable BeBoB sound card"); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic DEFINE_MUTEX(devices_mutex); 3262306a36Sopenharmony_cistatic DECLARE_BITMAP(devices_used, SNDRV_CARDS); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Offsets from information register. */ 3562306a36Sopenharmony_ci#define INFO_OFFSET_BEBOB_VERSION 0x08 3662306a36Sopenharmony_ci#define INFO_OFFSET_GUID 0x10 3762306a36Sopenharmony_ci#define INFO_OFFSET_HW_MODEL_ID 0x18 3862306a36Sopenharmony_ci#define INFO_OFFSET_HW_MODEL_REVISION 0x1c 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define VEN_EDIROL 0x000040ab 4162306a36Sopenharmony_ci#define VEN_PRESONUS 0x00000a92 4262306a36Sopenharmony_ci#define VEN_BRIDGECO 0x000007f5 4362306a36Sopenharmony_ci#define VEN_MACKIE 0x00000ff2 4462306a36Sopenharmony_ci#define VEN_STANTON 0x00001260 4562306a36Sopenharmony_ci#define VEN_TASCAM 0x0000022e 4662306a36Sopenharmony_ci#define VEN_BEHRINGER 0x00001564 4762306a36Sopenharmony_ci#define VEN_APOGEE 0x000003db 4862306a36Sopenharmony_ci#define VEN_ESI 0x00000f1b 4962306a36Sopenharmony_ci#define VEN_CME 0x0000000a 5062306a36Sopenharmony_ci#define VEN_PHONIC 0x00001496 5162306a36Sopenharmony_ci#define VEN_LYNX 0x000019e5 5262306a36Sopenharmony_ci#define VEN_ICON 0x00001a9e 5362306a36Sopenharmony_ci#define VEN_PRISMSOUND 0x00001198 5462306a36Sopenharmony_ci#define VEN_TERRATEC 0x00000aac 5562306a36Sopenharmony_ci#define VEN_YAMAHA 0x0000a0de 5662306a36Sopenharmony_ci#define VEN_FOCUSRITE 0x0000130e 5762306a36Sopenharmony_ci#define VEN_MAUDIO 0x00000d6c 5862306a36Sopenharmony_ci#define VEN_DIGIDESIGN 0x00a07e 5962306a36Sopenharmony_ci#define OUI_SHOUYO 0x002327 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 6262306a36Sopenharmony_ci#define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 6362306a36Sopenharmony_ci#define MODEL_MAUDIO_FW1814 0x00010071 6462306a36Sopenharmony_ci#define MODEL_MAUDIO_PROJECTMIX 0x00010091 6562306a36Sopenharmony_ci#define MODEL_MAUDIO_PROFIRELIGHTBRIDGE 0x000100a1 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic int 6862306a36Sopenharmony_ciname_device(struct snd_bebob *bebob) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(bebob->unit); 7162306a36Sopenharmony_ci char vendor[24] = {0}; 7262306a36Sopenharmony_ci char model[32] = {0}; 7362306a36Sopenharmony_ci u32 hw_id; 7462306a36Sopenharmony_ci u32 data[2] = {0}; 7562306a36Sopenharmony_ci u32 revision; 7662306a36Sopenharmony_ci int err; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* get vendor name from root directory */ 7962306a36Sopenharmony_ci err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR, 8062306a36Sopenharmony_ci vendor, sizeof(vendor)); 8162306a36Sopenharmony_ci if (err < 0) 8262306a36Sopenharmony_ci goto end; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* get model name from unit directory */ 8562306a36Sopenharmony_ci err = fw_csr_string(bebob->unit->directory, CSR_MODEL, 8662306a36Sopenharmony_ci model, sizeof(model)); 8762306a36Sopenharmony_ci if (err < 0) 8862306a36Sopenharmony_ci goto end; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* get hardware id */ 9162306a36Sopenharmony_ci err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_HW_MODEL_ID, 9262306a36Sopenharmony_ci &hw_id); 9362306a36Sopenharmony_ci if (err < 0) 9462306a36Sopenharmony_ci goto end; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* get hardware revision */ 9762306a36Sopenharmony_ci err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_HW_MODEL_REVISION, 9862306a36Sopenharmony_ci &revision); 9962306a36Sopenharmony_ci if (err < 0) 10062306a36Sopenharmony_ci goto end; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* get GUID */ 10362306a36Sopenharmony_ci err = snd_bebob_read_block(bebob->unit, INFO_OFFSET_GUID, 10462306a36Sopenharmony_ci data, sizeof(data)); 10562306a36Sopenharmony_ci if (err < 0) 10662306a36Sopenharmony_ci goto end; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci strcpy(bebob->card->driver, "BeBoB"); 10962306a36Sopenharmony_ci strcpy(bebob->card->shortname, model); 11062306a36Sopenharmony_ci strcpy(bebob->card->mixername, model); 11162306a36Sopenharmony_ci snprintf(bebob->card->longname, sizeof(bebob->card->longname), 11262306a36Sopenharmony_ci "%s %s (id:%d, rev:%d), GUID %08x%08x at %s, S%d", 11362306a36Sopenharmony_ci vendor, model, hw_id, revision, 11462306a36Sopenharmony_ci data[0], data[1], dev_name(&bebob->unit->device), 11562306a36Sopenharmony_ci 100 << fw_dev->max_speed); 11662306a36Sopenharmony_ciend: 11762306a36Sopenharmony_ci return err; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void 12162306a36Sopenharmony_cibebob_card_free(struct snd_card *card) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct snd_bebob *bebob = card->private_data; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci mutex_lock(&devices_mutex); 12662306a36Sopenharmony_ci clear_bit(bebob->card_index, devices_used); 12762306a36Sopenharmony_ci mutex_unlock(&devices_mutex); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci snd_bebob_stream_destroy_duplex(bebob); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci mutex_destroy(&bebob->mutex); 13262306a36Sopenharmony_ci fw_unit_put(bebob->unit); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic const struct snd_bebob_spec * 13662306a36Sopenharmony_ciget_saffire_spec(struct fw_unit *unit) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci char name[24] = {0}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0) 14162306a36Sopenharmony_ci return NULL; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (strcmp(name, "SaffireLE") == 0) 14462306a36Sopenharmony_ci return &saffire_le_spec; 14562306a36Sopenharmony_ci else 14662306a36Sopenharmony_ci return &saffire_spec; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic bool 15062306a36Sopenharmony_cicheck_audiophile_booted(struct fw_unit *unit) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci char name[28] = {0}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0) 15562306a36Sopenharmony_ci return false; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return strncmp(name, "FW Audiophile Bootloader", 24) != 0; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic int detect_quirks(struct snd_bebob *bebob, const struct ieee1394_device_id *entry) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci if (entry->vendor_id == VEN_MAUDIO) { 16362306a36Sopenharmony_ci switch (entry->model_id) { 16462306a36Sopenharmony_ci case MODEL_MAUDIO_PROFIRELIGHTBRIDGE: 16562306a36Sopenharmony_ci // M-Audio ProFire Lightbridge has a quirk to transfer packets with 16662306a36Sopenharmony_ci // discontinuous cycle or data block counter in early stage of packet 16762306a36Sopenharmony_ci // streaming. The cycle span from the first packet with event is variable. 16862306a36Sopenharmony_ci bebob->quirks |= SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC; 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci case MODEL_MAUDIO_FW1814: 17162306a36Sopenharmony_ci case MODEL_MAUDIO_PROJECTMIX: 17262306a36Sopenharmony_ci // At high sampling rate, M-Audio special firmware transmits empty packet 17362306a36Sopenharmony_ci // with the value of dbc incremented by 8. 17462306a36Sopenharmony_ci bebob->quirks |= SND_BEBOB_QUIRK_WRONG_DBC; 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci default: 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return 0; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic int bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci unsigned int card_index; 18762306a36Sopenharmony_ci struct snd_card *card; 18862306a36Sopenharmony_ci struct snd_bebob *bebob; 18962306a36Sopenharmony_ci const struct snd_bebob_spec *spec; 19062306a36Sopenharmony_ci int err; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (entry->vendor_id == VEN_FOCUSRITE && 19362306a36Sopenharmony_ci entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH) 19462306a36Sopenharmony_ci spec = get_saffire_spec(unit); 19562306a36Sopenharmony_ci else if (entry->vendor_id == VEN_MAUDIO && 19662306a36Sopenharmony_ci entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH && 19762306a36Sopenharmony_ci !check_audiophile_booted(unit)) 19862306a36Sopenharmony_ci spec = NULL; 19962306a36Sopenharmony_ci else 20062306a36Sopenharmony_ci spec = (const struct snd_bebob_spec *)entry->driver_data; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (spec == NULL) { 20362306a36Sopenharmony_ci // To boot up M-Audio models. 20462306a36Sopenharmony_ci if (entry->vendor_id == VEN_MAUDIO || entry->vendor_id == VEN_BRIDGECO) 20562306a36Sopenharmony_ci return snd_bebob_maudio_load_firmware(unit); 20662306a36Sopenharmony_ci else 20762306a36Sopenharmony_ci return -ENODEV; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci mutex_lock(&devices_mutex); 21162306a36Sopenharmony_ci for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { 21262306a36Sopenharmony_ci if (!test_bit(card_index, devices_used) && enable[card_index]) 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci if (card_index >= SNDRV_CARDS) { 21662306a36Sopenharmony_ci mutex_unlock(&devices_mutex); 21762306a36Sopenharmony_ci return -ENOENT; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, 22162306a36Sopenharmony_ci sizeof(*bebob), &card); 22262306a36Sopenharmony_ci if (err < 0) { 22362306a36Sopenharmony_ci mutex_unlock(&devices_mutex); 22462306a36Sopenharmony_ci return err; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci card->private_free = bebob_card_free; 22762306a36Sopenharmony_ci set_bit(card_index, devices_used); 22862306a36Sopenharmony_ci mutex_unlock(&devices_mutex); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci bebob = card->private_data; 23162306a36Sopenharmony_ci bebob->unit = fw_unit_get(unit); 23262306a36Sopenharmony_ci dev_set_drvdata(&unit->device, bebob); 23362306a36Sopenharmony_ci bebob->card = card; 23462306a36Sopenharmony_ci bebob->card_index = card_index; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci bebob->spec = spec; 23762306a36Sopenharmony_ci mutex_init(&bebob->mutex); 23862306a36Sopenharmony_ci spin_lock_init(&bebob->lock); 23962306a36Sopenharmony_ci init_waitqueue_head(&bebob->hwdep_wait); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci err = name_device(bebob); 24262306a36Sopenharmony_ci if (err < 0) 24362306a36Sopenharmony_ci goto error; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci err = detect_quirks(bebob, entry); 24662306a36Sopenharmony_ci if (err < 0) 24762306a36Sopenharmony_ci goto error; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (bebob->spec == &maudio_special_spec) { 25062306a36Sopenharmony_ci if (entry->model_id == MODEL_MAUDIO_FW1814) 25162306a36Sopenharmony_ci err = snd_bebob_maudio_special_discover(bebob, true); 25262306a36Sopenharmony_ci else 25362306a36Sopenharmony_ci err = snd_bebob_maudio_special_discover(bebob, false); 25462306a36Sopenharmony_ci } else { 25562306a36Sopenharmony_ci err = snd_bebob_stream_discover(bebob); 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci if (err < 0) 25862306a36Sopenharmony_ci goto error; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci err = snd_bebob_stream_init_duplex(bebob); 26162306a36Sopenharmony_ci if (err < 0) 26262306a36Sopenharmony_ci goto error; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci snd_bebob_proc_init(bebob); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (bebob->midi_input_ports > 0 || bebob->midi_output_ports > 0) { 26762306a36Sopenharmony_ci err = snd_bebob_create_midi_devices(bebob); 26862306a36Sopenharmony_ci if (err < 0) 26962306a36Sopenharmony_ci goto error; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci err = snd_bebob_create_pcm_devices(bebob); 27362306a36Sopenharmony_ci if (err < 0) 27462306a36Sopenharmony_ci goto error; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci err = snd_bebob_create_hwdep_device(bebob); 27762306a36Sopenharmony_ci if (err < 0) 27862306a36Sopenharmony_ci goto error; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci err = snd_card_register(card); 28162306a36Sopenharmony_ci if (err < 0) 28262306a36Sopenharmony_ci goto error; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (entry->vendor_id == VEN_MAUDIO && 28562306a36Sopenharmony_ci (entry->model_id == MODEL_MAUDIO_FW1814 || entry->model_id == MODEL_MAUDIO_PROJECTMIX)) { 28662306a36Sopenharmony_ci // This is a workaround. This bus reset seems to have an effect to make devices 28762306a36Sopenharmony_ci // correctly handling transactions. Without this, the devices have gap_count 28862306a36Sopenharmony_ci // mismatch. This causes much failure of transaction. 28962306a36Sopenharmony_ci // 29062306a36Sopenharmony_ci // Just after registration, user-land application receive signals from dbus and 29162306a36Sopenharmony_ci // starts I/Os. To avoid I/Os till the future bus reset, registration is done in 29262306a36Sopenharmony_ci // next update(). 29362306a36Sopenharmony_ci fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, false, true); 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return 0; 29762306a36Sopenharmony_cierror: 29862306a36Sopenharmony_ci snd_card_free(card); 29962306a36Sopenharmony_ci return err; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci/* 30362306a36Sopenharmony_ci * This driver doesn't update streams in bus reset handler. 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * DM1000/ DM1100/DM1500 chipsets with BeBoB firmware transfer packets with 30662306a36Sopenharmony_ci * discontinued counter at bus reset. This discontinuity is immediately 30762306a36Sopenharmony_ci * detected in packet streaming layer, then it sets XRUN to PCM substream. 30862306a36Sopenharmony_ci * 30962306a36Sopenharmony_ci * ALSA PCM applications can know the XRUN by getting -EPIPE from PCM operation. 31062306a36Sopenharmony_ci * Then, they can recover the PCM substream by executing ioctl(2) with 31162306a36Sopenharmony_ci * SNDRV_PCM_IOCTL_PREPARE. 'struct snd_pcm_ops.prepare' is called and drivers 31262306a36Sopenharmony_ci * restart packet streaming. 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * The above processing may be executed before this bus-reset handler is 31562306a36Sopenharmony_ci * executed. When this handler updates streams with current isochronous 31662306a36Sopenharmony_ci * channels, the streams already have the current ones. 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_cistatic void 31962306a36Sopenharmony_cibebob_update(struct fw_unit *unit) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct snd_bebob *bebob = dev_get_drvdata(&unit->device); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (bebob == NULL) 32462306a36Sopenharmony_ci return; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci fcp_bus_reset(bebob->unit); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic void bebob_remove(struct fw_unit *unit) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci struct snd_bebob *bebob = dev_get_drvdata(&unit->device); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (bebob == NULL) 33462306a36Sopenharmony_ci return; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci // Block till all of ALSA character devices are released. 33762306a36Sopenharmony_ci snd_card_free(bebob->card); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic const struct snd_bebob_rate_spec normal_rate_spec = { 34162306a36Sopenharmony_ci .get = &snd_bebob_stream_get_rate, 34262306a36Sopenharmony_ci .set = &snd_bebob_stream_set_rate 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_cistatic const struct snd_bebob_spec spec_normal = { 34562306a36Sopenharmony_ci .clock = NULL, 34662306a36Sopenharmony_ci .rate = &normal_rate_spec, 34762306a36Sopenharmony_ci .meter = NULL 34862306a36Sopenharmony_ci}; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci#define SPECIFIER_1394TA 0x00a02d 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci// The immediate entry for version in unit directory differs depending on models: 35362306a36Sopenharmony_ci// * 0x010001 35462306a36Sopenharmony_ci// * 0x014001 35562306a36Sopenharmony_ci#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ 35662306a36Sopenharmony_ci{ \ 35762306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 35862306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID | \ 35962306a36Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID, \ 36062306a36Sopenharmony_ci .vendor_id = vendor, \ 36162306a36Sopenharmony_ci .model_id = model, \ 36262306a36Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, \ 36362306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)data \ 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic const struct ieee1394_device_id bebob_id_table[] = { 36762306a36Sopenharmony_ci /* Edirol, FA-66 */ 36862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049, &spec_normal), 36962306a36Sopenharmony_ci /* Edirol, FA-101 */ 37062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010048, &spec_normal), 37162306a36Sopenharmony_ci /* Presonus, FIREBOX */ 37262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010000, &spec_normal), 37362306a36Sopenharmony_ci /* PreSonus, FIREPOD/FP10 */ 37462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010066, &spec_normal), 37562306a36Sopenharmony_ci /* PreSonus, Inspire1394 */ 37662306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010001, &spec_normal), 37762306a36Sopenharmony_ci /* BridgeCo, RDAudio1 */ 37862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010048, &spec_normal), 37962306a36Sopenharmony_ci /* BridgeCo, Audio5 */ 38062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), 38162306a36Sopenharmony_ci /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ 38262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal), 38362306a36Sopenharmony_ci // Mackie, d.2 (optional Firewire card with DM1000). 38462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal), 38562306a36Sopenharmony_ci /* Stanton, ScratchAmp */ 38662306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), 38762306a36Sopenharmony_ci /* Tascam, IF-FW DM */ 38862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TASCAM, 0x00010067, &spec_normal), 38962306a36Sopenharmony_ci /* Behringer, XENIX UFX 1204 */ 39062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001204, &spec_normal), 39162306a36Sopenharmony_ci /* Behringer, XENIX UFX 1604 */ 39262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), 39362306a36Sopenharmony_ci /* Behringer, Digital Mixer X32 series (X-UF Card) */ 39462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), 39562306a36Sopenharmony_ci /* Behringer, F-Control Audio 1616 */ 39662306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x001616, &spec_normal), 39762306a36Sopenharmony_ci /* Behringer, F-Control Audio 610 */ 39862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x000610, &spec_normal), 39962306a36Sopenharmony_ci /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ 40062306a36Sopenharmony_ci /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ 40162306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), 40262306a36Sopenharmony_ci /* Apogee Electronics, Ensemble */ 40362306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x01eeee, &spec_normal), 40462306a36Sopenharmony_ci /* ESI, Quatafire610 */ 40562306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal), 40662306a36Sopenharmony_ci /* CME, MatrixKFW */ 40762306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000, &spec_normal), 40862306a36Sopenharmony_ci // Phonic Helix Board 12 FireWire MkII. 40962306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000, &spec_normal), 41062306a36Sopenharmony_ci // Phonic Helix Board 18 FireWire MkII. 41162306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000, &spec_normal), 41262306a36Sopenharmony_ci // Phonic Helix Board 24 FireWire MkII. 41362306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000, &spec_normal), 41462306a36Sopenharmony_ci // Phonic FireFly 808 FireWire. 41562306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00080000, &spec_normal), 41662306a36Sopenharmony_ci // Phonic FireFly 202, 302, 808 Universal. 41762306a36Sopenharmony_ci // Phinic Helix Board 12/18/24 FireWire, 12/18/24 Universal 41862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000, &spec_normal), 41962306a36Sopenharmony_ci /* Lynx, Aurora 8/16 (LT-FW) */ 42062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001, &spec_normal), 42162306a36Sopenharmony_ci /* ICON, FireXon */ 42262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_ICON, 0x00000001, &spec_normal), 42362306a36Sopenharmony_ci /* PrismSound, Orpheus */ 42462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x00010048, &spec_normal), 42562306a36Sopenharmony_ci /* PrismSound, ADA-8XR */ 42662306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x0000ada8, &spec_normal), 42762306a36Sopenharmony_ci /* TerraTec Electronic GmbH, PHASE 88 Rack FW */ 42862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000003, &phase88_rack_spec), 42962306a36Sopenharmony_ci /* TerraTec Electronic GmbH, PHASE 24 FW */ 43062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &yamaha_terratec_spec), 43162306a36Sopenharmony_ci /* TerraTec Electronic GmbH, Phase X24 FW */ 43262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &yamaha_terratec_spec), 43362306a36Sopenharmony_ci /* TerraTec Electronic GmbH, EWS MIC2/MIC8 */ 43462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000005, &spec_normal), 43562306a36Sopenharmony_ci // Terratec Electronic GmbH, Aureon 7.1 Firewire. 43662306a36Sopenharmony_ci // AcousticReality, eAR Master One, Eroica, Figaro, and Ciaccona. Perhaps Terratec OEM. 43762306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal), 43862306a36Sopenharmony_ci /* Yamaha, GO44 */ 43962306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_terratec_spec), 44062306a36Sopenharmony_ci /* YAMAHA, GO46 */ 44162306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_terratec_spec), 44262306a36Sopenharmony_ci /* Focusrite, SaffirePro 26 I/O */ 44362306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec), 44462306a36Sopenharmony_ci /* Focusrite, SaffirePro 10 I/O */ 44562306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x000006, &saffirepro_10_spec), 44662306a36Sopenharmony_ci /* Focusrite, Saffire(no label and LE) */ 44762306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH, 44862306a36Sopenharmony_ci &saffire_spec), 44962306a36Sopenharmony_ci // M-Audio, Firewire 410. The vendor field is left as BridgeCo. AG. 45062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010058, NULL), 45162306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010046, &maudio_fw410_spec), 45262306a36Sopenharmony_ci /* M-Audio, Firewire Audiophile */ 45362306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_AUDIOPHILE_BOTH, 45462306a36Sopenharmony_ci &maudio_audiophile_spec), 45562306a36Sopenharmony_ci /* M-Audio, Firewire Solo */ 45662306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010062, &maudio_solo_spec), 45762306a36Sopenharmony_ci /* M-Audio, Ozonic */ 45862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x0000000a, &maudio_ozonic_spec), 45962306a36Sopenharmony_ci /* M-Audio NRV10 */ 46062306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010081, &maudio_nrv10_spec), 46162306a36Sopenharmony_ci /* M-Audio, ProFireLightbridge */ 46262306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROFIRELIGHTBRIDGE, &spec_normal), 46362306a36Sopenharmony_ci /* Firewire 1814 */ 46462306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010070, NULL), /* bootloader */ 46562306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_FW1814, 46662306a36Sopenharmony_ci &maudio_special_spec), 46762306a36Sopenharmony_ci /* M-Audio ProjectMix */ 46862306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROJECTMIX, 46962306a36Sopenharmony_ci &maudio_special_spec), 47062306a36Sopenharmony_ci /* Digidesign Mbox 2 Pro */ 47162306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), 47262306a36Sopenharmony_ci // Toneweal FW66. 47362306a36Sopenharmony_ci SND_BEBOB_DEV_ENTRY(OUI_SHOUYO, 0x020002, &spec_normal), 47462306a36Sopenharmony_ci /* IDs are unknown but able to be supported */ 47562306a36Sopenharmony_ci /* Apogee, Mini-ME Firewire */ 47662306a36Sopenharmony_ci /* Apogee, Mini-DAC Firewire */ 47762306a36Sopenharmony_ci /* Cakawalk, Sonar Power Studio 66 */ 47862306a36Sopenharmony_ci /* CME, UF400e */ 47962306a36Sopenharmony_ci /* ESI, Quotafire XL */ 48062306a36Sopenharmony_ci /* Infrasonic, DewX */ 48162306a36Sopenharmony_ci /* Infrasonic, Windy6 */ 48262306a36Sopenharmony_ci /* Mackie, Digital X Bus x.200 */ 48362306a36Sopenharmony_ci /* Mackie, Digital X Bus x.400 */ 48462306a36Sopenharmony_ci /* Rolf Spuler, Firewire Guitar */ 48562306a36Sopenharmony_ci {} 48662306a36Sopenharmony_ci}; 48762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, bebob_id_table); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic struct fw_driver bebob_driver = { 49062306a36Sopenharmony_ci .driver = { 49162306a36Sopenharmony_ci .owner = THIS_MODULE, 49262306a36Sopenharmony_ci .name = KBUILD_MODNAME, 49362306a36Sopenharmony_ci .bus = &fw_bus_type, 49462306a36Sopenharmony_ci }, 49562306a36Sopenharmony_ci .probe = bebob_probe, 49662306a36Sopenharmony_ci .update = bebob_update, 49762306a36Sopenharmony_ci .remove = bebob_remove, 49862306a36Sopenharmony_ci .id_table = bebob_id_table, 49962306a36Sopenharmony_ci}; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int __init 50262306a36Sopenharmony_cisnd_bebob_init(void) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci return driver_register(&bebob_driver.driver); 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic void __exit 50862306a36Sopenharmony_cisnd_bebob_exit(void) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci driver_unregister(&bebob_driver.driver); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cimodule_init(snd_bebob_init); 51462306a36Sopenharmony_cimodule_exit(snd_bebob_exit); 515