xref: /openbmc/linux/sound/firewire/oxfw/oxfw.c (revision 2cc47d31)
11a4e39c2STakashi Sakamoto /*
21a4e39c2STakashi Sakamoto  * oxfw.c - a part of driver for OXFW970/971 based devices
31a4e39c2STakashi Sakamoto  *
41a4e39c2STakashi Sakamoto  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
51a4e39c2STakashi Sakamoto  * Licensed under the terms of the GNU General Public License, version 2.
61a4e39c2STakashi Sakamoto  */
71a4e39c2STakashi Sakamoto 
8e2786ca6STakashi Sakamoto #include "oxfw.h"
91a4e39c2STakashi Sakamoto 
101a4e39c2STakashi Sakamoto #define OXFORD_FIRMWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x50000)
111a4e39c2STakashi Sakamoto /* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
121a4e39c2STakashi Sakamoto 
131a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x90020)
141a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_OXFW970	0x39443841
151a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_OXFW971	0x39373100
161a4e39c2STakashi Sakamoto 
17ec4dba50STakashi Sakamoto #define VENDOR_LOUD		0x000ff2
181a4e39c2STakashi Sakamoto #define VENDOR_GRIFFIN		0x001292
19ec4dba50STakashi Sakamoto #define VENDOR_BEHRINGER	0x001564
201a4e39c2STakashi Sakamoto #define VENDOR_LACIE		0x00d04b
21759a2f40STakashi Sakamoto #define VENDOR_TASCAM		0x00022e
229e2004f9STakashi Sakamoto #define OUI_STANTON		0x001260
231a4e39c2STakashi Sakamoto 
2413f3a46dSTakashi Sakamoto #define MODEL_SATELLITE		0x00200f
2513f3a46dSTakashi Sakamoto 
261a4e39c2STakashi Sakamoto #define SPECIFIER_1394TA	0x00a02d
271a4e39c2STakashi Sakamoto #define VERSION_AVC		0x010001
281a4e39c2STakashi Sakamoto 
291a4e39c2STakashi Sakamoto MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
301a4e39c2STakashi Sakamoto MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
311a4e39c2STakashi Sakamoto MODULE_LICENSE("GPL v2");
321a4e39c2STakashi Sakamoto MODULE_ALIAS("snd-firewire-speakers");
339e2004f9STakashi Sakamoto MODULE_ALIAS("snd-scs1x");
341a4e39c2STakashi Sakamoto 
35d6ce6bbdSTakashi Sakamoto struct compat_info {
36d6ce6bbdSTakashi Sakamoto 	const char *driver_name;
37d6ce6bbdSTakashi Sakamoto 	const char *vendor_name;
38d6ce6bbdSTakashi Sakamoto 	const char *model_name;
39d6ce6bbdSTakashi Sakamoto };
40d6ce6bbdSTakashi Sakamoto 
41ec4dba50STakashi Sakamoto static bool detect_loud_models(struct fw_unit *unit)
42ec4dba50STakashi Sakamoto {
43ec4dba50STakashi Sakamoto 	const char *const models[] = {
44ec4dba50STakashi Sakamoto 		"Onyxi",
45ec4dba50STakashi Sakamoto 		"Onyx-i",
4603abd33aSTakashi Sakamoto 		"Onyx 1640i",
47ec4dba50STakashi Sakamoto 		"d.Pro",
48ec4dba50STakashi Sakamoto 		"Mackie Onyx Satellite",
49ec4dba50STakashi Sakamoto 		"Tapco LINK.firewire 4x6",
50ec4dba50STakashi Sakamoto 		"U.420"};
51ec4dba50STakashi Sakamoto 	char model[32];
52ec4dba50STakashi Sakamoto 	int err;
53ec4dba50STakashi Sakamoto 
54ec4dba50STakashi Sakamoto 	err = fw_csr_string(unit->directory, CSR_MODEL,
55ec4dba50STakashi Sakamoto 			    model, sizeof(model));
56ec4dba50STakashi Sakamoto 	if (err < 0)
570d3aba30SDan Carpenter 		return false;
58ec4dba50STakashi Sakamoto 
592cc47d31SYisheng Xie 	return match_string(models, ARRAY_SIZE(models), model) >= 0;
60ec4dba50STakashi Sakamoto }
61ec4dba50STakashi Sakamoto 
62fec7b753STakashi Sakamoto static int name_card(struct snd_oxfw *oxfw)
631a4e39c2STakashi Sakamoto {
64fec7b753STakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
65d6ce6bbdSTakashi Sakamoto 	const struct compat_info *info;
66ec4dba50STakashi Sakamoto 	char vendor[24];
67ec4dba50STakashi Sakamoto 	char model[32];
68fec7b753STakashi Sakamoto 	const char *d, *v, *m;
69fec7b753STakashi Sakamoto 	u32 firmware;
701a4e39c2STakashi Sakamoto 	int err;
711a4e39c2STakashi Sakamoto 
72ec4dba50STakashi Sakamoto 	/* get vendor name from root directory */
73ec4dba50STakashi Sakamoto 	err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR,
74ec4dba50STakashi Sakamoto 			    vendor, sizeof(vendor));
75ec4dba50STakashi Sakamoto 	if (err < 0)
76ec4dba50STakashi Sakamoto 		goto end;
77ec4dba50STakashi Sakamoto 
78ec4dba50STakashi Sakamoto 	/* get model name from unit directory */
79ec4dba50STakashi Sakamoto 	err = fw_csr_string(oxfw->unit->directory, CSR_MODEL,
80ec4dba50STakashi Sakamoto 			    model, sizeof(model));
81ec4dba50STakashi Sakamoto 	if (err < 0)
82ec4dba50STakashi Sakamoto 		goto end;
83ec4dba50STakashi Sakamoto 
84fec7b753STakashi Sakamoto 	err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST,
85fec7b753STakashi Sakamoto 				 OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0);
86fec7b753STakashi Sakamoto 	if (err < 0)
87fec7b753STakashi Sakamoto 		goto end;
88fec7b753STakashi Sakamoto 	be32_to_cpus(&firmware);
89fec7b753STakashi Sakamoto 
90ec4dba50STakashi Sakamoto 	/* to apply card definitions */
9127e66635STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_GRIFFIN ||
9227e66635STakashi Sakamoto 	    oxfw->entry->vendor_id == VENDOR_LACIE) {
93d6ce6bbdSTakashi Sakamoto 		info = (const struct compat_info *)oxfw->entry->driver_data;
9427e66635STakashi Sakamoto 		d = info->driver_name;
9527e66635STakashi Sakamoto 		v = info->vendor_name;
9627e66635STakashi Sakamoto 		m = info->model_name;
97ec4dba50STakashi Sakamoto 	} else {
98ec4dba50STakashi Sakamoto 		d = "OXFW";
99ec4dba50STakashi Sakamoto 		v = vendor;
100ec4dba50STakashi Sakamoto 		m = model;
101ec4dba50STakashi Sakamoto 	}
102fec7b753STakashi Sakamoto 
103fec7b753STakashi Sakamoto 	strcpy(oxfw->card->driver, d);
104fec7b753STakashi Sakamoto 	strcpy(oxfw->card->mixername, m);
105fec7b753STakashi Sakamoto 	strcpy(oxfw->card->shortname, m);
106fec7b753STakashi Sakamoto 
107fec7b753STakashi Sakamoto 	snprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
108fec7b753STakashi Sakamoto 		 "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
109fec7b753STakashi Sakamoto 		 v, m, firmware >> 20, firmware & 0xffff,
110fec7b753STakashi Sakamoto 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
111fec7b753STakashi Sakamoto 		 dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
112fec7b753STakashi Sakamoto end:
113fec7b753STakashi Sakamoto 	return err;
1141a4e39c2STakashi Sakamoto }
1151a4e39c2STakashi Sakamoto 
1166c29230eSTakashi Sakamoto static void oxfw_free(struct snd_oxfw *oxfw)
1171a4e39c2STakashi Sakamoto {
1185cd1d3f4STakashi Sakamoto 	unsigned int i;
1195cd1d3f4STakashi Sakamoto 
120dec84316STakashi Sakamoto 	snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
121dec84316STakashi Sakamoto 	if (oxfw->has_output)
122dec84316STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
123dec84316STakashi Sakamoto 
12412ed7192STakashi Sakamoto 	fw_unit_put(oxfw->unit);
12512ed7192STakashi Sakamoto 
126b0ac0009STakashi Sakamoto 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
127b0ac0009STakashi Sakamoto 		kfree(oxfw->tx_stream_formats[i]);
1285cd1d3f4STakashi Sakamoto 		kfree(oxfw->rx_stream_formats[i]);
129b0ac0009STakashi Sakamoto 	}
1301a4e39c2STakashi Sakamoto 
131c582cc66STakashi Sakamoto 	kfree(oxfw->spec);
1321a4e39c2STakashi Sakamoto 	mutex_destroy(&oxfw->mutex);
1331a4e39c2STakashi Sakamoto }
1341a4e39c2STakashi Sakamoto 
1356c29230eSTakashi Sakamoto /*
1366c29230eSTakashi Sakamoto  * This module releases the FireWire unit data after all ALSA character devices
1376c29230eSTakashi Sakamoto  * are released by applications. This is for releasing stream data or finishing
1386c29230eSTakashi Sakamoto  * transactions safely. Thus at returning from .remove(), this module still keep
1396c29230eSTakashi Sakamoto  * references for the unit.
1406c29230eSTakashi Sakamoto  */
1416c29230eSTakashi Sakamoto static void oxfw_card_free(struct snd_card *card)
1426c29230eSTakashi Sakamoto {
1436c29230eSTakashi Sakamoto 	oxfw_free(card->private_data);
1446c29230eSTakashi Sakamoto }
1456c29230eSTakashi Sakamoto 
1465ce8cc48STakashi Sakamoto static int detect_quirks(struct snd_oxfw *oxfw)
14713f3a46dSTakashi Sakamoto {
14813f3a46dSTakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
14913f3a46dSTakashi Sakamoto 	struct fw_csr_iterator it;
15013f3a46dSTakashi Sakamoto 	int key, val;
15113f3a46dSTakashi Sakamoto 	int vendor, model;
15213f3a46dSTakashi Sakamoto 
15327e66635STakashi Sakamoto 	/*
1545ce8cc48STakashi Sakamoto 	 * Add ALSA control elements for two models to keep compatibility to
1555ce8cc48STakashi Sakamoto 	 * old firewire-speaker module.
1565ce8cc48STakashi Sakamoto 	 */
1573e2f4570STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_GRIFFIN)
1583e2f4570STakashi Sakamoto 		return snd_oxfw_add_spkr(oxfw, false);
1593e2f4570STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_LACIE)
1603e2f4570STakashi Sakamoto 		return snd_oxfw_add_spkr(oxfw, true);
1615ce8cc48STakashi Sakamoto 
1625ce8cc48STakashi Sakamoto 	/*
1639e2004f9STakashi Sakamoto 	 * Stanton models supports asynchronous transactions for unique MIDI
1649e2004f9STakashi Sakamoto 	 * messages.
1659e2004f9STakashi Sakamoto 	 */
166de5126ccSTakashi Sakamoto 	if (oxfw->entry->vendor_id == OUI_STANTON) {
167de5126ccSTakashi Sakamoto 		/* No physical MIDI ports. */
168de5126ccSTakashi Sakamoto 		oxfw->midi_input_ports = 0;
169de5126ccSTakashi Sakamoto 		oxfw->midi_output_ports = 0;
170de5126ccSTakashi Sakamoto 
171de5126ccSTakashi Sakamoto 		/* Output stream exists but no data channels are useful. */
172de5126ccSTakashi Sakamoto 		oxfw->has_output = false;
173de5126ccSTakashi Sakamoto 
1749e2004f9STakashi Sakamoto 		return snd_oxfw_scs1x_add(oxfw);
175de5126ccSTakashi Sakamoto 	}
1769e2004f9STakashi Sakamoto 
1779e2004f9STakashi Sakamoto 	/*
17827e66635STakashi Sakamoto 	 * TASCAM FireOne has physical control and requires a pair of additional
17927e66635STakashi Sakamoto 	 * MIDI ports.
18027e66635STakashi Sakamoto 	 */
18127e66635STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_TASCAM) {
18227e66635STakashi Sakamoto 		oxfw->midi_input_ports++;
18327e66635STakashi Sakamoto 		oxfw->midi_output_ports++;
1845ce8cc48STakashi Sakamoto 		return 0;
18527e66635STakashi Sakamoto 	}
18627e66635STakashi Sakamoto 
18713f3a46dSTakashi Sakamoto 	/* Seek from Root Directory of Config ROM. */
18813f3a46dSTakashi Sakamoto 	vendor = model = 0;
18913f3a46dSTakashi Sakamoto 	fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
19013f3a46dSTakashi Sakamoto 	while (fw_csr_iterator_next(&it, &key, &val)) {
19113f3a46dSTakashi Sakamoto 		if (key == CSR_VENDOR)
19213f3a46dSTakashi Sakamoto 			vendor = val;
19313f3a46dSTakashi Sakamoto 		else if (key == CSR_MODEL)
19413f3a46dSTakashi Sakamoto 			model = val;
19513f3a46dSTakashi Sakamoto 	}
19613f3a46dSTakashi Sakamoto 
19713f3a46dSTakashi Sakamoto 	/*
19813f3a46dSTakashi Sakamoto 	 * Mackie Onyx Satellite with base station has a quirk to report a wrong
19913f3a46dSTakashi Sakamoto 	 * value in 'dbs' field of CIP header against its format information.
20013f3a46dSTakashi Sakamoto 	 */
20113f3a46dSTakashi Sakamoto 	if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
20213f3a46dSTakashi Sakamoto 		oxfw->wrong_dbs = true;
2035ce8cc48STakashi Sakamoto 
2045ce8cc48STakashi Sakamoto 	return 0;
20513f3a46dSTakashi Sakamoto }
20613f3a46dSTakashi Sakamoto 
2076c29230eSTakashi Sakamoto static void do_registration(struct work_struct *work)
2081a4e39c2STakashi Sakamoto {
2096c29230eSTakashi Sakamoto 	struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work);
2101a4e39c2STakashi Sakamoto 	int err;
2111a4e39c2STakashi Sakamoto 
2126c29230eSTakashi Sakamoto 	if (oxfw->registered)
2136c29230eSTakashi Sakamoto 		return;
214ec4dba50STakashi Sakamoto 
2156c29230eSTakashi Sakamoto 	err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0,
2166c29230eSTakashi Sakamoto 			   &oxfw->card);
2171a4e39c2STakashi Sakamoto 	if (err < 0)
2186c29230eSTakashi Sakamoto 		return;
2195cd1d3f4STakashi Sakamoto 
2203f47152aSTakashi Sakamoto 	err = name_card(oxfw);
2215ce8cc48STakashi Sakamoto 	if (err < 0)
2225ce8cc48STakashi Sakamoto 		goto error;
22313f3a46dSTakashi Sakamoto 
2243d016d57STakashi Sakamoto 	err = snd_oxfw_stream_discover(oxfw);
225fec7b753STakashi Sakamoto 	if (err < 0)
226fec7b753STakashi Sakamoto 		goto error;
2271a4e39c2STakashi Sakamoto 
2283d016d57STakashi Sakamoto 	err = detect_quirks(oxfw);
2296c29230eSTakashi Sakamoto 	if (err < 0)
2306c29230eSTakashi Sakamoto 		goto error;
2316c29230eSTakashi Sakamoto 
2326c29230eSTakashi Sakamoto 	err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream);
2336c29230eSTakashi Sakamoto 	if (err < 0)
2346c29230eSTakashi Sakamoto 		goto error;
2356c29230eSTakashi Sakamoto 	if (oxfw->has_output) {
2366c29230eSTakashi Sakamoto 		err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream);
2376c29230eSTakashi Sakamoto 		if (err < 0)
2386c29230eSTakashi Sakamoto 			goto error;
2396c29230eSTakashi Sakamoto 	}
2406c29230eSTakashi Sakamoto 
2413713d93aSTakashi Sakamoto 	err = snd_oxfw_create_pcm(oxfw);
2421a4e39c2STakashi Sakamoto 	if (err < 0)
2431a4e39c2STakashi Sakamoto 		goto error;
2441a4e39c2STakashi Sakamoto 
2453c96101fSTakashi Sakamoto 	snd_oxfw_proc_init(oxfw);
2463c96101fSTakashi Sakamoto 
24705588d34STakashi Sakamoto 	err = snd_oxfw_create_midi(oxfw);
24805588d34STakashi Sakamoto 	if (err < 0)
24905588d34STakashi Sakamoto 		goto error;
25005588d34STakashi Sakamoto 
2518985f4acSTakashi Sakamoto 	err = snd_oxfw_create_hwdep(oxfw);
2528985f4acSTakashi Sakamoto 	if (err < 0)
2538985f4acSTakashi Sakamoto 		goto error;
2548985f4acSTakashi Sakamoto 
2556c29230eSTakashi Sakamoto 	err = snd_card_register(oxfw->card);
2561a4e39c2STakashi Sakamoto 	if (err < 0)
2571a4e39c2STakashi Sakamoto 		goto error;
2581a4e39c2STakashi Sakamoto 
2596c29230eSTakashi Sakamoto 	/*
2606c29230eSTakashi Sakamoto 	 * After registered, oxfw instance can be released corresponding to
2616c29230eSTakashi Sakamoto 	 * releasing the sound card instance.
2626c29230eSTakashi Sakamoto 	 */
2636c29230eSTakashi Sakamoto 	oxfw->card->private_free = oxfw_card_free;
2646c29230eSTakashi Sakamoto 	oxfw->card->private_data = oxfw;
2656c29230eSTakashi Sakamoto 	oxfw->registered = true;
2666c29230eSTakashi Sakamoto 
2676c29230eSTakashi Sakamoto 	return;
2686c29230eSTakashi Sakamoto error:
269b0ac0009STakashi Sakamoto 	snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
270b0ac0009STakashi Sakamoto 	if (oxfw->has_output)
271b0ac0009STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
2726c29230eSTakashi Sakamoto 	snd_card_free(oxfw->card);
2736c29230eSTakashi Sakamoto 	dev_info(&oxfw->unit->device,
2746c29230eSTakashi Sakamoto 		 "Sound card registration failed: %d\n", err);
275e2786ca6STakashi Sakamoto }
2766c29230eSTakashi Sakamoto 
2776c29230eSTakashi Sakamoto static int oxfw_probe(struct fw_unit *unit,
2786c29230eSTakashi Sakamoto 		      const struct ieee1394_device_id *entry)
2796c29230eSTakashi Sakamoto {
2806c29230eSTakashi Sakamoto 	struct snd_oxfw *oxfw;
2816c29230eSTakashi Sakamoto 
2826c29230eSTakashi Sakamoto 	if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit))
2836c29230eSTakashi Sakamoto 		return -ENODEV;
2846c29230eSTakashi Sakamoto 
2856c29230eSTakashi Sakamoto 	/* Allocate this independent of sound card instance. */
2866c29230eSTakashi Sakamoto 	oxfw = kzalloc(sizeof(struct snd_oxfw), GFP_KERNEL);
2876c29230eSTakashi Sakamoto 	if (oxfw == NULL)
2886c29230eSTakashi Sakamoto 		return -ENOMEM;
2896c29230eSTakashi Sakamoto 
2906c29230eSTakashi Sakamoto 	oxfw->entry = entry;
2916c29230eSTakashi Sakamoto 	oxfw->unit = fw_unit_get(unit);
2921a4e39c2STakashi Sakamoto 	dev_set_drvdata(&unit->device, oxfw);
2931a4e39c2STakashi Sakamoto 
2946c29230eSTakashi Sakamoto 	mutex_init(&oxfw->mutex);
2956c29230eSTakashi Sakamoto 	spin_lock_init(&oxfw->lock);
2966c29230eSTakashi Sakamoto 	init_waitqueue_head(&oxfw->hwdep_wait);
2976c29230eSTakashi Sakamoto 
2986c29230eSTakashi Sakamoto 	/* Allocate and register this sound card later. */
2996c29230eSTakashi Sakamoto 	INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration);
3006c29230eSTakashi Sakamoto 	snd_fw_schedule_registration(unit, &oxfw->dwork);
3016c29230eSTakashi Sakamoto 
3021a4e39c2STakashi Sakamoto 	return 0;
3031a4e39c2STakashi Sakamoto }
3041a4e39c2STakashi Sakamoto 
3051a4e39c2STakashi Sakamoto static void oxfw_bus_reset(struct fw_unit *unit)
3061a4e39c2STakashi Sakamoto {
3071a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
3081a4e39c2STakashi Sakamoto 
3096c29230eSTakashi Sakamoto 	if (!oxfw->registered)
3106c29230eSTakashi Sakamoto 		snd_fw_schedule_registration(unit, &oxfw->dwork);
3116c29230eSTakashi Sakamoto 
3121a4e39c2STakashi Sakamoto 	fcp_bus_reset(oxfw->unit);
3131a4e39c2STakashi Sakamoto 
3146c29230eSTakashi Sakamoto 	if (oxfw->registered) {
3151a4e39c2STakashi Sakamoto 		mutex_lock(&oxfw->mutex);
316b0ac0009STakashi Sakamoto 
317b0ac0009STakashi Sakamoto 		snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream);
318b0ac0009STakashi Sakamoto 		if (oxfw->has_output)
319b0ac0009STakashi Sakamoto 			snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
320b0ac0009STakashi Sakamoto 
3211a4e39c2STakashi Sakamoto 		mutex_unlock(&oxfw->mutex);
3229e2004f9STakashi Sakamoto 
3239e2004f9STakashi Sakamoto 		if (oxfw->entry->vendor_id == OUI_STANTON)
3249e2004f9STakashi Sakamoto 			snd_oxfw_scs1x_update(oxfw);
3251a4e39c2STakashi Sakamoto 	}
3266c29230eSTakashi Sakamoto }
3271a4e39c2STakashi Sakamoto 
3281a4e39c2STakashi Sakamoto static void oxfw_remove(struct fw_unit *unit)
3291a4e39c2STakashi Sakamoto {
3301a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
3311a4e39c2STakashi Sakamoto 
3326c29230eSTakashi Sakamoto 	/*
3336c29230eSTakashi Sakamoto 	 * Confirm to stop the work for registration before the sound card is
3346c29230eSTakashi Sakamoto 	 * going to be released. The work is not scheduled again because bus
3356c29230eSTakashi Sakamoto 	 * reset handler is not called anymore.
3366c29230eSTakashi Sakamoto 	 */
3376c29230eSTakashi Sakamoto 	cancel_delayed_work_sync(&oxfw->dwork);
3386c29230eSTakashi Sakamoto 
3396c29230eSTakashi Sakamoto 	if (oxfw->registered) {
34012ed7192STakashi Sakamoto 		/* No need to wait for releasing card object in this context. */
3411a4e39c2STakashi Sakamoto 		snd_card_free_when_closed(oxfw->card);
3426c29230eSTakashi Sakamoto 	} else {
3436c29230eSTakashi Sakamoto 		/* Don't forget this case. */
3446c29230eSTakashi Sakamoto 		oxfw_free(oxfw);
3456c29230eSTakashi Sakamoto 	}
3461a4e39c2STakashi Sakamoto }
3471a4e39c2STakashi Sakamoto 
348d6ce6bbdSTakashi Sakamoto static const struct compat_info griffin_firewave = {
3491a4e39c2STakashi Sakamoto 	.driver_name = "FireWave",
350fec7b753STakashi Sakamoto 	.vendor_name = "Griffin",
351fec7b753STakashi Sakamoto 	.model_name = "FireWave",
3521a4e39c2STakashi Sakamoto };
3531a4e39c2STakashi Sakamoto 
354d6ce6bbdSTakashi Sakamoto static const struct compat_info lacie_speakers = {
3551a4e39c2STakashi Sakamoto 	.driver_name = "FWSpeakers",
356fec7b753STakashi Sakamoto 	.vendor_name = "LaCie",
357fec7b753STakashi Sakamoto 	.model_name = "FireWire Speakers",
3581a4e39c2STakashi Sakamoto };
3591a4e39c2STakashi Sakamoto 
3601a4e39c2STakashi Sakamoto static const struct ieee1394_device_id oxfw_id_table[] = {
3611a4e39c2STakashi Sakamoto 	{
3621a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
3631a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
3641a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
3651a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
3661a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_GRIFFIN,
3671a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
3681a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
3691a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
3701a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&griffin_firewave,
3711a4e39c2STakashi Sakamoto 	},
3721a4e39c2STakashi Sakamoto 	{
3731a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
3741a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
3751a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
3761a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
3771a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_LACIE,
3781a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
3791a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
3801a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
3811a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&lacie_speakers,
3821a4e39c2STakashi Sakamoto 	},
383ec4dba50STakashi Sakamoto 	/* Behringer,F-Control Audio 202 */
384ec4dba50STakashi Sakamoto 	{
385ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
386ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
387ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_BEHRINGER,
388ec4dba50STakashi Sakamoto 		.model_id	= 0x00fc22,
389ec4dba50STakashi Sakamoto 	},
390ec4dba50STakashi Sakamoto 	/*
391ec4dba50STakashi Sakamoto 	 * Any Mackie(Loud) models (name string/model id):
392ec4dba50STakashi Sakamoto 	 *  Onyx-i series (former models):	0x081216
393ec4dba50STakashi Sakamoto 	 *  Mackie Onyx Satellite:		0x00200f
394ec4dba50STakashi Sakamoto 	 *  Tapco LINK.firewire 4x6:		0x000460
395ec4dba50STakashi Sakamoto 	 *  d.2 pro:				Unknown
396ec4dba50STakashi Sakamoto 	 *  d.4 pro:				Unknown
397ec4dba50STakashi Sakamoto 	 *  U.420:				Unknown
398ec4dba50STakashi Sakamoto 	 *  U.420d:				Unknown
399ec4dba50STakashi Sakamoto 	 */
400ec4dba50STakashi Sakamoto 	{
401ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
402ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_SPECIFIER_ID |
403ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_VERSION,
404ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_LOUD,
405ec4dba50STakashi Sakamoto 		.specifier_id	= SPECIFIER_1394TA,
406ec4dba50STakashi Sakamoto 		.version	= VERSION_AVC,
407ec4dba50STakashi Sakamoto 	},
408759a2f40STakashi Sakamoto 	/* TASCAM, FireOne */
409759a2f40STakashi Sakamoto 	{
410759a2f40STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
411759a2f40STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
412759a2f40STakashi Sakamoto 		.vendor_id	= VENDOR_TASCAM,
413759a2f40STakashi Sakamoto 		.model_id	= 0x800007,
414759a2f40STakashi Sakamoto 	},
4159e2004f9STakashi Sakamoto 	/* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */
4169e2004f9STakashi Sakamoto 	{
4179e2004f9STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
4189e2004f9STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
4199e2004f9STakashi Sakamoto 		.vendor_id	= OUI_STANTON,
4209e2004f9STakashi Sakamoto 		.model_id	= 0x001000,
4219e2004f9STakashi Sakamoto 	},
4229e2004f9STakashi Sakamoto 	/* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */
4239e2004f9STakashi Sakamoto 	{
4249e2004f9STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
4259e2004f9STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
4269e2004f9STakashi Sakamoto 		.vendor_id	= OUI_STANTON,
4279e2004f9STakashi Sakamoto 		.model_id	= 0x002000,
4289e2004f9STakashi Sakamoto 	},
4291a4e39c2STakashi Sakamoto 	{ }
4301a4e39c2STakashi Sakamoto };
4311a4e39c2STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
4321a4e39c2STakashi Sakamoto 
4331a4e39c2STakashi Sakamoto static struct fw_driver oxfw_driver = {
4341a4e39c2STakashi Sakamoto 	.driver   = {
4351a4e39c2STakashi Sakamoto 		.owner	= THIS_MODULE,
4361a4e39c2STakashi Sakamoto 		.name	= KBUILD_MODNAME,
4371a4e39c2STakashi Sakamoto 		.bus	= &fw_bus_type,
4381a4e39c2STakashi Sakamoto 	},
4391a4e39c2STakashi Sakamoto 	.probe    = oxfw_probe,
4401a4e39c2STakashi Sakamoto 	.update   = oxfw_bus_reset,
4411a4e39c2STakashi Sakamoto 	.remove   = oxfw_remove,
4421a4e39c2STakashi Sakamoto 	.id_table = oxfw_id_table,
4431a4e39c2STakashi Sakamoto };
4441a4e39c2STakashi Sakamoto 
4451a4e39c2STakashi Sakamoto static int __init snd_oxfw_init(void)
4461a4e39c2STakashi Sakamoto {
4471a4e39c2STakashi Sakamoto 	return driver_register(&oxfw_driver.driver);
4481a4e39c2STakashi Sakamoto }
4491a4e39c2STakashi Sakamoto 
4501a4e39c2STakashi Sakamoto static void __exit snd_oxfw_exit(void)
4511a4e39c2STakashi Sakamoto {
4521a4e39c2STakashi Sakamoto 	driver_unregister(&oxfw_driver.driver);
4531a4e39c2STakashi Sakamoto }
4541a4e39c2STakashi Sakamoto 
4551a4e39c2STakashi Sakamoto module_init(snd_oxfw_init);
4561a4e39c2STakashi Sakamoto module_exit(snd_oxfw_exit);
457