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