162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * oxfw.c - a part of driver for OXFW970/971 based devices 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "oxfw.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) 1162306a36Sopenharmony_ci/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020) 1462306a36Sopenharmony_ci#define OXFORD_HARDWARE_ID_OXFW970 0x39443841 1562306a36Sopenharmony_ci#define OXFORD_HARDWARE_ID_OXFW971 0x39373100 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define VENDOR_LOUD 0x000ff2 1862306a36Sopenharmony_ci#define VENDOR_GRIFFIN 0x001292 1962306a36Sopenharmony_ci#define VENDOR_BEHRINGER 0x001564 2062306a36Sopenharmony_ci#define VENDOR_LACIE 0x00d04b 2162306a36Sopenharmony_ci#define VENDOR_TASCAM 0x00022e 2262306a36Sopenharmony_ci#define OUI_STANTON 0x001260 2362306a36Sopenharmony_ci#define OUI_APOGEE 0x0003db 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define MODEL_SATELLITE 0x00200f 2662306a36Sopenharmony_ci#define MODEL_SCS1M 0x001000 2762306a36Sopenharmony_ci#define MODEL_DUET_FW 0x01dddd 2862306a36Sopenharmony_ci#define MODEL_ONYX_1640I 0x001640 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define SPECIFIER_1394TA 0x00a02d 3162306a36Sopenharmony_ci#define VERSION_AVC 0x010001 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciMODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver"); 3462306a36Sopenharmony_ciMODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 3562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 3662306a36Sopenharmony_ciMODULE_ALIAS("snd-firewire-speakers"); 3762306a36Sopenharmony_ciMODULE_ALIAS("snd-scs1x"); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct compat_info { 4062306a36Sopenharmony_ci const char *driver_name; 4162306a36Sopenharmony_ci const char *vendor_name; 4262306a36Sopenharmony_ci const char *model_name; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic bool detect_loud_models(struct fw_unit *unit) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci static const char *const models[] = { 4862306a36Sopenharmony_ci "Onyxi", 4962306a36Sopenharmony_ci "Onyx-i", 5062306a36Sopenharmony_ci "Onyx 1640i", 5162306a36Sopenharmony_ci "d.Pro", 5262306a36Sopenharmony_ci "U.420"}; 5362306a36Sopenharmony_ci char model[32]; 5462306a36Sopenharmony_ci int err; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci err = fw_csr_string(unit->directory, CSR_MODEL, 5762306a36Sopenharmony_ci model, sizeof(model)); 5862306a36Sopenharmony_ci if (err < 0) 5962306a36Sopenharmony_ci return false; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return match_string(models, ARRAY_SIZE(models), model) >= 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(oxfw->unit); 6762306a36Sopenharmony_ci const struct compat_info *info; 6862306a36Sopenharmony_ci char vendor[24]; 6962306a36Sopenharmony_ci char model[32]; 7062306a36Sopenharmony_ci const char *d, *v, *m; 7162306a36Sopenharmony_ci u32 firmware; 7262306a36Sopenharmony_ci int err; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* get vendor name from root directory */ 7562306a36Sopenharmony_ci err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR, 7662306a36Sopenharmony_ci vendor, sizeof(vendor)); 7762306a36Sopenharmony_ci if (err < 0) 7862306a36Sopenharmony_ci goto end; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* get model name from unit directory */ 8162306a36Sopenharmony_ci err = fw_csr_string(oxfw->unit->directory, CSR_MODEL, 8262306a36Sopenharmony_ci model, sizeof(model)); 8362306a36Sopenharmony_ci if (err < 0) 8462306a36Sopenharmony_ci goto end; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST, 8762306a36Sopenharmony_ci OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0); 8862306a36Sopenharmony_ci if (err < 0) 8962306a36Sopenharmony_ci goto end; 9062306a36Sopenharmony_ci be32_to_cpus(&firmware); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (firmware >> 20 == 0x970) 9362306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_JUMBO_PAYLOAD; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* to apply card definitions */ 9662306a36Sopenharmony_ci if (entry->vendor_id == VENDOR_GRIFFIN || entry->vendor_id == VENDOR_LACIE) { 9762306a36Sopenharmony_ci info = (const struct compat_info *)entry->driver_data; 9862306a36Sopenharmony_ci d = info->driver_name; 9962306a36Sopenharmony_ci v = info->vendor_name; 10062306a36Sopenharmony_ci m = info->model_name; 10162306a36Sopenharmony_ci } else { 10262306a36Sopenharmony_ci d = "OXFW"; 10362306a36Sopenharmony_ci v = vendor; 10462306a36Sopenharmony_ci m = model; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci strcpy(oxfw->card->driver, d); 10862306a36Sopenharmony_ci strcpy(oxfw->card->mixername, m); 10962306a36Sopenharmony_ci strcpy(oxfw->card->shortname, m); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci scnprintf(oxfw->card->longname, sizeof(oxfw->card->longname), 11262306a36Sopenharmony_ci "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d", 11362306a36Sopenharmony_ci v, m, firmware >> 20, firmware & 0xffff, 11462306a36Sopenharmony_ci fw_dev->config_rom[3], fw_dev->config_rom[4], 11562306a36Sopenharmony_ci dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed); 11662306a36Sopenharmony_ciend: 11762306a36Sopenharmony_ci return err; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void oxfw_card_free(struct snd_card *card) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct snd_oxfw *oxfw = card->private_data; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) 12562306a36Sopenharmony_ci snd_oxfw_stream_destroy_duplex(oxfw); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci mutex_destroy(&oxfw->mutex); 12862306a36Sopenharmony_ci fw_unit_put(oxfw->unit); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(oxfw->unit); 13462306a36Sopenharmony_ci struct fw_csr_iterator it; 13562306a36Sopenharmony_ci int key, val; 13662306a36Sopenharmony_ci int vendor, model; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* 13962306a36Sopenharmony_ci * Add ALSA control elements for two models to keep compatibility to 14062306a36Sopenharmony_ci * old firewire-speaker module. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci if (entry->vendor_id == VENDOR_GRIFFIN) 14362306a36Sopenharmony_ci return snd_oxfw_add_spkr(oxfw, false); 14462306a36Sopenharmony_ci if (entry->vendor_id == VENDOR_LACIE) 14562306a36Sopenharmony_ci return snd_oxfw_add_spkr(oxfw, true); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* 14862306a36Sopenharmony_ci * Stanton models supports asynchronous transactions for unique MIDI 14962306a36Sopenharmony_ci * messages. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci if (entry->vendor_id == OUI_STANTON) { 15262306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_SCS_TRANSACTION; 15362306a36Sopenharmony_ci if (entry->model_id == MODEL_SCS1M) 15462306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci // No physical MIDI ports. 15762306a36Sopenharmony_ci oxfw->midi_input_ports = 0; 15862306a36Sopenharmony_ci oxfw->midi_output_ports = 0; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return snd_oxfw_scs1x_add(oxfw); 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW) { 16462306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION | 16562306a36Sopenharmony_ci SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* 16962306a36Sopenharmony_ci * TASCAM FireOne has physical control and requires a pair of additional 17062306a36Sopenharmony_ci * MIDI ports. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci if (entry->vendor_id == VENDOR_TASCAM) { 17362306a36Sopenharmony_ci oxfw->midi_input_ports++; 17462306a36Sopenharmony_ci oxfw->midi_output_ports++; 17562306a36Sopenharmony_ci return 0; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* Seek from Root Directory of Config ROM. */ 17962306a36Sopenharmony_ci vendor = model = 0; 18062306a36Sopenharmony_ci fw_csr_iterator_init(&it, fw_dev->config_rom + 5); 18162306a36Sopenharmony_ci while (fw_csr_iterator_next(&it, &key, &val)) { 18262306a36Sopenharmony_ci if (key == CSR_VENDOR) 18362306a36Sopenharmony_ci vendor = val; 18462306a36Sopenharmony_ci else if (key == CSR_MODEL) 18562306a36Sopenharmony_ci model = val; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (vendor == VENDOR_LOUD) { 18962306a36Sopenharmony_ci // Mackie Onyx Satellite with base station has a quirk to report a wrong 19062306a36Sopenharmony_ci // value in 'dbs' field of CIP header against its format information. 19162306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci // OXFW971-based models may transfer events by blocking method. 19462306a36Sopenharmony_ci if (!(oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)) 19562306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (model == MODEL_ONYX_1640I) { 19862306a36Sopenharmony_ci //Unless receiving packets without NOINFO packet, the device transfers 19962306a36Sopenharmony_ci //mostly half of events in packets than expected. 20062306a36Sopenharmony_ci oxfw->quirks |= SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET | 20162306a36Sopenharmony_ci SND_OXFW_QUIRK_VOLUNTARY_RECOVERY; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int oxfw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct snd_card *card; 21162306a36Sopenharmony_ci struct snd_oxfw *oxfw; 21262306a36Sopenharmony_ci int err; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (entry->vendor_id == VENDOR_LOUD && entry->model_id == 0 && !detect_loud_models(unit)) 21562306a36Sopenharmony_ci return -ENODEV; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*oxfw), &card); 21862306a36Sopenharmony_ci if (err < 0) 21962306a36Sopenharmony_ci return err; 22062306a36Sopenharmony_ci card->private_free = oxfw_card_free; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci oxfw = card->private_data; 22362306a36Sopenharmony_ci oxfw->unit = fw_unit_get(unit); 22462306a36Sopenharmony_ci dev_set_drvdata(&unit->device, oxfw); 22562306a36Sopenharmony_ci oxfw->card = card; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci mutex_init(&oxfw->mutex); 22862306a36Sopenharmony_ci spin_lock_init(&oxfw->lock); 22962306a36Sopenharmony_ci init_waitqueue_head(&oxfw->hwdep_wait); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci err = name_card(oxfw, entry); 23262306a36Sopenharmony_ci if (err < 0) 23362306a36Sopenharmony_ci goto error; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci err = snd_oxfw_stream_discover(oxfw); 23662306a36Sopenharmony_ci if (err < 0) 23762306a36Sopenharmony_ci goto error; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci err = detect_quirks(oxfw, entry); 24062306a36Sopenharmony_ci if (err < 0) 24162306a36Sopenharmony_ci goto error; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) { 24462306a36Sopenharmony_ci err = snd_oxfw_stream_init_duplex(oxfw); 24562306a36Sopenharmony_ci if (err < 0) 24662306a36Sopenharmony_ci goto error; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci err = snd_oxfw_create_pcm(oxfw); 24962306a36Sopenharmony_ci if (err < 0) 25062306a36Sopenharmony_ci goto error; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci snd_oxfw_proc_init(oxfw); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci err = snd_oxfw_create_midi(oxfw); 25562306a36Sopenharmony_ci if (err < 0) 25662306a36Sopenharmony_ci goto error; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci err = snd_oxfw_create_hwdep(oxfw); 25962306a36Sopenharmony_ci if (err < 0) 26062306a36Sopenharmony_ci goto error; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci err = snd_card_register(card); 26462306a36Sopenharmony_ci if (err < 0) 26562306a36Sopenharmony_ci goto error; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_cierror: 26962306a36Sopenharmony_ci snd_card_free(card); 27062306a36Sopenharmony_ci return err; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic void oxfw_bus_reset(struct fw_unit *unit) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci fcp_bus_reset(oxfw->unit); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) { 28062306a36Sopenharmony_ci mutex_lock(&oxfw->mutex); 28162306a36Sopenharmony_ci snd_oxfw_stream_update_duplex(oxfw); 28262306a36Sopenharmony_ci mutex_unlock(&oxfw->mutex); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (oxfw->quirks & SND_OXFW_QUIRK_SCS_TRANSACTION) 28662306a36Sopenharmony_ci snd_oxfw_scs1x_update(oxfw); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic void oxfw_remove(struct fw_unit *unit) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci // Block till all of ALSA character devices are released. 29462306a36Sopenharmony_ci snd_card_free(oxfw->card); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct compat_info griffin_firewave = { 29862306a36Sopenharmony_ci .driver_name = "FireWave", 29962306a36Sopenharmony_ci .vendor_name = "Griffin", 30062306a36Sopenharmony_ci .model_name = "FireWave", 30162306a36Sopenharmony_ci}; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic const struct compat_info lacie_speakers = { 30462306a36Sopenharmony_ci .driver_name = "FWSpeakers", 30562306a36Sopenharmony_ci .vendor_name = "LaCie", 30662306a36Sopenharmony_ci .model_name = "FireWire Speakers", 30762306a36Sopenharmony_ci}; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci#define OXFW_DEV_ENTRY(vendor, model, data) \ 31062306a36Sopenharmony_ci{ \ 31162306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 31262306a36Sopenharmony_ci IEEE1394_MATCH_MODEL_ID | \ 31362306a36Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | \ 31462306a36Sopenharmony_ci IEEE1394_MATCH_VERSION, \ 31562306a36Sopenharmony_ci .vendor_id = vendor, \ 31662306a36Sopenharmony_ci .model_id = model, \ 31762306a36Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, \ 31862306a36Sopenharmony_ci .version = VERSION_AVC, \ 31962306a36Sopenharmony_ci .driver_data = (kernel_ulong_t)data, \ 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic const struct ieee1394_device_id oxfw_id_table[] = { 32362306a36Sopenharmony_ci // 32462306a36Sopenharmony_ci // OXFW970 devices: 32562306a36Sopenharmony_ci // Initial firmware has a quirk to postpone isoc packet transmission during finishing async 32662306a36Sopenharmony_ci // transaction. As a result, several isochronous cycles are skipped to transfer the packets 32762306a36Sopenharmony_ci // and the audio data frames which should have been transferred during the cycles are put 32862306a36Sopenharmony_ci // into packet at the first isoc cycle after the postpone. Furthermore, the value of SYT 32962306a36Sopenharmony_ci // field in CIP header is not reliable as synchronization timing, 33062306a36Sopenharmony_ci // 33162306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_GRIFFIN, 0x00f970, &griffin_firewave), 33262306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_LACIE, 0x00f970, &lacie_speakers), 33362306a36Sopenharmony_ci // Behringer,F-Control Audio 202. The value of SYT field is not reliable at all. 33462306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_BEHRINGER, 0x00fc22, NULL), 33562306a36Sopenharmony_ci // Loud Technologies, Tapco Link.FireWire 4x6. The value of SYT field is always 0xffff. 33662306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_LOUD, 0x000460, NULL), 33762306a36Sopenharmony_ci // Loud Technologies, Mackie Onyx Satellite. Although revised version of firmware is 33862306a36Sopenharmony_ci // installed to avoid the postpone, the value of SYT field is always 0xffff. 33962306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_LOUD, MODEL_SATELLITE, NULL), 34062306a36Sopenharmony_ci // Miglia HarmonyAudio. Not yet identified. 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci // 34362306a36Sopenharmony_ci // OXFW971 devices: 34462306a36Sopenharmony_ci // The value of SYT field in CIP header is enough reliable. Both of blocking and non-blocking 34562306a36Sopenharmony_ci // transmission methods are available. 34662306a36Sopenharmony_ci // 34762306a36Sopenharmony_ci // Any Mackie(Loud) models (name string/model id): 34862306a36Sopenharmony_ci // Onyx-i series (former models): 0x081216 34962306a36Sopenharmony_ci // Onyx 1640i: 0x001640 35062306a36Sopenharmony_ci // d.2 pro/d.4 pro (built-in card): Unknown 35162306a36Sopenharmony_ci // U.420: Unknown 35262306a36Sopenharmony_ci // U.420d: Unknown 35362306a36Sopenharmony_ci { 35462306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 35562306a36Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | 35662306a36Sopenharmony_ci IEEE1394_MATCH_VERSION, 35762306a36Sopenharmony_ci .vendor_id = VENDOR_LOUD, 35862306a36Sopenharmony_ci .model_id = 0, 35962306a36Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, 36062306a36Sopenharmony_ci .version = VERSION_AVC, 36162306a36Sopenharmony_ci }, 36262306a36Sopenharmony_ci // TASCAM, FireOne. 36362306a36Sopenharmony_ci OXFW_DEV_ENTRY(VENDOR_TASCAM, 0x800007, NULL), 36462306a36Sopenharmony_ci // Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m). 36562306a36Sopenharmony_ci OXFW_DEV_ENTRY(OUI_STANTON, MODEL_SCS1M, NULL), 36662306a36Sopenharmony_ci // Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d). 36762306a36Sopenharmony_ci OXFW_DEV_ENTRY(OUI_STANTON, 0x002000, NULL), 36862306a36Sopenharmony_ci // APOGEE, duet FireWire. 36962306a36Sopenharmony_ci OXFW_DEV_ENTRY(OUI_APOGEE, MODEL_DUET_FW, NULL), 37062306a36Sopenharmony_ci { } 37162306a36Sopenharmony_ci}; 37262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, oxfw_id_table); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic struct fw_driver oxfw_driver = { 37562306a36Sopenharmony_ci .driver = { 37662306a36Sopenharmony_ci .owner = THIS_MODULE, 37762306a36Sopenharmony_ci .name = KBUILD_MODNAME, 37862306a36Sopenharmony_ci .bus = &fw_bus_type, 37962306a36Sopenharmony_ci }, 38062306a36Sopenharmony_ci .probe = oxfw_probe, 38162306a36Sopenharmony_ci .update = oxfw_bus_reset, 38262306a36Sopenharmony_ci .remove = oxfw_remove, 38362306a36Sopenharmony_ci .id_table = oxfw_id_table, 38462306a36Sopenharmony_ci}; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic int __init snd_oxfw_init(void) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci return driver_register(&oxfw_driver.driver); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic void __exit snd_oxfw_exit(void) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci driver_unregister(&oxfw_driver.driver); 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cimodule_init(snd_oxfw_init); 39762306a36Sopenharmony_cimodule_exit(snd_oxfw_exit); 398