18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fireworks.c - a part of driver for Fireworks based devices 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2009-2010 Clemens Ladisch 68c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014 Takashi Sakamoto 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci * Fireworks is a board module which Echo Audio produced. This module consists 118c2ecf20Sopenharmony_ci * of three chipsets: 128c2ecf20Sopenharmony_ci * - Communication chipset for IEEE1394 PHY/Link and IEC 61883-1/6 138c2ecf20Sopenharmony_ci * - DSP or/and FPGA for signal processing 148c2ecf20Sopenharmony_ci * - Flash Memory to store firmwares 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "fireworks.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Echo Fireworks driver"); 208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>"); 218c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 248c2ecf20Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 258c2ecf20Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 268c2ecf20Sopenharmony_ciunsigned int snd_efw_resp_buf_size = 1024; 278c2ecf20Sopenharmony_cibool snd_efw_resp_buf_debug = false; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(index, "card index"); 318c2ecf20Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 328c2ecf20Sopenharmony_ciMODULE_PARM_DESC(id, "ID string"); 338c2ecf20Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable, "enable Fireworks sound card"); 358c2ecf20Sopenharmony_cimodule_param_named(resp_buf_size, snd_efw_resp_buf_size, uint, 0444); 368c2ecf20Sopenharmony_ciMODULE_PARM_DESC(resp_buf_size, 378c2ecf20Sopenharmony_ci "response buffer size (max 4096, default 1024)"); 388c2ecf20Sopenharmony_cimodule_param_named(resp_buf_debug, snd_efw_resp_buf_debug, bool, 0444); 398c2ecf20Sopenharmony_ciMODULE_PARM_DESC(resp_buf_debug, "store all responses to buffer"); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(devices_mutex); 428c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(devices_used, SNDRV_CARDS); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define VENDOR_LOUD 0x000ff2 458c2ecf20Sopenharmony_ci#define MODEL_MACKIE_400F 0x00400f 468c2ecf20Sopenharmony_ci#define MODEL_MACKIE_1200F 0x01200f 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define VENDOR_ECHO 0x001486 498c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_12 0x00af12 508c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_12HD 0x0af12d 518c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_12_APPLE 0x0af12a 528c2ecf20Sopenharmony_ci/* This is applied for AudioFire8 (until 2009 July) */ 538c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_8 0x000af8 548c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_2 0x000af2 558c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_4 0x000af4 568c2ecf20Sopenharmony_ci/* AudioFire9 is applied for AudioFire8(since 2009 July) and AudioFirePre8 */ 578c2ecf20Sopenharmony_ci#define MODEL_ECHO_AUDIOFIRE_9 0x000af9 588c2ecf20Sopenharmony_ci/* unknown as product */ 598c2ecf20Sopenharmony_ci#define MODEL_ECHO_FIREWORKS_8 0x0000f8 608c2ecf20Sopenharmony_ci#define MODEL_ECHO_FIREWORKS_HDMI 0x00afd1 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define VENDOR_GIBSON 0x00075b 638c2ecf20Sopenharmony_ci/* for Robot Interface Pack of Dark Fire, Dusk Tiger, Les Paul Standard 2010 */ 648c2ecf20Sopenharmony_ci#define MODEL_GIBSON_RIP 0x00afb2 658c2ecf20Sopenharmony_ci/* unknown as product */ 668c2ecf20Sopenharmony_ci#define MODEL_GIBSON_GOLDTOP 0x00afb9 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* part of hardware capability flags */ 698c2ecf20Sopenharmony_ci#define FLAG_RESP_ADDR_CHANGABLE 0 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic int 728c2ecf20Sopenharmony_ciget_hardware_info(struct snd_efw *efw) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci struct fw_device *fw_dev = fw_parent_device(efw->unit); 758c2ecf20Sopenharmony_ci struct snd_efw_hwinfo *hwinfo; 768c2ecf20Sopenharmony_ci char version[12] = {0}; 778c2ecf20Sopenharmony_ci int err; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci hwinfo = kzalloc(sizeof(struct snd_efw_hwinfo), GFP_KERNEL); 808c2ecf20Sopenharmony_ci if (hwinfo == NULL) 818c2ecf20Sopenharmony_ci return -ENOMEM; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci err = snd_efw_command_get_hwinfo(efw, hwinfo); 848c2ecf20Sopenharmony_ci if (err < 0) 858c2ecf20Sopenharmony_ci goto end; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* firmware version for communication chipset */ 888c2ecf20Sopenharmony_ci snprintf(version, sizeof(version), "%u.%u", 898c2ecf20Sopenharmony_ci (hwinfo->arm_version >> 24) & 0xff, 908c2ecf20Sopenharmony_ci (hwinfo->arm_version >> 16) & 0xff); 918c2ecf20Sopenharmony_ci efw->firmware_version = hwinfo->arm_version; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci strcpy(efw->card->driver, "Fireworks"); 948c2ecf20Sopenharmony_ci strcpy(efw->card->shortname, hwinfo->model_name); 958c2ecf20Sopenharmony_ci strcpy(efw->card->mixername, hwinfo->model_name); 968c2ecf20Sopenharmony_ci snprintf(efw->card->longname, sizeof(efw->card->longname), 978c2ecf20Sopenharmony_ci "%s %s v%s, GUID %08x%08x at %s, S%d", 988c2ecf20Sopenharmony_ci hwinfo->vendor_name, hwinfo->model_name, version, 998c2ecf20Sopenharmony_ci hwinfo->guid_hi, hwinfo->guid_lo, 1008c2ecf20Sopenharmony_ci dev_name(&efw->unit->device), 100 << fw_dev->max_speed); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (hwinfo->flags & BIT(FLAG_RESP_ADDR_CHANGABLE)) 1038c2ecf20Sopenharmony_ci efw->resp_addr_changable = true; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci efw->supported_sampling_rate = 0; 1068c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 22050) 1078c2ecf20Sopenharmony_ci && (22050 <= hwinfo->max_sample_rate)) 1088c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_22050; 1098c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 32000) 1108c2ecf20Sopenharmony_ci && (32000 <= hwinfo->max_sample_rate)) 1118c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_32000; 1128c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 44100) 1138c2ecf20Sopenharmony_ci && (44100 <= hwinfo->max_sample_rate)) 1148c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_44100; 1158c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 48000) 1168c2ecf20Sopenharmony_ci && (48000 <= hwinfo->max_sample_rate)) 1178c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_48000; 1188c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 88200) 1198c2ecf20Sopenharmony_ci && (88200 <= hwinfo->max_sample_rate)) 1208c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_88200; 1218c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 96000) 1228c2ecf20Sopenharmony_ci && (96000 <= hwinfo->max_sample_rate)) 1238c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_96000; 1248c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 176400) 1258c2ecf20Sopenharmony_ci && (176400 <= hwinfo->max_sample_rate)) 1268c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_176400; 1278c2ecf20Sopenharmony_ci if ((hwinfo->min_sample_rate <= 192000) 1288c2ecf20Sopenharmony_ci && (192000 <= hwinfo->max_sample_rate)) 1298c2ecf20Sopenharmony_ci efw->supported_sampling_rate |= SNDRV_PCM_RATE_192000; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* the number of MIDI ports, not of MIDI conformant data channels */ 1328c2ecf20Sopenharmony_ci if (hwinfo->midi_out_ports > SND_EFW_MAX_MIDI_OUT_PORTS || 1338c2ecf20Sopenharmony_ci hwinfo->midi_in_ports > SND_EFW_MAX_MIDI_IN_PORTS) { 1348c2ecf20Sopenharmony_ci err = -EIO; 1358c2ecf20Sopenharmony_ci goto end; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci efw->midi_out_ports = hwinfo->midi_out_ports; 1388c2ecf20Sopenharmony_ci efw->midi_in_ports = hwinfo->midi_in_ports; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (hwinfo->amdtp_tx_pcm_channels > AM824_MAX_CHANNELS_FOR_PCM || 1418c2ecf20Sopenharmony_ci hwinfo->amdtp_tx_pcm_channels_2x > AM824_MAX_CHANNELS_FOR_PCM || 1428c2ecf20Sopenharmony_ci hwinfo->amdtp_tx_pcm_channels_4x > AM824_MAX_CHANNELS_FOR_PCM || 1438c2ecf20Sopenharmony_ci hwinfo->amdtp_rx_pcm_channels > AM824_MAX_CHANNELS_FOR_PCM || 1448c2ecf20Sopenharmony_ci hwinfo->amdtp_rx_pcm_channels_2x > AM824_MAX_CHANNELS_FOR_PCM || 1458c2ecf20Sopenharmony_ci hwinfo->amdtp_rx_pcm_channels_4x > AM824_MAX_CHANNELS_FOR_PCM) { 1468c2ecf20Sopenharmony_ci err = -ENOSYS; 1478c2ecf20Sopenharmony_ci goto end; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci efw->pcm_capture_channels[0] = hwinfo->amdtp_tx_pcm_channels; 1508c2ecf20Sopenharmony_ci efw->pcm_capture_channels[1] = hwinfo->amdtp_tx_pcm_channels_2x; 1518c2ecf20Sopenharmony_ci efw->pcm_capture_channels[2] = hwinfo->amdtp_tx_pcm_channels_4x; 1528c2ecf20Sopenharmony_ci efw->pcm_playback_channels[0] = hwinfo->amdtp_rx_pcm_channels; 1538c2ecf20Sopenharmony_ci efw->pcm_playback_channels[1] = hwinfo->amdtp_rx_pcm_channels_2x; 1548c2ecf20Sopenharmony_ci efw->pcm_playback_channels[2] = hwinfo->amdtp_rx_pcm_channels_4x; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Hardware metering. */ 1578c2ecf20Sopenharmony_ci if (hwinfo->phys_in_grp_count > HWINFO_MAX_CAPS_GROUPS || 1588c2ecf20Sopenharmony_ci hwinfo->phys_out_grp_count > HWINFO_MAX_CAPS_GROUPS) { 1598c2ecf20Sopenharmony_ci err = -EIO; 1608c2ecf20Sopenharmony_ci goto end; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci efw->phys_in = hwinfo->phys_in; 1638c2ecf20Sopenharmony_ci efw->phys_out = hwinfo->phys_out; 1648c2ecf20Sopenharmony_ci efw->phys_in_grp_count = hwinfo->phys_in_grp_count; 1658c2ecf20Sopenharmony_ci efw->phys_out_grp_count = hwinfo->phys_out_grp_count; 1668c2ecf20Sopenharmony_ci memcpy(&efw->phys_in_grps, hwinfo->phys_in_grps, 1678c2ecf20Sopenharmony_ci sizeof(struct snd_efw_phys_grp) * hwinfo->phys_in_grp_count); 1688c2ecf20Sopenharmony_ci memcpy(&efw->phys_out_grps, hwinfo->phys_out_grps, 1698c2ecf20Sopenharmony_ci sizeof(struct snd_efw_phys_grp) * hwinfo->phys_out_grp_count); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* AudioFire8 (since 2009) and AudioFirePre8 */ 1728c2ecf20Sopenharmony_ci if (hwinfo->type == MODEL_ECHO_AUDIOFIRE_9) 1738c2ecf20Sopenharmony_ci efw->is_af9 = true; 1748c2ecf20Sopenharmony_ci /* These models uses the same firmware. */ 1758c2ecf20Sopenharmony_ci if (hwinfo->type == MODEL_ECHO_AUDIOFIRE_2 || 1768c2ecf20Sopenharmony_ci hwinfo->type == MODEL_ECHO_AUDIOFIRE_4 || 1778c2ecf20Sopenharmony_ci hwinfo->type == MODEL_ECHO_AUDIOFIRE_9 || 1788c2ecf20Sopenharmony_ci hwinfo->type == MODEL_GIBSON_RIP || 1798c2ecf20Sopenharmony_ci hwinfo->type == MODEL_GIBSON_GOLDTOP) 1808c2ecf20Sopenharmony_ci efw->is_fireworks3 = true; 1818c2ecf20Sopenharmony_ciend: 1828c2ecf20Sopenharmony_ci kfree(hwinfo); 1838c2ecf20Sopenharmony_ci return err; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic void 1878c2ecf20Sopenharmony_ciefw_card_free(struct snd_card *card) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct snd_efw *efw = card->private_data; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci mutex_lock(&devices_mutex); 1928c2ecf20Sopenharmony_ci clear_bit(efw->card_index, devices_used); 1938c2ecf20Sopenharmony_ci mutex_unlock(&devices_mutex); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci snd_efw_stream_destroy_duplex(efw); 1968c2ecf20Sopenharmony_ci snd_efw_transaction_remove_instance(efw); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic void 2008c2ecf20Sopenharmony_cido_registration(struct work_struct *work) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct snd_efw *efw = container_of(work, struct snd_efw, dwork.work); 2038c2ecf20Sopenharmony_ci unsigned int card_index; 2048c2ecf20Sopenharmony_ci int err; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (efw->registered) 2078c2ecf20Sopenharmony_ci return; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* check registered cards */ 2108c2ecf20Sopenharmony_ci mutex_lock(&devices_mutex); 2118c2ecf20Sopenharmony_ci for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { 2128c2ecf20Sopenharmony_ci if (!test_bit(card_index, devices_used) && enable[card_index]) 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci if (card_index >= SNDRV_CARDS) { 2168c2ecf20Sopenharmony_ci mutex_unlock(&devices_mutex); 2178c2ecf20Sopenharmony_ci return; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci err = snd_card_new(&efw->unit->device, index[card_index], 2218c2ecf20Sopenharmony_ci id[card_index], THIS_MODULE, 0, &efw->card); 2228c2ecf20Sopenharmony_ci if (err < 0) { 2238c2ecf20Sopenharmony_ci mutex_unlock(&devices_mutex); 2248c2ecf20Sopenharmony_ci return; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci set_bit(card_index, devices_used); 2278c2ecf20Sopenharmony_ci mutex_unlock(&devices_mutex); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci efw->card->private_free = efw_card_free; 2308c2ecf20Sopenharmony_ci efw->card->private_data = efw; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* prepare response buffer */ 2338c2ecf20Sopenharmony_ci snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, 2348c2ecf20Sopenharmony_ci SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); 2358c2ecf20Sopenharmony_ci efw->resp_buf = devm_kzalloc(&efw->card->card_dev, 2368c2ecf20Sopenharmony_ci snd_efw_resp_buf_size, GFP_KERNEL); 2378c2ecf20Sopenharmony_ci if (!efw->resp_buf) { 2388c2ecf20Sopenharmony_ci err = -ENOMEM; 2398c2ecf20Sopenharmony_ci goto error; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci efw->pull_ptr = efw->push_ptr = efw->resp_buf; 2428c2ecf20Sopenharmony_ci snd_efw_transaction_add_instance(efw); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci err = get_hardware_info(efw); 2458c2ecf20Sopenharmony_ci if (err < 0) 2468c2ecf20Sopenharmony_ci goto error; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci err = snd_efw_stream_init_duplex(efw); 2498c2ecf20Sopenharmony_ci if (err < 0) 2508c2ecf20Sopenharmony_ci goto error; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci snd_efw_proc_init(efw); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (efw->midi_out_ports || efw->midi_in_ports) { 2558c2ecf20Sopenharmony_ci err = snd_efw_create_midi_devices(efw); 2568c2ecf20Sopenharmony_ci if (err < 0) 2578c2ecf20Sopenharmony_ci goto error; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci err = snd_efw_create_pcm_devices(efw); 2618c2ecf20Sopenharmony_ci if (err < 0) 2628c2ecf20Sopenharmony_ci goto error; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci err = snd_efw_create_hwdep_device(efw); 2658c2ecf20Sopenharmony_ci if (err < 0) 2668c2ecf20Sopenharmony_ci goto error; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci err = snd_card_register(efw->card); 2698c2ecf20Sopenharmony_ci if (err < 0) 2708c2ecf20Sopenharmony_ci goto error; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci efw->registered = true; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci return; 2758c2ecf20Sopenharmony_cierror: 2768c2ecf20Sopenharmony_ci snd_card_free(efw->card); 2778c2ecf20Sopenharmony_ci dev_info(&efw->unit->device, 2788c2ecf20Sopenharmony_ci "Sound card registration failed: %d\n", err); 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic int 2828c2ecf20Sopenharmony_ciefw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct snd_efw *efw; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci efw = devm_kzalloc(&unit->device, sizeof(struct snd_efw), GFP_KERNEL); 2878c2ecf20Sopenharmony_ci if (efw == NULL) 2888c2ecf20Sopenharmony_ci return -ENOMEM; 2898c2ecf20Sopenharmony_ci efw->unit = fw_unit_get(unit); 2908c2ecf20Sopenharmony_ci dev_set_drvdata(&unit->device, efw); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci mutex_init(&efw->mutex); 2938c2ecf20Sopenharmony_ci spin_lock_init(&efw->lock); 2948c2ecf20Sopenharmony_ci init_waitqueue_head(&efw->hwdep_wait); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* Allocate and register this sound card later. */ 2978c2ecf20Sopenharmony_ci INIT_DEFERRABLE_WORK(&efw->dwork, do_registration); 2988c2ecf20Sopenharmony_ci snd_fw_schedule_registration(unit, &efw->dwork); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic void efw_update(struct fw_unit *unit) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct snd_efw *efw = dev_get_drvdata(&unit->device); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* Postpone a workqueue for deferred registration. */ 3088c2ecf20Sopenharmony_ci if (!efw->registered) 3098c2ecf20Sopenharmony_ci snd_fw_schedule_registration(unit, &efw->dwork); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci snd_efw_transaction_bus_reset(efw->unit); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* 3148c2ecf20Sopenharmony_ci * After registration, userspace can start packet streaming, then this 3158c2ecf20Sopenharmony_ci * code block works fine. 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_ci if (efw->registered) { 3188c2ecf20Sopenharmony_ci mutex_lock(&efw->mutex); 3198c2ecf20Sopenharmony_ci snd_efw_stream_update_duplex(efw); 3208c2ecf20Sopenharmony_ci mutex_unlock(&efw->mutex); 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic void efw_remove(struct fw_unit *unit) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci struct snd_efw *efw = dev_get_drvdata(&unit->device); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* 3298c2ecf20Sopenharmony_ci * Confirm to stop the work for registration before the sound card is 3308c2ecf20Sopenharmony_ci * going to be released. The work is not scheduled again because bus 3318c2ecf20Sopenharmony_ci * reset handler is not called anymore. 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&efw->dwork); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (efw->registered) { 3368c2ecf20Sopenharmony_ci // Block till all of ALSA character devices are released. 3378c2ecf20Sopenharmony_ci snd_card_free(efw->card); 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci mutex_destroy(&efw->mutex); 3418c2ecf20Sopenharmony_ci fw_unit_put(efw->unit); 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic const struct ieee1394_device_id efw_id_table[] = { 3458c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_LOUD, MODEL_MACKIE_400F), 3468c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_LOUD, MODEL_MACKIE_1200F), 3478c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_8), 3488c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12), 3498c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12HD), 3508c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12_APPLE), 3518c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_2), 3528c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_4), 3538c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_9), 3548c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_FIREWORKS_8), 3558c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_FIREWORKS_HDMI), 3568c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_GIBSON, MODEL_GIBSON_RIP), 3578c2ecf20Sopenharmony_ci SND_EFW_DEV_ENTRY(VENDOR_GIBSON, MODEL_GIBSON_GOLDTOP), 3588c2ecf20Sopenharmony_ci {} 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, efw_id_table); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic struct fw_driver efw_driver = { 3638c2ecf20Sopenharmony_ci .driver = { 3648c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3658c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 3668c2ecf20Sopenharmony_ci .bus = &fw_bus_type, 3678c2ecf20Sopenharmony_ci }, 3688c2ecf20Sopenharmony_ci .probe = efw_probe, 3698c2ecf20Sopenharmony_ci .update = efw_update, 3708c2ecf20Sopenharmony_ci .remove = efw_remove, 3718c2ecf20Sopenharmony_ci .id_table = efw_id_table, 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic int __init snd_efw_init(void) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci int err; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci err = snd_efw_transaction_register(); 3798c2ecf20Sopenharmony_ci if (err < 0) 3808c2ecf20Sopenharmony_ci goto end; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci err = driver_register(&efw_driver.driver); 3838c2ecf20Sopenharmony_ci if (err < 0) 3848c2ecf20Sopenharmony_ci snd_efw_transaction_unregister(); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ciend: 3878c2ecf20Sopenharmony_ci return err; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic void __exit snd_efw_exit(void) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci snd_efw_transaction_unregister(); 3938c2ecf20Sopenharmony_ci driver_unregister(&efw_driver.driver); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cimodule_init(snd_efw_init); 3978c2ecf20Sopenharmony_cimodule_exit(snd_efw_exit); 398