1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21a4e39c2STakashi Sakamoto /*
31a4e39c2STakashi Sakamoto * oxfw.c - a part of driver for OXFW970/971 based devices
41a4e39c2STakashi Sakamoto *
51a4e39c2STakashi Sakamoto * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
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
23fba43f45STakashi Sakamoto #define OUI_APOGEE 0x0003db
241a4e39c2STakashi Sakamoto
2513f3a46dSTakashi Sakamoto #define MODEL_SATELLITE 0x00200f
2607a35edcSTakashi Sakamoto #define MODEL_SCS1M 0x001000
2707a35edcSTakashi Sakamoto #define MODEL_DUET_FW 0x01dddd
28cddcd547STakashi Sakamoto #define MODEL_ONYX_1640I 0x001640
2913f3a46dSTakashi Sakamoto
301a4e39c2STakashi Sakamoto #define SPECIFIER_1394TA 0x00a02d
311a4e39c2STakashi Sakamoto #define VERSION_AVC 0x010001
321a4e39c2STakashi Sakamoto
331a4e39c2STakashi Sakamoto MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
341a4e39c2STakashi Sakamoto MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
359b446941STakashi Sakamoto MODULE_LICENSE("GPL");
361a4e39c2STakashi Sakamoto MODULE_ALIAS("snd-firewire-speakers");
379e2004f9STakashi Sakamoto MODULE_ALIAS("snd-scs1x");
381a4e39c2STakashi Sakamoto
39d6ce6bbdSTakashi Sakamoto struct compat_info {
40d6ce6bbdSTakashi Sakamoto const char *driver_name;
41d6ce6bbdSTakashi Sakamoto const char *vendor_name;
42d6ce6bbdSTakashi Sakamoto const char *model_name;
43d6ce6bbdSTakashi Sakamoto };
44d6ce6bbdSTakashi Sakamoto
detect_loud_models(struct fw_unit * unit)45ec4dba50STakashi Sakamoto static bool detect_loud_models(struct fw_unit *unit)
46ec4dba50STakashi Sakamoto {
47d17f0ce9SColin Ian King static const char *const models[] = {
48ec4dba50STakashi Sakamoto "Onyxi",
49ec4dba50STakashi Sakamoto "Onyx-i",
5003abd33aSTakashi Sakamoto "Onyx 1640i",
51ec4dba50STakashi Sakamoto "d.Pro",
52ec4dba50STakashi Sakamoto "U.420"};
53ec4dba50STakashi Sakamoto char model[32];
54ec4dba50STakashi Sakamoto int err;
55ec4dba50STakashi Sakamoto
56ec4dba50STakashi Sakamoto err = fw_csr_string(unit->directory, CSR_MODEL,
57ec4dba50STakashi Sakamoto model, sizeof(model));
58ec4dba50STakashi Sakamoto if (err < 0)
590d3aba30SDan Carpenter return false;
60ec4dba50STakashi Sakamoto
612cc47d31SYisheng Xie return match_string(models, ARRAY_SIZE(models), model) >= 0;
62ec4dba50STakashi Sakamoto }
63ec4dba50STakashi Sakamoto
name_card(struct snd_oxfw * oxfw,const struct ieee1394_device_id * entry)64b566e972STakashi Sakamoto static int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry)
651a4e39c2STakashi Sakamoto {
66fec7b753STakashi Sakamoto struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
67d6ce6bbdSTakashi Sakamoto const struct compat_info *info;
68ec4dba50STakashi Sakamoto char vendor[24];
69ec4dba50STakashi Sakamoto char model[32];
70fec7b753STakashi Sakamoto const char *d, *v, *m;
71fec7b753STakashi Sakamoto u32 firmware;
721a4e39c2STakashi Sakamoto int err;
731a4e39c2STakashi Sakamoto
74ec4dba50STakashi Sakamoto /* get vendor name from root directory */
75ec4dba50STakashi Sakamoto err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR,
76ec4dba50STakashi Sakamoto vendor, sizeof(vendor));
77ec4dba50STakashi Sakamoto if (err < 0)
78ec4dba50STakashi Sakamoto goto end;
79ec4dba50STakashi Sakamoto
80ec4dba50STakashi Sakamoto /* get model name from unit directory */
81ec4dba50STakashi Sakamoto err = fw_csr_string(oxfw->unit->directory, CSR_MODEL,
82ec4dba50STakashi Sakamoto model, sizeof(model));
83ec4dba50STakashi Sakamoto if (err < 0)
84ec4dba50STakashi Sakamoto goto end;
85ec4dba50STakashi Sakamoto
86fec7b753STakashi Sakamoto err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST,
87fec7b753STakashi Sakamoto OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0);
88fec7b753STakashi Sakamoto if (err < 0)
89fec7b753STakashi Sakamoto goto end;
90fec7b753STakashi Sakamoto be32_to_cpus(&firmware);
91fec7b753STakashi Sakamoto
92a092f000STakashi Sakamoto if (firmware >> 20 == 0x970)
93a092f000STakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_JUMBO_PAYLOAD;
94a092f000STakashi Sakamoto
95ec4dba50STakashi Sakamoto /* to apply card definitions */
96b566e972STakashi Sakamoto if (entry->vendor_id == VENDOR_GRIFFIN || entry->vendor_id == VENDOR_LACIE) {
97b566e972STakashi Sakamoto info = (const struct compat_info *)entry->driver_data;
9827e66635STakashi Sakamoto d = info->driver_name;
9927e66635STakashi Sakamoto v = info->vendor_name;
10027e66635STakashi Sakamoto m = info->model_name;
101ec4dba50STakashi Sakamoto } else {
102ec4dba50STakashi Sakamoto d = "OXFW";
103ec4dba50STakashi Sakamoto v = vendor;
104ec4dba50STakashi Sakamoto m = model;
105ec4dba50STakashi Sakamoto }
106fec7b753STakashi Sakamoto
107fec7b753STakashi Sakamoto strcpy(oxfw->card->driver, d);
108fec7b753STakashi Sakamoto strcpy(oxfw->card->mixername, m);
109fec7b753STakashi Sakamoto strcpy(oxfw->card->shortname, m);
110fec7b753STakashi Sakamoto
111*641e9691STakashi Iwai scnprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
112fec7b753STakashi Sakamoto "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
113fec7b753STakashi Sakamoto v, m, firmware >> 20, firmware & 0xffff,
114fec7b753STakashi Sakamoto fw_dev->config_rom[3], fw_dev->config_rom[4],
115fec7b753STakashi Sakamoto dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
116fec7b753STakashi Sakamoto end:
117fec7b753STakashi Sakamoto return err;
1181a4e39c2STakashi Sakamoto }
1191a4e39c2STakashi Sakamoto
oxfw_card_free(struct snd_card * card)1203babca45STakashi Sakamoto static void oxfw_card_free(struct snd_card *card)
1211a4e39c2STakashi Sakamoto {
1223babca45STakashi Sakamoto struct snd_oxfw *oxfw = card->private_data;
1233babca45STakashi Sakamoto
12406a42a74STakashi Sakamoto if (oxfw->has_output || oxfw->has_input)
125779f0dbaSTakashi Sakamoto snd_oxfw_stream_destroy_duplex(oxfw);
126b566e972STakashi Sakamoto
127b566e972STakashi Sakamoto mutex_destroy(&oxfw->mutex);
128b566e972STakashi Sakamoto fw_unit_put(oxfw->unit);
1291a4e39c2STakashi Sakamoto }
1301a4e39c2STakashi Sakamoto
detect_quirks(struct snd_oxfw * oxfw,const struct ieee1394_device_id * entry)131b566e972STakashi Sakamoto static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry)
13213f3a46dSTakashi Sakamoto {
13313f3a46dSTakashi Sakamoto struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
13413f3a46dSTakashi Sakamoto struct fw_csr_iterator it;
13513f3a46dSTakashi Sakamoto int key, val;
13613f3a46dSTakashi Sakamoto int vendor, model;
13713f3a46dSTakashi Sakamoto
13827e66635STakashi Sakamoto /*
1395ce8cc48STakashi Sakamoto * Add ALSA control elements for two models to keep compatibility to
1405ce8cc48STakashi Sakamoto * old firewire-speaker module.
1415ce8cc48STakashi Sakamoto */
142b566e972STakashi Sakamoto if (entry->vendor_id == VENDOR_GRIFFIN)
1433e2f4570STakashi Sakamoto return snd_oxfw_add_spkr(oxfw, false);
144b566e972STakashi Sakamoto if (entry->vendor_id == VENDOR_LACIE)
1453e2f4570STakashi Sakamoto return snd_oxfw_add_spkr(oxfw, true);
1465ce8cc48STakashi Sakamoto
1475ce8cc48STakashi Sakamoto /*
1489e2004f9STakashi Sakamoto * Stanton models supports asynchronous transactions for unique MIDI
1499e2004f9STakashi Sakamoto * messages.
1509e2004f9STakashi Sakamoto */
151b566e972STakashi Sakamoto if (entry->vendor_id == OUI_STANTON) {
152b566e972STakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_SCS_TRANSACTION;
153b566e972STakashi Sakamoto if (entry->model_id == MODEL_SCS1M)
15407a35edcSTakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
15507a35edcSTakashi Sakamoto
15607a35edcSTakashi Sakamoto // No physical MIDI ports.
157de5126ccSTakashi Sakamoto oxfw->midi_input_ports = 0;
158de5126ccSTakashi Sakamoto oxfw->midi_output_ports = 0;
159de5126ccSTakashi Sakamoto
1609e2004f9STakashi Sakamoto return snd_oxfw_scs1x_add(oxfw);
161de5126ccSTakashi Sakamoto }
1629e2004f9STakashi Sakamoto
16367bb66d3STakashi Sakamoto if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW) {
16467bb66d3STakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION |
16567bb66d3STakashi Sakamoto SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET;
16667bb66d3STakashi Sakamoto }
16707a35edcSTakashi Sakamoto
1689e2004f9STakashi Sakamoto /*
16927e66635STakashi Sakamoto * TASCAM FireOne has physical control and requires a pair of additional
17027e66635STakashi Sakamoto * MIDI ports.
17127e66635STakashi Sakamoto */
172b566e972STakashi Sakamoto if (entry->vendor_id == VENDOR_TASCAM) {
17327e66635STakashi Sakamoto oxfw->midi_input_ports++;
17427e66635STakashi Sakamoto oxfw->midi_output_ports++;
1755ce8cc48STakashi Sakamoto return 0;
17627e66635STakashi Sakamoto }
17727e66635STakashi Sakamoto
17813f3a46dSTakashi Sakamoto /* Seek from Root Directory of Config ROM. */
17913f3a46dSTakashi Sakamoto vendor = model = 0;
18013f3a46dSTakashi Sakamoto fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
18113f3a46dSTakashi Sakamoto while (fw_csr_iterator_next(&it, &key, &val)) {
18213f3a46dSTakashi Sakamoto if (key == CSR_VENDOR)
18313f3a46dSTakashi Sakamoto vendor = val;
18413f3a46dSTakashi Sakamoto else if (key == CSR_MODEL)
18513f3a46dSTakashi Sakamoto model = val;
18613f3a46dSTakashi Sakamoto }
18713f3a46dSTakashi Sakamoto
18864794d6dSTakashi Sakamoto if (vendor == VENDOR_LOUD) {
18964794d6dSTakashi Sakamoto // Mackie Onyx Satellite with base station has a quirk to report a wrong
19064794d6dSTakashi Sakamoto // value in 'dbs' field of CIP header against its format information.
191a6f91693STakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS;
1925ce8cc48STakashi Sakamoto
19364794d6dSTakashi Sakamoto // OXFW971-based models may transfer events by blocking method.
19464794d6dSTakashi Sakamoto if (!(oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD))
19564794d6dSTakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
196cddcd547STakashi Sakamoto
197cddcd547STakashi Sakamoto if (model == MODEL_ONYX_1640I) {
198cddcd547STakashi Sakamoto //Unless receiving packets without NOINFO packet, the device transfers
199cddcd547STakashi Sakamoto //mostly half of events in packets than expected.
200cddcd547STakashi Sakamoto oxfw->quirks |= SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET |
201cddcd547STakashi Sakamoto SND_OXFW_QUIRK_VOLUNTARY_RECOVERY;
202cddcd547STakashi Sakamoto }
20364794d6dSTakashi Sakamoto }
20464794d6dSTakashi Sakamoto
2055ce8cc48STakashi Sakamoto return 0;
20613f3a46dSTakashi Sakamoto }
20713f3a46dSTakashi Sakamoto
oxfw_probe(struct fw_unit * unit,const struct ieee1394_device_id * entry)208b566e972STakashi Sakamoto static int oxfw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
2091a4e39c2STakashi Sakamoto {
210b566e972STakashi Sakamoto struct snd_card *card;
211b566e972STakashi Sakamoto struct snd_oxfw *oxfw;
2121a4e39c2STakashi Sakamoto int err;
2131a4e39c2STakashi Sakamoto
214b566e972STakashi Sakamoto if (entry->vendor_id == VENDOR_LOUD && entry->model_id == 0 && !detect_loud_models(unit))
215b566e972STakashi Sakamoto return -ENODEV;
216ec4dba50STakashi Sakamoto
217b566e972STakashi Sakamoto err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*oxfw), &card);
2181a4e39c2STakashi Sakamoto if (err < 0)
219b566e972STakashi Sakamoto return err;
220b566e972STakashi Sakamoto card->private_free = oxfw_card_free;
2215cd1d3f4STakashi Sakamoto
222b566e972STakashi Sakamoto oxfw = card->private_data;
223b566e972STakashi Sakamoto oxfw->unit = fw_unit_get(unit);
224b566e972STakashi Sakamoto dev_set_drvdata(&unit->device, oxfw);
225b566e972STakashi Sakamoto oxfw->card = card;
226b566e972STakashi Sakamoto
227b566e972STakashi Sakamoto mutex_init(&oxfw->mutex);
228b566e972STakashi Sakamoto spin_lock_init(&oxfw->lock);
229b566e972STakashi Sakamoto init_waitqueue_head(&oxfw->hwdep_wait);
230b566e972STakashi Sakamoto
231b566e972STakashi Sakamoto err = name_card(oxfw, entry);
2325ce8cc48STakashi Sakamoto if (err < 0)
2335ce8cc48STakashi Sakamoto goto error;
23413f3a46dSTakashi Sakamoto
2353d016d57STakashi Sakamoto err = snd_oxfw_stream_discover(oxfw);
236fec7b753STakashi Sakamoto if (err < 0)
237fec7b753STakashi Sakamoto goto error;
2381a4e39c2STakashi Sakamoto
239b566e972STakashi Sakamoto err = detect_quirks(oxfw, entry);
2406c29230eSTakashi Sakamoto if (err < 0)
2416c29230eSTakashi Sakamoto goto error;
2426c29230eSTakashi Sakamoto
24306a42a74STakashi Sakamoto if (oxfw->has_output || oxfw->has_input) {
244779f0dbaSTakashi Sakamoto err = snd_oxfw_stream_init_duplex(oxfw);
2456c29230eSTakashi Sakamoto if (err < 0)
2466c29230eSTakashi Sakamoto goto error;
2476c29230eSTakashi Sakamoto
2483713d93aSTakashi Sakamoto err = snd_oxfw_create_pcm(oxfw);
2491a4e39c2STakashi Sakamoto if (err < 0)
2501a4e39c2STakashi Sakamoto goto error;
2511a4e39c2STakashi Sakamoto
2523c96101fSTakashi Sakamoto snd_oxfw_proc_init(oxfw);
2533c96101fSTakashi Sakamoto
25405588d34STakashi Sakamoto err = snd_oxfw_create_midi(oxfw);
25505588d34STakashi Sakamoto if (err < 0)
25605588d34STakashi Sakamoto goto error;
25705588d34STakashi Sakamoto
2588985f4acSTakashi Sakamoto err = snd_oxfw_create_hwdep(oxfw);
2598985f4acSTakashi Sakamoto if (err < 0)
2608985f4acSTakashi Sakamoto goto error;
26106a42a74STakashi Sakamoto }
2628985f4acSTakashi Sakamoto
263b566e972STakashi Sakamoto err = snd_card_register(card);
2641a4e39c2STakashi Sakamoto if (err < 0)
2651a4e39c2STakashi Sakamoto goto error;
2661a4e39c2STakashi Sakamoto
2671a4e39c2STakashi Sakamoto return 0;
268b566e972STakashi Sakamoto error:
269b566e972STakashi Sakamoto snd_card_free(card);
270b566e972STakashi Sakamoto return err;
2711a4e39c2STakashi Sakamoto }
2721a4e39c2STakashi Sakamoto
oxfw_bus_reset(struct fw_unit * unit)2731a4e39c2STakashi Sakamoto static void oxfw_bus_reset(struct fw_unit *unit)
2741a4e39c2STakashi Sakamoto {
2751a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
2761a4e39c2STakashi Sakamoto
2771a4e39c2STakashi Sakamoto fcp_bus_reset(oxfw->unit);
2781a4e39c2STakashi Sakamoto
27906a42a74STakashi Sakamoto if (oxfw->has_output || oxfw->has_input) {
2801a4e39c2STakashi Sakamoto mutex_lock(&oxfw->mutex);
281779f0dbaSTakashi Sakamoto snd_oxfw_stream_update_duplex(oxfw);
2821a4e39c2STakashi Sakamoto mutex_unlock(&oxfw->mutex);
28306a42a74STakashi Sakamoto }
2849e2004f9STakashi Sakamoto
285b566e972STakashi Sakamoto if (oxfw->quirks & SND_OXFW_QUIRK_SCS_TRANSACTION)
2869e2004f9STakashi Sakamoto snd_oxfw_scs1x_update(oxfw);
2871a4e39c2STakashi Sakamoto }
2881a4e39c2STakashi Sakamoto
oxfw_remove(struct fw_unit * unit)2891a4e39c2STakashi Sakamoto static void oxfw_remove(struct fw_unit *unit)
2901a4e39c2STakashi Sakamoto {
2911a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
2921a4e39c2STakashi Sakamoto
29361ccc6f6STakashi Sakamoto // Block till all of ALSA character devices are released.
29461ccc6f6STakashi Sakamoto snd_card_free(oxfw->card);
2956c29230eSTakashi Sakamoto }
2965b14ec25STakashi Sakamoto
297d6ce6bbdSTakashi Sakamoto static const struct compat_info griffin_firewave = {
2981a4e39c2STakashi Sakamoto .driver_name = "FireWave",
299fec7b753STakashi Sakamoto .vendor_name = "Griffin",
300fec7b753STakashi Sakamoto .model_name = "FireWave",
3011a4e39c2STakashi Sakamoto };
3021a4e39c2STakashi Sakamoto
303d6ce6bbdSTakashi Sakamoto static const struct compat_info lacie_speakers = {
3041a4e39c2STakashi Sakamoto .driver_name = "FWSpeakers",
305fec7b753STakashi Sakamoto .vendor_name = "LaCie",
306fec7b753STakashi Sakamoto .model_name = "FireWire Speakers",
3071a4e39c2STakashi Sakamoto };
3081a4e39c2STakashi Sakamoto
309c127d5cdSTakashi Sakamoto #define OXFW_DEV_ENTRY(vendor, model, data) \
310c127d5cdSTakashi Sakamoto { \
311c127d5cdSTakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID | \
312c127d5cdSTakashi Sakamoto IEEE1394_MATCH_MODEL_ID | \
313c127d5cdSTakashi Sakamoto IEEE1394_MATCH_SPECIFIER_ID | \
314c127d5cdSTakashi Sakamoto IEEE1394_MATCH_VERSION, \
315c127d5cdSTakashi Sakamoto .vendor_id = vendor, \
316c127d5cdSTakashi Sakamoto .model_id = model, \
317c127d5cdSTakashi Sakamoto .specifier_id = SPECIFIER_1394TA, \
318c127d5cdSTakashi Sakamoto .version = VERSION_AVC, \
319c127d5cdSTakashi Sakamoto .driver_data = (kernel_ulong_t)data, \
320c127d5cdSTakashi Sakamoto }
321c127d5cdSTakashi Sakamoto
3221a4e39c2STakashi Sakamoto static const struct ieee1394_device_id oxfw_id_table[] = {
32395d0c24dSTakashi Sakamoto //
32495d0c24dSTakashi Sakamoto // OXFW970 devices:
32595d0c24dSTakashi Sakamoto // Initial firmware has a quirk to postpone isoc packet transmission during finishing async
32695d0c24dSTakashi Sakamoto // transaction. As a result, several isochronous cycles are skipped to transfer the packets
32795d0c24dSTakashi Sakamoto // and the audio data frames which should have been transferred during the cycles are put
32895d0c24dSTakashi Sakamoto // into packet at the first isoc cycle after the postpone. Furthermore, the value of SYT
32995d0c24dSTakashi Sakamoto // field in CIP header is not reliable as synchronization timing,
33095d0c24dSTakashi Sakamoto //
331c127d5cdSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_GRIFFIN, 0x00f970, &griffin_firewave),
332c127d5cdSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_LACIE, 0x00f970, &lacie_speakers),
33395d0c24dSTakashi Sakamoto // Behringer,F-Control Audio 202. The value of SYT field is not reliable at all.
334c127d5cdSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_BEHRINGER, 0x00fc22, NULL),
33595d0c24dSTakashi Sakamoto // Loud Technologies, Tapco Link.FireWire 4x6. The value of SYT field is always 0xffff.
3362239924bSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_LOUD, 0x000460, NULL),
33795d0c24dSTakashi Sakamoto // Loud Technologies, Mackie Onyx Satellite. Although revised version of firmware is
33895d0c24dSTakashi Sakamoto // installed to avoid the postpone, the value of SYT field is always 0xffff.
339c59bc10eSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_LOUD, MODEL_SATELLITE, NULL),
34095d0c24dSTakashi Sakamoto // Miglia HarmonyAudio. Not yet identified.
34195d0c24dSTakashi Sakamoto
34295d0c24dSTakashi Sakamoto //
34395d0c24dSTakashi Sakamoto // OXFW971 devices:
34495d0c24dSTakashi Sakamoto // The value of SYT field in CIP header is enough reliable. Both of blocking and non-blocking
34595d0c24dSTakashi Sakamoto // transmission methods are available.
34695d0c24dSTakashi Sakamoto //
347c59bc10eSTakashi Sakamoto // Any Mackie(Loud) models (name string/model id):
348c59bc10eSTakashi Sakamoto // Onyx-i series (former models): 0x081216
349c59bc10eSTakashi Sakamoto // Onyx 1640i: 0x001640
350c59bc10eSTakashi Sakamoto // d.2 pro/d.4 pro (built-in card): Unknown
351c59bc10eSTakashi Sakamoto // U.420: Unknown
352c59bc10eSTakashi Sakamoto // U.420d: Unknown
353ec4dba50STakashi Sakamoto {
354ec4dba50STakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID |
355ec4dba50STakashi Sakamoto IEEE1394_MATCH_SPECIFIER_ID |
356ec4dba50STakashi Sakamoto IEEE1394_MATCH_VERSION,
357ec4dba50STakashi Sakamoto .vendor_id = VENDOR_LOUD,
358bb5d776bSTakashi Sakamoto .model_id = 0,
359ec4dba50STakashi Sakamoto .specifier_id = SPECIFIER_1394TA,
360ec4dba50STakashi Sakamoto .version = VERSION_AVC,
361ec4dba50STakashi Sakamoto },
362c127d5cdSTakashi Sakamoto // TASCAM, FireOne.
363c127d5cdSTakashi Sakamoto OXFW_DEV_ENTRY(VENDOR_TASCAM, 0x800007, NULL),
364c127d5cdSTakashi Sakamoto // Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m).
36507a35edcSTakashi Sakamoto OXFW_DEV_ENTRY(OUI_STANTON, MODEL_SCS1M, NULL),
366c127d5cdSTakashi Sakamoto // Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d).
367c127d5cdSTakashi Sakamoto OXFW_DEV_ENTRY(OUI_STANTON, 0x002000, NULL),
368c127d5cdSTakashi Sakamoto // APOGEE, duet FireWire.
36907a35edcSTakashi Sakamoto OXFW_DEV_ENTRY(OUI_APOGEE, MODEL_DUET_FW, NULL),
3701a4e39c2STakashi Sakamoto { }
3711a4e39c2STakashi Sakamoto };
3721a4e39c2STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
3731a4e39c2STakashi Sakamoto
3741a4e39c2STakashi Sakamoto static struct fw_driver oxfw_driver = {
3751a4e39c2STakashi Sakamoto .driver = {
3761a4e39c2STakashi Sakamoto .owner = THIS_MODULE,
3771a4e39c2STakashi Sakamoto .name = KBUILD_MODNAME,
3781a4e39c2STakashi Sakamoto .bus = &fw_bus_type,
3791a4e39c2STakashi Sakamoto },
3801a4e39c2STakashi Sakamoto .probe = oxfw_probe,
3811a4e39c2STakashi Sakamoto .update = oxfw_bus_reset,
3821a4e39c2STakashi Sakamoto .remove = oxfw_remove,
3831a4e39c2STakashi Sakamoto .id_table = oxfw_id_table,
3841a4e39c2STakashi Sakamoto };
3851a4e39c2STakashi Sakamoto
snd_oxfw_init(void)3861a4e39c2STakashi Sakamoto static int __init snd_oxfw_init(void)
3871a4e39c2STakashi Sakamoto {
3881a4e39c2STakashi Sakamoto return driver_register(&oxfw_driver.driver);
3891a4e39c2STakashi Sakamoto }
3901a4e39c2STakashi Sakamoto
snd_oxfw_exit(void)3911a4e39c2STakashi Sakamoto static void __exit snd_oxfw_exit(void)
3921a4e39c2STakashi Sakamoto {
3931a4e39c2STakashi Sakamoto driver_unregister(&oxfw_driver.driver);
3941a4e39c2STakashi Sakamoto }
3951a4e39c2STakashi Sakamoto
3961a4e39c2STakashi Sakamoto module_init(snd_oxfw_init);
3971a4e39c2STakashi Sakamoto module_exit(snd_oxfw_exit);
398