18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * oxfw.c - a part of driver for OXFW970/971 based devices 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "oxfw.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) 118c2ecf20Sopenharmony_ci/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020) 148c2ecf20Sopenharmony_ci#define OXFORD_HARDWARE_ID_OXFW970 0x39443841 158c2ecf20Sopenharmony_ci#define OXFORD_HARDWARE_ID_OXFW971 0x39373100 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define VENDOR_LOUD 0x000ff2 188c2ecf20Sopenharmony_ci#define VENDOR_GRIFFIN 0x001292 198c2ecf20Sopenharmony_ci#define VENDOR_BEHRINGER 0x001564 208c2ecf20Sopenharmony_ci#define VENDOR_LACIE 0x00d04b 218c2ecf20Sopenharmony_ci#define VENDOR_TASCAM 0x00022e 228c2ecf20Sopenharmony_ci#define OUI_STANTON 0x001260 238c2ecf20Sopenharmony_ci#define OUI_APOGEE 0x0003db 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define MODEL_SATELLITE 0x00200f 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define SPECIFIER_1394TA 0x00a02d 288c2ecf20Sopenharmony_ci#define VERSION_AVC 0x010001 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver"); 318c2ecf20Sopenharmony_ciMODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 328c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 338c2ecf20Sopenharmony_ciMODULE_ALIAS("snd-firewire-speakers"); 348c2ecf20Sopenharmony_ciMODULE_ALIAS("snd-scs1x"); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct compat_info { 378c2ecf20Sopenharmony_ci const char *driver_name; 388c2ecf20Sopenharmony_ci const char *vendor_name; 398c2ecf20Sopenharmony_ci const char *model_name; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic bool detect_loud_models(struct fw_unit *unit) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci const char *const models[] = { 458c2ecf20Sopenharmony_ci "Onyxi", 468c2ecf20Sopenharmony_ci "Onyx-i", 478c2ecf20Sopenharmony_ci "Onyx 1640i", 488c2ecf20Sopenharmony_ci "d.Pro", 498c2ecf20Sopenharmony_ci "Mackie Onyx Satellite", 508c2ecf20Sopenharmony_ci "Tapco LINK.firewire 4x6", 518c2ecf20Sopenharmony_ci "U.420"}; 528c2ecf20Sopenharmony_ci char model[32]; 538c2ecf20Sopenharmony_ci int err; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci err = fw_csr_string(unit->directory, CSR_MODEL, 568c2ecf20Sopenharmony_ci model, sizeof(model)); 578c2ecf20Sopenharmony_ci if (err < 0) 588c2ecf20Sopenharmony_ci return false; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return match_string(models, ARRAY_SIZE(models), model) >= 0; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic int name_card(struct snd_oxfw *oxfw) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(oxfw->unit); 668c2ecf20Sopenharmony_ci const struct compat_info *info; 678c2ecf20Sopenharmony_ci char vendor[24]; 688c2ecf20Sopenharmony_ci char model[32]; 698c2ecf20Sopenharmony_ci const char *d, *v, *m; 708c2ecf20Sopenharmony_ci u32 firmware; 718c2ecf20Sopenharmony_ci int err; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* get vendor name from root directory */ 748c2ecf20Sopenharmony_ci err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR, 758c2ecf20Sopenharmony_ci vendor, sizeof(vendor)); 768c2ecf20Sopenharmony_ci if (err < 0) 778c2ecf20Sopenharmony_ci goto end; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* get model name from unit directory */ 808c2ecf20Sopenharmony_ci err = fw_csr_string(oxfw->unit->directory, CSR_MODEL, 818c2ecf20Sopenharmony_ci model, sizeof(model)); 828c2ecf20Sopenharmony_ci if (err < 0) 838c2ecf20Sopenharmony_ci goto end; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST, 868c2ecf20Sopenharmony_ci OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0); 878c2ecf20Sopenharmony_ci if (err < 0) 888c2ecf20Sopenharmony_ci goto end; 898c2ecf20Sopenharmony_ci be32_to_cpus(&firmware); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* to apply card definitions */ 928c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == VENDOR_GRIFFIN || 938c2ecf20Sopenharmony_ci oxfw->entry->vendor_id == VENDOR_LACIE) { 948c2ecf20Sopenharmony_ci info = (const struct compat_info *)oxfw->entry->driver_data; 958c2ecf20Sopenharmony_ci d = info->driver_name; 968c2ecf20Sopenharmony_ci v = info->vendor_name; 978c2ecf20Sopenharmony_ci m = info->model_name; 988c2ecf20Sopenharmony_ci } else { 998c2ecf20Sopenharmony_ci d = "OXFW"; 1008c2ecf20Sopenharmony_ci v = vendor; 1018c2ecf20Sopenharmony_ci m = model; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci strcpy(oxfw->card->driver, d); 1058c2ecf20Sopenharmony_ci strcpy(oxfw->card->mixername, m); 1068c2ecf20Sopenharmony_ci strcpy(oxfw->card->shortname, m); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci snprintf(oxfw->card->longname, sizeof(oxfw->card->longname), 1098c2ecf20Sopenharmony_ci "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d", 1108c2ecf20Sopenharmony_ci v, m, firmware >> 20, firmware & 0xffff, 1118c2ecf20Sopenharmony_ci fw_dev->config_rom[3], fw_dev->config_rom[4], 1128c2ecf20Sopenharmony_ci dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed); 1138c2ecf20Sopenharmony_ciend: 1148c2ecf20Sopenharmony_ci return err; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void oxfw_card_free(struct snd_card *card) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct snd_oxfw *oxfw = card->private_data; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) 1228c2ecf20Sopenharmony_ci snd_oxfw_stream_destroy_duplex(oxfw); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic int detect_quirks(struct snd_oxfw *oxfw) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(oxfw->unit); 1288c2ecf20Sopenharmony_ci struct fw_csr_iterator it; 1298c2ecf20Sopenharmony_ci int key, val; 1308c2ecf20Sopenharmony_ci int vendor, model; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* 1338c2ecf20Sopenharmony_ci * Add ALSA control elements for two models to keep compatibility to 1348c2ecf20Sopenharmony_ci * old firewire-speaker module. 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == VENDOR_GRIFFIN) 1378c2ecf20Sopenharmony_ci return snd_oxfw_add_spkr(oxfw, false); 1388c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == VENDOR_LACIE) 1398c2ecf20Sopenharmony_ci return snd_oxfw_add_spkr(oxfw, true); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * Stanton models supports asynchronous transactions for unique MIDI 1438c2ecf20Sopenharmony_ci * messages. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == OUI_STANTON) { 1468c2ecf20Sopenharmony_ci /* No physical MIDI ports. */ 1478c2ecf20Sopenharmony_ci oxfw->midi_input_ports = 0; 1488c2ecf20Sopenharmony_ci oxfw->midi_output_ports = 0; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return snd_oxfw_scs1x_add(oxfw); 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * TASCAM FireOne has physical control and requires a pair of additional 1558c2ecf20Sopenharmony_ci * MIDI ports. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == VENDOR_TASCAM) { 1588c2ecf20Sopenharmony_ci oxfw->midi_input_ports++; 1598c2ecf20Sopenharmony_ci oxfw->midi_output_ports++; 1608c2ecf20Sopenharmony_ci return 0; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Seek from Root Directory of Config ROM. */ 1648c2ecf20Sopenharmony_ci vendor = model = 0; 1658c2ecf20Sopenharmony_ci fw_csr_iterator_init(&it, fw_dev->config_rom + 5); 1668c2ecf20Sopenharmony_ci while (fw_csr_iterator_next(&it, &key, &val)) { 1678c2ecf20Sopenharmony_ci if (key == CSR_VENDOR) 1688c2ecf20Sopenharmony_ci vendor = val; 1698c2ecf20Sopenharmony_ci else if (key == CSR_MODEL) 1708c2ecf20Sopenharmony_ci model = val; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* 1748c2ecf20Sopenharmony_ci * Mackie Onyx Satellite with base station has a quirk to report a wrong 1758c2ecf20Sopenharmony_ci * value in 'dbs' field of CIP header against its format information. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE) 1788c2ecf20Sopenharmony_ci oxfw->wrong_dbs = true; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic void do_registration(struct work_struct *work) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); 1868c2ecf20Sopenharmony_ci int err; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (oxfw->registered) 1898c2ecf20Sopenharmony_ci return; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0, 1928c2ecf20Sopenharmony_ci &oxfw->card); 1938c2ecf20Sopenharmony_ci if (err < 0) 1948c2ecf20Sopenharmony_ci return; 1958c2ecf20Sopenharmony_ci oxfw->card->private_free = oxfw_card_free; 1968c2ecf20Sopenharmony_ci oxfw->card->private_data = oxfw; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci err = name_card(oxfw); 1998c2ecf20Sopenharmony_ci if (err < 0) 2008c2ecf20Sopenharmony_ci goto error; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci err = snd_oxfw_stream_discover(oxfw); 2038c2ecf20Sopenharmony_ci if (err < 0) 2048c2ecf20Sopenharmony_ci goto error; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci err = detect_quirks(oxfw); 2078c2ecf20Sopenharmony_ci if (err < 0) 2088c2ecf20Sopenharmony_ci goto error; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) { 2118c2ecf20Sopenharmony_ci err = snd_oxfw_stream_init_duplex(oxfw); 2128c2ecf20Sopenharmony_ci if (err < 0) 2138c2ecf20Sopenharmony_ci goto error; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci err = snd_oxfw_create_pcm(oxfw); 2168c2ecf20Sopenharmony_ci if (err < 0) 2178c2ecf20Sopenharmony_ci goto error; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci snd_oxfw_proc_init(oxfw); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci err = snd_oxfw_create_midi(oxfw); 2228c2ecf20Sopenharmony_ci if (err < 0) 2238c2ecf20Sopenharmony_ci goto error; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci err = snd_oxfw_create_hwdep(oxfw); 2268c2ecf20Sopenharmony_ci if (err < 0) 2278c2ecf20Sopenharmony_ci goto error; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci err = snd_card_register(oxfw->card); 2318c2ecf20Sopenharmony_ci if (err < 0) 2328c2ecf20Sopenharmony_ci goto error; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci oxfw->registered = true; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci return; 2378c2ecf20Sopenharmony_cierror: 2388c2ecf20Sopenharmony_ci snd_card_free(oxfw->card); 2398c2ecf20Sopenharmony_ci dev_info(&oxfw->unit->device, 2408c2ecf20Sopenharmony_ci "Sound card registration failed: %d\n", err); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic int oxfw_probe(struct fw_unit *unit, 2448c2ecf20Sopenharmony_ci const struct ieee1394_device_id *entry) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct snd_oxfw *oxfw; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit)) 2498c2ecf20Sopenharmony_ci return -ENODEV; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* Allocate this independent of sound card instance. */ 2528c2ecf20Sopenharmony_ci oxfw = devm_kzalloc(&unit->device, sizeof(struct snd_oxfw), GFP_KERNEL); 2538c2ecf20Sopenharmony_ci if (!oxfw) 2548c2ecf20Sopenharmony_ci return -ENOMEM; 2558c2ecf20Sopenharmony_ci oxfw->unit = fw_unit_get(unit); 2568c2ecf20Sopenharmony_ci dev_set_drvdata(&unit->device, oxfw); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci oxfw->entry = entry; 2598c2ecf20Sopenharmony_ci mutex_init(&oxfw->mutex); 2608c2ecf20Sopenharmony_ci spin_lock_init(&oxfw->lock); 2618c2ecf20Sopenharmony_ci init_waitqueue_head(&oxfw->hwdep_wait); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Allocate and register this sound card later. */ 2648c2ecf20Sopenharmony_ci INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration); 2658c2ecf20Sopenharmony_ci snd_fw_schedule_registration(unit, &oxfw->dwork); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic void oxfw_bus_reset(struct fw_unit *unit) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (!oxfw->registered) 2758c2ecf20Sopenharmony_ci snd_fw_schedule_registration(unit, &oxfw->dwork); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci fcp_bus_reset(oxfw->unit); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (oxfw->registered) { 2808c2ecf20Sopenharmony_ci if (oxfw->has_output || oxfw->has_input) { 2818c2ecf20Sopenharmony_ci mutex_lock(&oxfw->mutex); 2828c2ecf20Sopenharmony_ci snd_oxfw_stream_update_duplex(oxfw); 2838c2ecf20Sopenharmony_ci mutex_unlock(&oxfw->mutex); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (oxfw->entry->vendor_id == OUI_STANTON) 2878c2ecf20Sopenharmony_ci snd_oxfw_scs1x_update(oxfw); 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic void oxfw_remove(struct fw_unit *unit) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* 2968c2ecf20Sopenharmony_ci * Confirm to stop the work for registration before the sound card is 2978c2ecf20Sopenharmony_ci * going to be released. The work is not scheduled again because bus 2988c2ecf20Sopenharmony_ci * reset handler is not called anymore. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&oxfw->dwork); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (oxfw->registered) { 3038c2ecf20Sopenharmony_ci // Block till all of ALSA character devices are released. 3048c2ecf20Sopenharmony_ci snd_card_free(oxfw->card); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci mutex_destroy(&oxfw->mutex); 3088c2ecf20Sopenharmony_ci fw_unit_put(oxfw->unit); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic const struct compat_info griffin_firewave = { 3128c2ecf20Sopenharmony_ci .driver_name = "FireWave", 3138c2ecf20Sopenharmony_ci .vendor_name = "Griffin", 3148c2ecf20Sopenharmony_ci .model_name = "FireWave", 3158c2ecf20Sopenharmony_ci}; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct compat_info lacie_speakers = { 3188c2ecf20Sopenharmony_ci .driver_name = "FWSpeakers", 3198c2ecf20Sopenharmony_ci .vendor_name = "LaCie", 3208c2ecf20Sopenharmony_ci .model_name = "FireWire Speakers", 3218c2ecf20Sopenharmony_ci}; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic const struct ieee1394_device_id oxfw_id_table[] = { 3248c2ecf20Sopenharmony_ci { 3258c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3268c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID | 3278c2ecf20Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | 3288c2ecf20Sopenharmony_ci IEEE1394_MATCH_VERSION, 3298c2ecf20Sopenharmony_ci .vendor_id = VENDOR_GRIFFIN, 3308c2ecf20Sopenharmony_ci .model_id = 0x00f970, 3318c2ecf20Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, 3328c2ecf20Sopenharmony_ci .version = VERSION_AVC, 3338c2ecf20Sopenharmony_ci .driver_data = (kernel_ulong_t)&griffin_firewave, 3348c2ecf20Sopenharmony_ci }, 3358c2ecf20Sopenharmony_ci { 3368c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3378c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID | 3388c2ecf20Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | 3398c2ecf20Sopenharmony_ci IEEE1394_MATCH_VERSION, 3408c2ecf20Sopenharmony_ci .vendor_id = VENDOR_LACIE, 3418c2ecf20Sopenharmony_ci .model_id = 0x00f970, 3428c2ecf20Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, 3438c2ecf20Sopenharmony_ci .version = VERSION_AVC, 3448c2ecf20Sopenharmony_ci .driver_data = (kernel_ulong_t)&lacie_speakers, 3458c2ecf20Sopenharmony_ci }, 3468c2ecf20Sopenharmony_ci /* Behringer,F-Control Audio 202 */ 3478c2ecf20Sopenharmony_ci { 3488c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3498c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 3508c2ecf20Sopenharmony_ci .vendor_id = VENDOR_BEHRINGER, 3518c2ecf20Sopenharmony_ci .model_id = 0x00fc22, 3528c2ecf20Sopenharmony_ci }, 3538c2ecf20Sopenharmony_ci /* 3548c2ecf20Sopenharmony_ci * Any Mackie(Loud) models (name string/model id): 3558c2ecf20Sopenharmony_ci * Onyx-i series (former models): 0x081216 3568c2ecf20Sopenharmony_ci * Mackie Onyx Satellite: 0x00200f 3578c2ecf20Sopenharmony_ci * Tapco LINK.firewire 4x6: 0x000460 3588c2ecf20Sopenharmony_ci * d.2 pro/d.4 pro (built-in card): Unknown 3598c2ecf20Sopenharmony_ci * U.420: Unknown 3608c2ecf20Sopenharmony_ci * U.420d: Unknown 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3648c2ecf20Sopenharmony_ci IEEE1394_MATCH_SPECIFIER_ID | 3658c2ecf20Sopenharmony_ci IEEE1394_MATCH_VERSION, 3668c2ecf20Sopenharmony_ci .vendor_id = VENDOR_LOUD, 3678c2ecf20Sopenharmony_ci .specifier_id = SPECIFIER_1394TA, 3688c2ecf20Sopenharmony_ci .version = VERSION_AVC, 3698c2ecf20Sopenharmony_ci }, 3708c2ecf20Sopenharmony_ci /* TASCAM, FireOne */ 3718c2ecf20Sopenharmony_ci { 3728c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3738c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 3748c2ecf20Sopenharmony_ci .vendor_id = VENDOR_TASCAM, 3758c2ecf20Sopenharmony_ci .model_id = 0x800007, 3768c2ecf20Sopenharmony_ci }, 3778c2ecf20Sopenharmony_ci /* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */ 3788c2ecf20Sopenharmony_ci { 3798c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3808c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 3818c2ecf20Sopenharmony_ci .vendor_id = OUI_STANTON, 3828c2ecf20Sopenharmony_ci .model_id = 0x001000, 3838c2ecf20Sopenharmony_ci }, 3848c2ecf20Sopenharmony_ci /* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */ 3858c2ecf20Sopenharmony_ci { 3868c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3878c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 3888c2ecf20Sopenharmony_ci .vendor_id = OUI_STANTON, 3898c2ecf20Sopenharmony_ci .model_id = 0x002000, 3908c2ecf20Sopenharmony_ci }, 3918c2ecf20Sopenharmony_ci // APOGEE, duet FireWire 3928c2ecf20Sopenharmony_ci { 3938c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | 3948c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, 3958c2ecf20Sopenharmony_ci .vendor_id = OUI_APOGEE, 3968c2ecf20Sopenharmony_ci .model_id = 0x01dddd, 3978c2ecf20Sopenharmony_ci }, 3988c2ecf20Sopenharmony_ci { } 3998c2ecf20Sopenharmony_ci}; 4008c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, oxfw_id_table); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic struct fw_driver oxfw_driver = { 4038c2ecf20Sopenharmony_ci .driver = { 4048c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4058c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 4068c2ecf20Sopenharmony_ci .bus = &fw_bus_type, 4078c2ecf20Sopenharmony_ci }, 4088c2ecf20Sopenharmony_ci .probe = oxfw_probe, 4098c2ecf20Sopenharmony_ci .update = oxfw_bus_reset, 4108c2ecf20Sopenharmony_ci .remove = oxfw_remove, 4118c2ecf20Sopenharmony_ci .id_table = oxfw_id_table, 4128c2ecf20Sopenharmony_ci}; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic int __init snd_oxfw_init(void) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci return driver_register(&oxfw_driver.driver); 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic void __exit snd_oxfw_exit(void) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci driver_unregister(&oxfw_driver.driver); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cimodule_init(snd_oxfw_init); 4258c2ecf20Sopenharmony_cimodule_exit(snd_oxfw_exit); 426