xref: /openbmc/linux/sound/firewire/oxfw/oxfw.c (revision 759a2f40)
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
221a4e39c2STakashi Sakamoto 
2313f3a46dSTakashi Sakamoto #define MODEL_SATELLITE		0x00200f
2413f3a46dSTakashi Sakamoto 
251a4e39c2STakashi Sakamoto #define SPECIFIER_1394TA	0x00a02d
261a4e39c2STakashi Sakamoto #define VERSION_AVC		0x010001
271a4e39c2STakashi Sakamoto 
281a4e39c2STakashi Sakamoto MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
291a4e39c2STakashi Sakamoto MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
301a4e39c2STakashi Sakamoto MODULE_LICENSE("GPL v2");
311a4e39c2STakashi Sakamoto MODULE_ALIAS("snd-firewire-speakers");
321a4e39c2STakashi Sakamoto 
33ec4dba50STakashi Sakamoto static bool detect_loud_models(struct fw_unit *unit)
34ec4dba50STakashi Sakamoto {
35ec4dba50STakashi Sakamoto 	const char *const models[] = {
36ec4dba50STakashi Sakamoto 		"Onyxi",
37ec4dba50STakashi Sakamoto 		"Onyx-i",
38ec4dba50STakashi Sakamoto 		"d.Pro",
39ec4dba50STakashi Sakamoto 		"Mackie Onyx Satellite",
40ec4dba50STakashi Sakamoto 		"Tapco LINK.firewire 4x6",
41ec4dba50STakashi Sakamoto 		"U.420"};
42ec4dba50STakashi Sakamoto 	char model[32];
43ec4dba50STakashi Sakamoto 	unsigned int i;
44ec4dba50STakashi Sakamoto 	int err;
45ec4dba50STakashi Sakamoto 
46ec4dba50STakashi Sakamoto 	err = fw_csr_string(unit->directory, CSR_MODEL,
47ec4dba50STakashi Sakamoto 			    model, sizeof(model));
48ec4dba50STakashi Sakamoto 	if (err < 0)
490d3aba30SDan Carpenter 		return false;
50ec4dba50STakashi Sakamoto 
51ec4dba50STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(models); i++) {
52ec4dba50STakashi Sakamoto 		if (strcmp(models[i], model) == 0)
53ec4dba50STakashi Sakamoto 			break;
54ec4dba50STakashi Sakamoto 	}
55ec4dba50STakashi Sakamoto 
56ec4dba50STakashi Sakamoto 	return (i < ARRAY_SIZE(models));
57ec4dba50STakashi Sakamoto }
58ec4dba50STakashi Sakamoto 
59fec7b753STakashi Sakamoto static int name_card(struct snd_oxfw *oxfw)
601a4e39c2STakashi Sakamoto {
61fec7b753STakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
62ec4dba50STakashi Sakamoto 	char vendor[24];
63ec4dba50STakashi Sakamoto 	char model[32];
64fec7b753STakashi Sakamoto 	const char *d, *v, *m;
65fec7b753STakashi Sakamoto 	u32 firmware;
661a4e39c2STakashi Sakamoto 	int err;
671a4e39c2STakashi Sakamoto 
68ec4dba50STakashi Sakamoto 	/* get vendor name from root directory */
69ec4dba50STakashi Sakamoto 	err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR,
70ec4dba50STakashi Sakamoto 			    vendor, sizeof(vendor));
71ec4dba50STakashi Sakamoto 	if (err < 0)
72ec4dba50STakashi Sakamoto 		goto end;
73ec4dba50STakashi Sakamoto 
74ec4dba50STakashi Sakamoto 	/* get model name from unit directory */
75ec4dba50STakashi Sakamoto 	err = fw_csr_string(oxfw->unit->directory, CSR_MODEL,
76ec4dba50STakashi Sakamoto 			    model, sizeof(model));
77ec4dba50STakashi Sakamoto 	if (err < 0)
78ec4dba50STakashi Sakamoto 		goto end;
79ec4dba50STakashi Sakamoto 
80fec7b753STakashi Sakamoto 	err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST,
81fec7b753STakashi Sakamoto 				 OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0);
82fec7b753STakashi Sakamoto 	if (err < 0)
83fec7b753STakashi Sakamoto 		goto end;
84fec7b753STakashi Sakamoto 	be32_to_cpus(&firmware);
85fec7b753STakashi Sakamoto 
86ec4dba50STakashi Sakamoto 	/* to apply card definitions */
87ec4dba50STakashi Sakamoto 	if (oxfw->device_info) {
88fec7b753STakashi Sakamoto 		d = oxfw->device_info->driver_name;
89fec7b753STakashi Sakamoto 		v = oxfw->device_info->vendor_name;
90fec7b753STakashi Sakamoto 		m = oxfw->device_info->model_name;
91ec4dba50STakashi Sakamoto 	} else {
92ec4dba50STakashi Sakamoto 		d = "OXFW";
93ec4dba50STakashi Sakamoto 		v = vendor;
94ec4dba50STakashi Sakamoto 		m = model;
95ec4dba50STakashi Sakamoto 	}
96fec7b753STakashi Sakamoto 
97fec7b753STakashi Sakamoto 	strcpy(oxfw->card->driver, d);
98fec7b753STakashi Sakamoto 	strcpy(oxfw->card->mixername, m);
99fec7b753STakashi Sakamoto 	strcpy(oxfw->card->shortname, m);
100fec7b753STakashi Sakamoto 
101fec7b753STakashi Sakamoto 	snprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
102fec7b753STakashi Sakamoto 		 "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
103fec7b753STakashi Sakamoto 		 v, m, firmware >> 20, firmware & 0xffff,
104fec7b753STakashi Sakamoto 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
105fec7b753STakashi Sakamoto 		 dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
106fec7b753STakashi Sakamoto end:
107fec7b753STakashi Sakamoto 	return err;
1081a4e39c2STakashi Sakamoto }
1091a4e39c2STakashi Sakamoto 
11012ed7192STakashi Sakamoto /*
11112ed7192STakashi Sakamoto  * This module releases the FireWire unit data after all ALSA character devices
11212ed7192STakashi Sakamoto  * are released by applications. This is for releasing stream data or finishing
11312ed7192STakashi Sakamoto  * transactions safely. Thus at returning from .remove(), this module still keep
11412ed7192STakashi Sakamoto  * references for the unit.
11512ed7192STakashi Sakamoto  */
1161a4e39c2STakashi Sakamoto static void oxfw_card_free(struct snd_card *card)
1171a4e39c2STakashi Sakamoto {
1181a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = card->private_data;
1195cd1d3f4STakashi Sakamoto 	unsigned int i;
1205cd1d3f4STakashi Sakamoto 
121dec84316STakashi Sakamoto 	snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
122dec84316STakashi Sakamoto 	if (oxfw->has_output)
123dec84316STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
124dec84316STakashi Sakamoto 
12512ed7192STakashi Sakamoto 	fw_unit_put(oxfw->unit);
12612ed7192STakashi Sakamoto 
127b0ac0009STakashi Sakamoto 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
128b0ac0009STakashi Sakamoto 		kfree(oxfw->tx_stream_formats[i]);
1295cd1d3f4STakashi Sakamoto 		kfree(oxfw->rx_stream_formats[i]);
130b0ac0009STakashi Sakamoto 	}
1311a4e39c2STakashi Sakamoto 
1321a4e39c2STakashi Sakamoto 	mutex_destroy(&oxfw->mutex);
1331a4e39c2STakashi Sakamoto }
1341a4e39c2STakashi Sakamoto 
13513f3a46dSTakashi Sakamoto static void detect_quirks(struct snd_oxfw *oxfw)
13613f3a46dSTakashi Sakamoto {
13713f3a46dSTakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
13813f3a46dSTakashi Sakamoto 	struct fw_csr_iterator it;
13913f3a46dSTakashi Sakamoto 	int key, val;
14013f3a46dSTakashi Sakamoto 	int vendor, model;
14113f3a46dSTakashi Sakamoto 
14213f3a46dSTakashi Sakamoto 	/* Seek from Root Directory of Config ROM. */
14313f3a46dSTakashi Sakamoto 	vendor = model = 0;
14413f3a46dSTakashi Sakamoto 	fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
14513f3a46dSTakashi Sakamoto 	while (fw_csr_iterator_next(&it, &key, &val)) {
14613f3a46dSTakashi Sakamoto 		if (key == CSR_VENDOR)
14713f3a46dSTakashi Sakamoto 			vendor = val;
14813f3a46dSTakashi Sakamoto 		else if (key == CSR_MODEL)
14913f3a46dSTakashi Sakamoto 			model = val;
15013f3a46dSTakashi Sakamoto 	}
15113f3a46dSTakashi Sakamoto 
15213f3a46dSTakashi Sakamoto 	/*
15313f3a46dSTakashi Sakamoto 	 * Mackie Onyx Satellite with base station has a quirk to report a wrong
15413f3a46dSTakashi Sakamoto 	 * value in 'dbs' field of CIP header against its format information.
15513f3a46dSTakashi Sakamoto 	 */
15613f3a46dSTakashi Sakamoto 	if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
15713f3a46dSTakashi Sakamoto 		oxfw->wrong_dbs = true;
158759a2f40STakashi Sakamoto 
159759a2f40STakashi Sakamoto 	/*
160759a2f40STakashi Sakamoto 	 * TASCAM FireOne has physical control and requires a pair of additional
161759a2f40STakashi Sakamoto 	 * MIDI ports.
162759a2f40STakashi Sakamoto 	 */
163759a2f40STakashi Sakamoto 	if (vendor == VENDOR_TASCAM) {
164759a2f40STakashi Sakamoto 		oxfw->midi_input_ports++;
165759a2f40STakashi Sakamoto 		oxfw->midi_output_ports++;
166759a2f40STakashi Sakamoto 	}
16713f3a46dSTakashi Sakamoto }
16813f3a46dSTakashi Sakamoto 
1691a4e39c2STakashi Sakamoto static int oxfw_probe(struct fw_unit *unit,
1701a4e39c2STakashi Sakamoto 		       const struct ieee1394_device_id *id)
1711a4e39c2STakashi Sakamoto {
1721a4e39c2STakashi Sakamoto 	struct snd_card *card;
1731a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw;
1741a4e39c2STakashi Sakamoto 	int err;
1751a4e39c2STakashi Sakamoto 
176ec4dba50STakashi Sakamoto 	if ((id->vendor_id == VENDOR_LOUD) && !detect_loud_models(unit))
177ec4dba50STakashi Sakamoto 		return -ENODEV;
178ec4dba50STakashi Sakamoto 
1791a4e39c2STakashi Sakamoto 	err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
1801a4e39c2STakashi Sakamoto 			   sizeof(*oxfw), &card);
1811a4e39c2STakashi Sakamoto 	if (err < 0)
1821a4e39c2STakashi Sakamoto 		return err;
1831a4e39c2STakashi Sakamoto 
184e2786ca6STakashi Sakamoto 	card->private_free = oxfw_card_free;
1851a4e39c2STakashi Sakamoto 	oxfw = card->private_data;
1861a4e39c2STakashi Sakamoto 	oxfw->card = card;
1871a4e39c2STakashi Sakamoto 	mutex_init(&oxfw->mutex);
18812ed7192STakashi Sakamoto 	oxfw->unit = fw_unit_get(unit);
1891a4e39c2STakashi Sakamoto 	oxfw->device_info = (const struct device_info *)id->driver_data;
19005588d34STakashi Sakamoto 	spin_lock_init(&oxfw->lock);
1918985f4acSTakashi Sakamoto 	init_waitqueue_head(&oxfw->hwdep_wait);
1921a4e39c2STakashi Sakamoto 
1935cd1d3f4STakashi Sakamoto 	err = snd_oxfw_stream_discover(oxfw);
1945cd1d3f4STakashi Sakamoto 	if (err < 0)
1955cd1d3f4STakashi Sakamoto 		goto error;
1965cd1d3f4STakashi Sakamoto 
19713f3a46dSTakashi Sakamoto 	detect_quirks(oxfw);
19813f3a46dSTakashi Sakamoto 
199fec7b753STakashi Sakamoto 	err = name_card(oxfw);
200fec7b753STakashi Sakamoto 	if (err < 0)
201fec7b753STakashi Sakamoto 		goto error;
2021a4e39c2STakashi Sakamoto 
2033713d93aSTakashi Sakamoto 	err = snd_oxfw_create_pcm(oxfw);
2041a4e39c2STakashi Sakamoto 	if (err < 0)
2051a4e39c2STakashi Sakamoto 		goto error;
2061a4e39c2STakashi Sakamoto 
207ec4dba50STakashi Sakamoto 	if (oxfw->device_info) {
20831514bfbSTakashi Sakamoto 		err = snd_oxfw_create_mixer(oxfw);
2091a4e39c2STakashi Sakamoto 		if (err < 0)
2101a4e39c2STakashi Sakamoto 			goto error;
211ec4dba50STakashi Sakamoto 	}
2121a4e39c2STakashi Sakamoto 
2133c96101fSTakashi Sakamoto 	snd_oxfw_proc_init(oxfw);
2143c96101fSTakashi Sakamoto 
21505588d34STakashi Sakamoto 	err = snd_oxfw_create_midi(oxfw);
21605588d34STakashi Sakamoto 	if (err < 0)
21705588d34STakashi Sakamoto 		goto error;
21805588d34STakashi Sakamoto 
2198985f4acSTakashi Sakamoto 	err = snd_oxfw_create_hwdep(oxfw);
2208985f4acSTakashi Sakamoto 	if (err < 0)
2218985f4acSTakashi Sakamoto 		goto error;
2228985f4acSTakashi Sakamoto 
223b0ac0009STakashi Sakamoto 	err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream);
2241a4e39c2STakashi Sakamoto 	if (err < 0)
2251a4e39c2STakashi Sakamoto 		goto error;
226b0ac0009STakashi Sakamoto 	if (oxfw->has_output) {
227b0ac0009STakashi Sakamoto 		err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream);
228b0ac0009STakashi Sakamoto 		if (err < 0)
229b0ac0009STakashi Sakamoto 			goto error;
230b0ac0009STakashi Sakamoto 	}
2311a4e39c2STakashi Sakamoto 
232e2786ca6STakashi Sakamoto 	err = snd_card_register(card);
233e2786ca6STakashi Sakamoto 	if (err < 0) {
234b0ac0009STakashi Sakamoto 		snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
235b0ac0009STakashi Sakamoto 		if (oxfw->has_output)
236b0ac0009STakashi Sakamoto 			snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
237e2786ca6STakashi Sakamoto 		goto error;
238e2786ca6STakashi Sakamoto 	}
2391a4e39c2STakashi Sakamoto 	dev_set_drvdata(&unit->device, oxfw);
2401a4e39c2STakashi Sakamoto 
2411a4e39c2STakashi Sakamoto 	return 0;
2421a4e39c2STakashi Sakamoto error:
2431a4e39c2STakashi Sakamoto 	snd_card_free(card);
2441a4e39c2STakashi Sakamoto 	return err;
2451a4e39c2STakashi Sakamoto }
2461a4e39c2STakashi Sakamoto 
2471a4e39c2STakashi Sakamoto static void oxfw_bus_reset(struct fw_unit *unit)
2481a4e39c2STakashi Sakamoto {
2491a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
2501a4e39c2STakashi Sakamoto 
2511a4e39c2STakashi Sakamoto 	fcp_bus_reset(oxfw->unit);
2521a4e39c2STakashi Sakamoto 
2531a4e39c2STakashi Sakamoto 	mutex_lock(&oxfw->mutex);
254b0ac0009STakashi Sakamoto 
255b0ac0009STakashi Sakamoto 	snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream);
256b0ac0009STakashi Sakamoto 	if (oxfw->has_output)
257b0ac0009STakashi Sakamoto 		snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
258b0ac0009STakashi Sakamoto 
2591a4e39c2STakashi Sakamoto 	mutex_unlock(&oxfw->mutex);
2601a4e39c2STakashi Sakamoto }
2611a4e39c2STakashi Sakamoto 
2621a4e39c2STakashi Sakamoto static void oxfw_remove(struct fw_unit *unit)
2631a4e39c2STakashi Sakamoto {
2641a4e39c2STakashi Sakamoto 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
2651a4e39c2STakashi Sakamoto 
26612ed7192STakashi Sakamoto 	/* No need to wait for releasing card object in this context. */
2671a4e39c2STakashi Sakamoto 	snd_card_free_when_closed(oxfw->card);
2681a4e39c2STakashi Sakamoto }
2691a4e39c2STakashi Sakamoto 
2701a4e39c2STakashi Sakamoto static const struct device_info griffin_firewave = {
2711a4e39c2STakashi Sakamoto 	.driver_name = "FireWave",
272fec7b753STakashi Sakamoto 	.vendor_name = "Griffin",
273fec7b753STakashi Sakamoto 	.model_name = "FireWave",
2741a4e39c2STakashi Sakamoto 	.mixer_channels = 6,
2751a4e39c2STakashi Sakamoto 	.mute_fb_id   = 0x01,
2761a4e39c2STakashi Sakamoto 	.volume_fb_id = 0x02,
2771a4e39c2STakashi Sakamoto };
2781a4e39c2STakashi Sakamoto 
2791a4e39c2STakashi Sakamoto static const struct device_info lacie_speakers = {
2801a4e39c2STakashi Sakamoto 	.driver_name = "FWSpeakers",
281fec7b753STakashi Sakamoto 	.vendor_name = "LaCie",
282fec7b753STakashi Sakamoto 	.model_name = "FireWire Speakers",
2831a4e39c2STakashi Sakamoto 	.mixer_channels = 1,
2841a4e39c2STakashi Sakamoto 	.mute_fb_id   = 0x01,
2851a4e39c2STakashi Sakamoto 	.volume_fb_id = 0x01,
2861a4e39c2STakashi Sakamoto };
2871a4e39c2STakashi Sakamoto 
2881a4e39c2STakashi Sakamoto static const struct ieee1394_device_id oxfw_id_table[] = {
2891a4e39c2STakashi Sakamoto 	{
2901a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
2911a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
2921a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
2931a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
2941a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_GRIFFIN,
2951a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
2961a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
2971a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
2981a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&griffin_firewave,
2991a4e39c2STakashi Sakamoto 	},
3001a4e39c2STakashi Sakamoto 	{
3011a4e39c2STakashi Sakamoto 		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
3021a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_MODEL_ID |
3031a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_SPECIFIER_ID |
3041a4e39c2STakashi Sakamoto 				IEEE1394_MATCH_VERSION,
3051a4e39c2STakashi Sakamoto 		.vendor_id    = VENDOR_LACIE,
3061a4e39c2STakashi Sakamoto 		.model_id     = 0x00f970,
3071a4e39c2STakashi Sakamoto 		.specifier_id = SPECIFIER_1394TA,
3081a4e39c2STakashi Sakamoto 		.version      = VERSION_AVC,
3091a4e39c2STakashi Sakamoto 		.driver_data  = (kernel_ulong_t)&lacie_speakers,
3101a4e39c2STakashi Sakamoto 	},
311ec4dba50STakashi Sakamoto 	/* Behringer,F-Control Audio 202 */
312ec4dba50STakashi Sakamoto 	{
313ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
314ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
315ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_BEHRINGER,
316ec4dba50STakashi Sakamoto 		.model_id	= 0x00fc22,
317ec4dba50STakashi Sakamoto 	},
318ec4dba50STakashi Sakamoto 	/*
319ec4dba50STakashi Sakamoto 	 * Any Mackie(Loud) models (name string/model id):
320ec4dba50STakashi Sakamoto 	 *  Onyx-i series (former models):	0x081216
321ec4dba50STakashi Sakamoto 	 *  Mackie Onyx Satellite:		0x00200f
322ec4dba50STakashi Sakamoto 	 *  Tapco LINK.firewire 4x6:		0x000460
323ec4dba50STakashi Sakamoto 	 *  d.2 pro:				Unknown
324ec4dba50STakashi Sakamoto 	 *  d.4 pro:				Unknown
325ec4dba50STakashi Sakamoto 	 *  U.420:				Unknown
326ec4dba50STakashi Sakamoto 	 *  U.420d:				Unknown
327ec4dba50STakashi Sakamoto 	 */
328ec4dba50STakashi Sakamoto 	{
329ec4dba50STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
330ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_SPECIFIER_ID |
331ec4dba50STakashi Sakamoto 				  IEEE1394_MATCH_VERSION,
332ec4dba50STakashi Sakamoto 		.vendor_id	= VENDOR_LOUD,
333ec4dba50STakashi Sakamoto 		.specifier_id	= SPECIFIER_1394TA,
334ec4dba50STakashi Sakamoto 		.version	= VERSION_AVC,
335ec4dba50STakashi Sakamoto 	},
336759a2f40STakashi Sakamoto 	/* TASCAM, FireOne */
337759a2f40STakashi Sakamoto 	{
338759a2f40STakashi Sakamoto 		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
339759a2f40STakashi Sakamoto 				  IEEE1394_MATCH_MODEL_ID,
340759a2f40STakashi Sakamoto 		.vendor_id	= VENDOR_TASCAM,
341759a2f40STakashi Sakamoto 		.model_id	= 0x800007,
342759a2f40STakashi Sakamoto 	},
3431a4e39c2STakashi Sakamoto 	{ }
3441a4e39c2STakashi Sakamoto };
3451a4e39c2STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
3461a4e39c2STakashi Sakamoto 
3471a4e39c2STakashi Sakamoto static struct fw_driver oxfw_driver = {
3481a4e39c2STakashi Sakamoto 	.driver   = {
3491a4e39c2STakashi Sakamoto 		.owner	= THIS_MODULE,
3501a4e39c2STakashi Sakamoto 		.name	= KBUILD_MODNAME,
3511a4e39c2STakashi Sakamoto 		.bus	= &fw_bus_type,
3521a4e39c2STakashi Sakamoto 	},
3531a4e39c2STakashi Sakamoto 	.probe    = oxfw_probe,
3541a4e39c2STakashi Sakamoto 	.update   = oxfw_bus_reset,
3551a4e39c2STakashi Sakamoto 	.remove   = oxfw_remove,
3561a4e39c2STakashi Sakamoto 	.id_table = oxfw_id_table,
3571a4e39c2STakashi Sakamoto };
3581a4e39c2STakashi Sakamoto 
3591a4e39c2STakashi Sakamoto static int __init snd_oxfw_init(void)
3601a4e39c2STakashi Sakamoto {
3611a4e39c2STakashi Sakamoto 	return driver_register(&oxfw_driver.driver);
3621a4e39c2STakashi Sakamoto }
3631a4e39c2STakashi Sakamoto 
3641a4e39c2STakashi Sakamoto static void __exit snd_oxfw_exit(void)
3651a4e39c2STakashi Sakamoto {
3661a4e39c2STakashi Sakamoto 	driver_unregister(&oxfw_driver.driver);
3671a4e39c2STakashi Sakamoto }
3681a4e39c2STakashi Sakamoto 
3691a4e39c2STakashi Sakamoto module_init(snd_oxfw_init);
3701a4e39c2STakashi Sakamoto module_exit(snd_oxfw_exit);
371