xref: /openbmc/linux/sound/firewire/oxfw/oxfw.c (revision 6c29230e)
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",
46ec4dba50STakashi Sakamoto 		"d.Pro",
47ec4dba50STakashi Sakamoto 		"Mackie Onyx Satellite",
48ec4dba50STakashi Sakamoto 		"Tapco LINK.firewire 4x6",
49ec4dba50STakashi Sakamoto 		"U.420"};
50ec4dba50STakashi Sakamoto 	char model[32];
51ec4dba50STakashi Sakamoto 	unsigned int i;
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 
59ec4dba50STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(models); i++) {
60ec4dba50STakashi Sakamoto 		if (strcmp(models[i], model) == 0)
61ec4dba50STakashi Sakamoto 			break;
62ec4dba50STakashi Sakamoto 	}
63ec4dba50STakashi Sakamoto 
64ec4dba50STakashi Sakamoto 	return (i < ARRAY_SIZE(models));
65ec4dba50STakashi Sakamoto }
66ec4dba50STakashi Sakamoto 
67fec7b753STakashi Sakamoto static int name_card(struct snd_oxfw *oxfw)
681a4e39c2STakashi Sakamoto {
69fec7b753STakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
70d6ce6bbdSTakashi Sakamoto 	const struct compat_info *info;
71ec4dba50STakashi Sakamoto 	char vendor[24];
72ec4dba50STakashi Sakamoto 	char model[32];
73fec7b753STakashi Sakamoto 	const char *d, *v, *m;
74fec7b753STakashi Sakamoto 	u32 firmware;
751a4e39c2STakashi Sakamoto 	int err;
761a4e39c2STakashi Sakamoto 
77ec4dba50STakashi Sakamoto 	/* get vendor name from root directory */
78ec4dba50STakashi Sakamoto 	err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR,
79ec4dba50STakashi Sakamoto 			    vendor, sizeof(vendor));
80ec4dba50STakashi Sakamoto 	if (err < 0)
81ec4dba50STakashi Sakamoto 		goto end;
82ec4dba50STakashi Sakamoto 
83ec4dba50STakashi Sakamoto 	/* get model name from unit directory */
84ec4dba50STakashi Sakamoto 	err = fw_csr_string(oxfw->unit->directory, CSR_MODEL,
85ec4dba50STakashi Sakamoto 			    model, sizeof(model));
86ec4dba50STakashi Sakamoto 	if (err < 0)
87ec4dba50STakashi Sakamoto 		goto end;
88ec4dba50STakashi Sakamoto 
89fec7b753STakashi Sakamoto 	err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST,
90fec7b753STakashi Sakamoto 				 OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0);
91fec7b753STakashi Sakamoto 	if (err < 0)
92fec7b753STakashi Sakamoto 		goto end;
93fec7b753STakashi Sakamoto 	be32_to_cpus(&firmware);
94fec7b753STakashi Sakamoto 
95ec4dba50STakashi Sakamoto 	/* to apply card definitions */
9627e66635STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_GRIFFIN ||
9727e66635STakashi Sakamoto 	    oxfw->entry->vendor_id == VENDOR_LACIE) {
98d6ce6bbdSTakashi Sakamoto 		info = (const struct compat_info *)oxfw->entry->driver_data;
9927e66635STakashi Sakamoto 		d = info->driver_name;
10027e66635STakashi Sakamoto 		v = info->vendor_name;
10127e66635STakashi Sakamoto 		m = info->model_name;
102ec4dba50STakashi Sakamoto 	} else {
103ec4dba50STakashi Sakamoto 		d = "OXFW";
104ec4dba50STakashi Sakamoto 		v = vendor;
105ec4dba50STakashi Sakamoto 		m = model;
106ec4dba50STakashi Sakamoto 	}
107fec7b753STakashi Sakamoto 
108fec7b753STakashi Sakamoto 	strcpy(oxfw->card->driver, d);
109fec7b753STakashi Sakamoto 	strcpy(oxfw->card->mixername, m);
110fec7b753STakashi Sakamoto 	strcpy(oxfw->card->shortname, m);
111fec7b753STakashi Sakamoto 
112fec7b753STakashi Sakamoto 	snprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
113fec7b753STakashi Sakamoto 		 "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
114fec7b753STakashi Sakamoto 		 v, m, firmware >> 20, firmware & 0xffff,
115fec7b753STakashi Sakamoto 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
116fec7b753STakashi Sakamoto 		 dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
117fec7b753STakashi Sakamoto end:
118fec7b753STakashi Sakamoto 	return err;
1191a4e39c2STakashi Sakamoto }
1201a4e39c2STakashi Sakamoto 
1216c29230eSTakashi Sakamoto static void oxfw_free(struct snd_oxfw *oxfw)
1221a4e39c2STakashi Sakamoto {
1235cd1d3f4STakashi Sakamoto 	unsigned int i;
1245cd1d3f4STakashi Sakamoto 
125dec84316STakashi Sakamoto 	snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
126dec84316STakashi Sakamoto 	if (oxfw->has_output)
127dec84316STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
128dec84316STakashi Sakamoto 
12912ed7192STakashi Sakamoto 	fw_unit_put(oxfw->unit);
13012ed7192STakashi Sakamoto 
131b0ac0009STakashi Sakamoto 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
132b0ac0009STakashi Sakamoto 		kfree(oxfw->tx_stream_formats[i]);
1335cd1d3f4STakashi Sakamoto 		kfree(oxfw->rx_stream_formats[i]);
134b0ac0009STakashi Sakamoto 	}
1351a4e39c2STakashi Sakamoto 
136c582cc66STakashi Sakamoto 	kfree(oxfw->spec);
1371a4e39c2STakashi Sakamoto 	mutex_destroy(&oxfw->mutex);
1381a4e39c2STakashi Sakamoto }
1391a4e39c2STakashi Sakamoto 
1406c29230eSTakashi Sakamoto /*
1416c29230eSTakashi Sakamoto  * This module releases the FireWire unit data after all ALSA character devices
1426c29230eSTakashi Sakamoto  * are released by applications. This is for releasing stream data or finishing
1436c29230eSTakashi Sakamoto  * transactions safely. Thus at returning from .remove(), this module still keep
1446c29230eSTakashi Sakamoto  * references for the unit.
1456c29230eSTakashi Sakamoto  */
1466c29230eSTakashi Sakamoto static void oxfw_card_free(struct snd_card *card)
1476c29230eSTakashi Sakamoto {
1486c29230eSTakashi Sakamoto 	oxfw_free(card->private_data);
1496c29230eSTakashi Sakamoto }
1506c29230eSTakashi Sakamoto 
1515ce8cc48STakashi Sakamoto static int detect_quirks(struct snd_oxfw *oxfw)
15213f3a46dSTakashi Sakamoto {
15313f3a46dSTakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
15413f3a46dSTakashi Sakamoto 	struct fw_csr_iterator it;
15513f3a46dSTakashi Sakamoto 	int key, val;
15613f3a46dSTakashi Sakamoto 	int vendor, model;
15713f3a46dSTakashi Sakamoto 
15827e66635STakashi Sakamoto 	/*
1595ce8cc48STakashi Sakamoto 	 * Add ALSA control elements for two models to keep compatibility to
1605ce8cc48STakashi Sakamoto 	 * old firewire-speaker module.
1615ce8cc48STakashi Sakamoto 	 */
1623e2f4570STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_GRIFFIN)
1633e2f4570STakashi Sakamoto 		return snd_oxfw_add_spkr(oxfw, false);
1643e2f4570STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_LACIE)
1653e2f4570STakashi Sakamoto 		return snd_oxfw_add_spkr(oxfw, true);
1665ce8cc48STakashi Sakamoto 
1675ce8cc48STakashi Sakamoto 	/*
1689e2004f9STakashi Sakamoto 	 * Stanton models supports asynchronous transactions for unique MIDI
1699e2004f9STakashi Sakamoto 	 * messages.
1709e2004f9STakashi Sakamoto 	 */
171de5126ccSTakashi Sakamoto 	if (oxfw->entry->vendor_id == OUI_STANTON) {
172de5126ccSTakashi Sakamoto 		/* No physical MIDI ports. */
173de5126ccSTakashi Sakamoto 		oxfw->midi_input_ports = 0;
174de5126ccSTakashi Sakamoto 		oxfw->midi_output_ports = 0;
175de5126ccSTakashi Sakamoto 
176de5126ccSTakashi Sakamoto 		/* Output stream exists but no data channels are useful. */
177de5126ccSTakashi Sakamoto 		oxfw->has_output = false;
178de5126ccSTakashi Sakamoto 
1799e2004f9STakashi Sakamoto 		return snd_oxfw_scs1x_add(oxfw);
180de5126ccSTakashi Sakamoto 	}
1819e2004f9STakashi Sakamoto 
1829e2004f9STakashi Sakamoto 	/*
18327e66635STakashi Sakamoto 	 * TASCAM FireOne has physical control and requires a pair of additional
18427e66635STakashi Sakamoto 	 * MIDI ports.
18527e66635STakashi Sakamoto 	 */
18627e66635STakashi Sakamoto 	if (oxfw->entry->vendor_id == VENDOR_TASCAM) {
18727e66635STakashi Sakamoto 		oxfw->midi_input_ports++;
18827e66635STakashi Sakamoto 		oxfw->midi_output_ports++;
1895ce8cc48STakashi Sakamoto 		return 0;
19027e66635STakashi Sakamoto 	}
19127e66635STakashi Sakamoto 
19213f3a46dSTakashi Sakamoto 	/* Seek from Root Directory of Config ROM. */
19313f3a46dSTakashi Sakamoto 	vendor = model = 0;
19413f3a46dSTakashi Sakamoto 	fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
19513f3a46dSTakashi Sakamoto 	while (fw_csr_iterator_next(&it, &key, &val)) {
19613f3a46dSTakashi Sakamoto 		if (key == CSR_VENDOR)
19713f3a46dSTakashi Sakamoto 			vendor = val;
19813f3a46dSTakashi Sakamoto 		else if (key == CSR_MODEL)
19913f3a46dSTakashi Sakamoto 			model = val;
20013f3a46dSTakashi Sakamoto 	}
20113f3a46dSTakashi Sakamoto 
20213f3a46dSTakashi Sakamoto 	/*
20313f3a46dSTakashi Sakamoto 	 * Mackie Onyx Satellite with base station has a quirk to report a wrong
20413f3a46dSTakashi Sakamoto 	 * value in 'dbs' field of CIP header against its format information.
20513f3a46dSTakashi Sakamoto 	 */
20613f3a46dSTakashi Sakamoto 	if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
20713f3a46dSTakashi Sakamoto 		oxfw->wrong_dbs = true;
2085ce8cc48STakashi Sakamoto 
2095ce8cc48STakashi Sakamoto 	return 0;
21013f3a46dSTakashi Sakamoto }
21113f3a46dSTakashi Sakamoto 
2126c29230eSTakashi Sakamoto static void do_registration(struct work_struct *work)
2131a4e39c2STakashi Sakamoto {
2146c29230eSTakashi Sakamoto 	struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work);
2151a4e39c2STakashi Sakamoto 	int err;
2161a4e39c2STakashi Sakamoto 
2176c29230eSTakashi Sakamoto 	if (oxfw->registered)
2186c29230eSTakashi Sakamoto 		return;
219ec4dba50STakashi Sakamoto 
2206c29230eSTakashi Sakamoto 	err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0,
2216c29230eSTakashi Sakamoto 			   &oxfw->card);
2221a4e39c2STakashi Sakamoto 	if (err < 0)
2236c29230eSTakashi Sakamoto 		return;
2245cd1d3f4STakashi Sakamoto 
2253f47152aSTakashi Sakamoto 	err = name_card(oxfw);
2265ce8cc48STakashi Sakamoto 	if (err < 0)
2275ce8cc48STakashi Sakamoto 		goto error;
22813f3a46dSTakashi Sakamoto 
2293f47152aSTakashi Sakamoto 	err = detect_quirks(oxfw);
230fec7b753STakashi Sakamoto 	if (err < 0)
231fec7b753STakashi Sakamoto 		goto error;
2321a4e39c2STakashi Sakamoto 
2336c29230eSTakashi Sakamoto 	err = snd_oxfw_stream_discover(oxfw);
2346c29230eSTakashi Sakamoto 	if (err < 0)
2356c29230eSTakashi Sakamoto 		goto error;
2366c29230eSTakashi Sakamoto 
2376c29230eSTakashi Sakamoto 	err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream);
2386c29230eSTakashi Sakamoto 	if (err < 0)
2396c29230eSTakashi Sakamoto 		goto error;
2406c29230eSTakashi Sakamoto 	if (oxfw->has_output) {
2416c29230eSTakashi Sakamoto 		err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream);
2426c29230eSTakashi Sakamoto 		if (err < 0)
2436c29230eSTakashi Sakamoto 			goto error;
2446c29230eSTakashi Sakamoto 	}
2456c29230eSTakashi Sakamoto 
2463713d93aSTakashi Sakamoto 	err = snd_oxfw_create_pcm(oxfw);
2471a4e39c2STakashi Sakamoto 	if (err < 0)
2481a4e39c2STakashi Sakamoto 		goto error;
2491a4e39c2STakashi Sakamoto 
2503c96101fSTakashi Sakamoto 	snd_oxfw_proc_init(oxfw);
2513c96101fSTakashi Sakamoto 
25205588d34STakashi Sakamoto 	err = snd_oxfw_create_midi(oxfw);
25305588d34STakashi Sakamoto 	if (err < 0)
25405588d34STakashi Sakamoto 		goto error;
25505588d34STakashi Sakamoto 
2568985f4acSTakashi Sakamoto 	err = snd_oxfw_create_hwdep(oxfw);
2578985f4acSTakashi Sakamoto 	if (err < 0)
2588985f4acSTakashi Sakamoto 		goto error;
2598985f4acSTakashi Sakamoto 
2606c29230eSTakashi Sakamoto 	err = snd_card_register(oxfw->card);
2611a4e39c2STakashi Sakamoto 	if (err < 0)
2621a4e39c2STakashi Sakamoto 		goto error;
2631a4e39c2STakashi Sakamoto 
2646c29230eSTakashi Sakamoto 	/*
2656c29230eSTakashi Sakamoto 	 * After registered, oxfw instance can be released corresponding to
2666c29230eSTakashi Sakamoto 	 * releasing the sound card instance.
2676c29230eSTakashi Sakamoto 	 */
2686c29230eSTakashi Sakamoto 	oxfw->card->private_free = oxfw_card_free;
2696c29230eSTakashi Sakamoto 	oxfw->card->private_data = oxfw;
2706c29230eSTakashi Sakamoto 	oxfw->registered = true;
2716c29230eSTakashi Sakamoto 
2726c29230eSTakashi Sakamoto 	return;
2736c29230eSTakashi Sakamoto error:
274b0ac0009STakashi Sakamoto 	snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
275b0ac0009STakashi Sakamoto 	if (oxfw->has_output)
276b0ac0009STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
2776c29230eSTakashi Sakamoto 	snd_card_free(oxfw->card);
2786c29230eSTakashi Sakamoto 	dev_info(&oxfw->unit->device,
2796c29230eSTakashi Sakamoto 		 "Sound card registration failed: %d\n", err);
280e2786ca6STakashi Sakamoto }
2816c29230eSTakashi Sakamoto 
2826c29230eSTakashi Sakamoto static int oxfw_probe(struct fw_unit *unit,
2836c29230eSTakashi Sakamoto 		      const struct ieee1394_device_id *entry)
2846c29230eSTakashi Sakamoto {
2856c29230eSTakashi Sakamoto 	struct snd_oxfw *oxfw;
2866c29230eSTakashi Sakamoto 
2876c29230eSTakashi Sakamoto 	if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit))
2886c29230eSTakashi Sakamoto 		return -ENODEV;
2896c29230eSTakashi Sakamoto 
2906c29230eSTakashi Sakamoto 	/* Allocate this independent of sound card instance. */
2916c29230eSTakashi Sakamoto 	oxfw = kzalloc(sizeof(struct snd_oxfw), GFP_KERNEL);
2926c29230eSTakashi Sakamoto 	if (oxfw == NULL)
2936c29230eSTakashi Sakamoto 		return -ENOMEM;
2946c29230eSTakashi Sakamoto 
2956c29230eSTakashi Sakamoto 	oxfw->entry = entry;
2966c29230eSTakashi Sakamoto 	oxfw->unit = fw_unit_get(unit);
2971a4e39c2STakashi Sakamoto 	dev_set_drvdata(&unit->device, oxfw);
2981a4e39c2STakashi Sakamoto 
2996c29230eSTakashi Sakamoto 	mutex_init(&oxfw->mutex);
3006c29230eSTakashi Sakamoto 	spin_lock_init(&oxfw->lock);
3016c29230eSTakashi Sakamoto 	init_waitqueue_head(&oxfw->hwdep_wait);
3026c29230eSTakashi Sakamoto 
3036c29230eSTakashi Sakamoto 	/* Allocate and register this sound card later. */
3046c29230eSTakashi Sakamoto 	INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration);
3056c29230eSTakashi Sakamoto 	snd_fw_schedule_registration(unit, &oxfw->dwork);
3066c29230eSTakashi Sakamoto 
3071a4e39c2STakashi Sakamoto 	return 0;
3081a4e39c2STakashi Sakamoto }
3091a4e39c2STakashi Sakamoto 
3101a4e39c2STakashi Sakamoto static void oxfw_bus_reset(struct fw_unit *unit)
3111a4e39c2STakashi Sakamoto {
3121a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
3131a4e39c2STakashi Sakamoto 
3146c29230eSTakashi Sakamoto 	if (!oxfw->registered)
3156c29230eSTakashi Sakamoto 		snd_fw_schedule_registration(unit, &oxfw->dwork);
3166c29230eSTakashi Sakamoto 
3171a4e39c2STakashi Sakamoto 	fcp_bus_reset(oxfw->unit);
3181a4e39c2STakashi Sakamoto 
3196c29230eSTakashi Sakamoto 	if (oxfw->registered) {
3201a4e39c2STakashi Sakamoto 		mutex_lock(&oxfw->mutex);
321b0ac0009STakashi Sakamoto 
322b0ac0009STakashi Sakamoto 		snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream);
323b0ac0009STakashi Sakamoto 		if (oxfw->has_output)
324b0ac0009STakashi Sakamoto 			snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
325b0ac0009STakashi Sakamoto 
3261a4e39c2STakashi Sakamoto 		mutex_unlock(&oxfw->mutex);
3279e2004f9STakashi Sakamoto 
3289e2004f9STakashi Sakamoto 		if (oxfw->entry->vendor_id == OUI_STANTON)
3299e2004f9STakashi Sakamoto 			snd_oxfw_scs1x_update(oxfw);
3301a4e39c2STakashi Sakamoto 	}
3316c29230eSTakashi Sakamoto }
3321a4e39c2STakashi Sakamoto 
3331a4e39c2STakashi Sakamoto static void oxfw_remove(struct fw_unit *unit)
3341a4e39c2STakashi Sakamoto {
3351a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
3361a4e39c2STakashi Sakamoto 
3376c29230eSTakashi Sakamoto 	/*
3386c29230eSTakashi Sakamoto 	 * Confirm to stop the work for registration before the sound card is
3396c29230eSTakashi Sakamoto 	 * going to be released. The work is not scheduled again because bus
3406c29230eSTakashi Sakamoto 	 * reset handler is not called anymore.
3416c29230eSTakashi Sakamoto 	 */
3426c29230eSTakashi Sakamoto 	cancel_delayed_work_sync(&oxfw->dwork);
3436c29230eSTakashi Sakamoto 
3446c29230eSTakashi Sakamoto 	if (oxfw->registered) {
34512ed7192STakashi Sakamoto 		/* No need to wait for releasing card object in this context. */
3461a4e39c2STakashi Sakamoto 		snd_card_free_when_closed(oxfw->card);
3476c29230eSTakashi Sakamoto 	} else {
3486c29230eSTakashi Sakamoto 		/* Don't forget this case. */
3496c29230eSTakashi Sakamoto 		oxfw_free(oxfw);
3506c29230eSTakashi Sakamoto 	}
3511a4e39c2STakashi Sakamoto }
3521a4e39c2STakashi Sakamoto 
353d6ce6bbdSTakashi Sakamoto static const struct compat_info griffin_firewave = {
3541a4e39c2STakashi Sakamoto 	.driver_name = "FireWave",
355fec7b753STakashi Sakamoto 	.vendor_name = "Griffin",
356fec7b753STakashi Sakamoto 	.model_name = "FireWave",
3571a4e39c2STakashi Sakamoto };
3581a4e39c2STakashi Sakamoto 
359d6ce6bbdSTakashi Sakamoto static const struct compat_info lacie_speakers = {
3601a4e39c2STakashi Sakamoto 	.driver_name = "FWSpeakers",
361fec7b753STakashi Sakamoto 	.vendor_name = "LaCie",
362fec7b753STakashi Sakamoto 	.model_name = "FireWire Speakers",
3631a4e39c2STakashi Sakamoto };
3641a4e39c2STakashi Sakamoto 
3651a4e39c2STakashi Sakamoto static const struct ieee1394_device_id oxfw_id_table[] = {
3661a4e39c2STakashi Sakamoto 	{
3671a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
3681a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
3691a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
3701a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
3711a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_GRIFFIN,
3721a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
3731a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
3741a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
3751a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&griffin_firewave,
3761a4e39c2STakashi Sakamoto 	},
3771a4e39c2STakashi Sakamoto 	{
3781a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
3791a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
3801a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
3811a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
3821a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_LACIE,
3831a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
3841a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
3851a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
3861a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&lacie_speakers,
3871a4e39c2STakashi Sakamoto 	},
388ec4dba50STakashi Sakamoto 	/* Behringer,F-Control Audio 202 */
389ec4dba50STakashi Sakamoto 	{
390ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
391ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
392ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_BEHRINGER,
393ec4dba50STakashi Sakamoto 		.model_id	= 0x00fc22,
394ec4dba50STakashi Sakamoto 	},
395ec4dba50STakashi Sakamoto 	/*
396ec4dba50STakashi Sakamoto 	 * Any Mackie(Loud) models (name string/model id):
397ec4dba50STakashi Sakamoto 	 *  Onyx-i series (former models):	0x081216
398ec4dba50STakashi Sakamoto 	 *  Mackie Onyx Satellite:		0x00200f
399ec4dba50STakashi Sakamoto 	 *  Tapco LINK.firewire 4x6:		0x000460
400ec4dba50STakashi Sakamoto 	 *  d.2 pro:				Unknown
401ec4dba50STakashi Sakamoto 	 *  d.4 pro:				Unknown
402ec4dba50STakashi Sakamoto 	 *  U.420:				Unknown
403ec4dba50STakashi Sakamoto 	 *  U.420d:				Unknown
404ec4dba50STakashi Sakamoto 	 */
405ec4dba50STakashi Sakamoto 	{
406ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
407ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_SPECIFIER_ID |
408ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_VERSION,
409ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_LOUD,
410ec4dba50STakashi Sakamoto 		.specifier_id	= SPECIFIER_1394TA,
411ec4dba50STakashi Sakamoto 		.version	= VERSION_AVC,
412ec4dba50STakashi Sakamoto 	},
413759a2f40STakashi Sakamoto 	/* TASCAM, FireOne */
414759a2f40STakashi Sakamoto 	{
415759a2f40STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
416759a2f40STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
417759a2f40STakashi Sakamoto 		.vendor_id	= VENDOR_TASCAM,
418759a2f40STakashi Sakamoto 		.model_id	= 0x800007,
419759a2f40STakashi Sakamoto 	},
4209e2004f9STakashi Sakamoto 	/* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */
4219e2004f9STakashi Sakamoto 	{
4229e2004f9STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
4239e2004f9STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
4249e2004f9STakashi Sakamoto 		.vendor_id	= OUI_STANTON,
4259e2004f9STakashi Sakamoto 		.model_id	= 0x001000,
4269e2004f9STakashi Sakamoto 	},
4279e2004f9STakashi Sakamoto 	/* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */
4289e2004f9STakashi Sakamoto 	{
4299e2004f9STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
4309e2004f9STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
4319e2004f9STakashi Sakamoto 		.vendor_id	= OUI_STANTON,
4329e2004f9STakashi Sakamoto 		.model_id	= 0x002000,
4339e2004f9STakashi Sakamoto 	},
4341a4e39c2STakashi Sakamoto 	{ }
4351a4e39c2STakashi Sakamoto };
4361a4e39c2STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
4371a4e39c2STakashi Sakamoto 
4381a4e39c2STakashi Sakamoto static struct fw_driver oxfw_driver = {
4391a4e39c2STakashi Sakamoto 	.driver   = {
4401a4e39c2STakashi Sakamoto 		.owner	= THIS_MODULE,
4411a4e39c2STakashi Sakamoto 		.name	= KBUILD_MODNAME,
4421a4e39c2STakashi Sakamoto 		.bus	= &fw_bus_type,
4431a4e39c2STakashi Sakamoto 	},
4441a4e39c2STakashi Sakamoto 	.probe    = oxfw_probe,
4451a4e39c2STakashi Sakamoto 	.update   = oxfw_bus_reset,
4461a4e39c2STakashi Sakamoto 	.remove   = oxfw_remove,
4471a4e39c2STakashi Sakamoto 	.id_table = oxfw_id_table,
4481a4e39c2STakashi Sakamoto };
4491a4e39c2STakashi Sakamoto 
4501a4e39c2STakashi Sakamoto static int __init snd_oxfw_init(void)
4511a4e39c2STakashi Sakamoto {
4521a4e39c2STakashi Sakamoto 	return driver_register(&oxfw_driver.driver);
4531a4e39c2STakashi Sakamoto }
4541a4e39c2STakashi Sakamoto 
4551a4e39c2STakashi Sakamoto static void __exit snd_oxfw_exit(void)
4561a4e39c2STakashi Sakamoto {
4571a4e39c2STakashi Sakamoto 	driver_unregister(&oxfw_driver.driver);
4581a4e39c2STakashi Sakamoto }
4591a4e39c2STakashi Sakamoto 
4601a4e39c2STakashi Sakamoto module_init(snd_oxfw_init);
4611a4e39c2STakashi Sakamoto module_exit(snd_oxfw_exit);
462