2011-03-15 14:53:21 +08:00
|
|
|
/*
|
2014-11-28 23:59:25 +08:00
|
|
|
* oxfw.c - a part of driver for OXFW970/971 based devices
|
2011-03-15 14:53:21 +08:00
|
|
|
*
|
|
|
|
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
|
|
* Licensed under the terms of the GNU General Public License, version 2.
|
|
|
|
*/
|
|
|
|
|
2014-11-28 23:59:27 +08:00
|
|
|
#include "oxfw.h"
|
2011-03-15 14:53:21 +08:00
|
|
|
|
|
|
|
#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000)
|
|
|
|
/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
|
|
|
|
|
|
|
|
#define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020)
|
|
|
|
#define OXFORD_HARDWARE_ID_OXFW970 0x39443841
|
|
|
|
#define OXFORD_HARDWARE_ID_OXFW971 0x39373100
|
|
|
|
|
2014-12-08 23:10:45 +08:00
|
|
|
#define VENDOR_LOUD 0x000ff2
|
2011-03-15 14:53:21 +08:00
|
|
|
#define VENDOR_GRIFFIN 0x001292
|
2014-12-08 23:10:45 +08:00
|
|
|
#define VENDOR_BEHRINGER 0x001564
|
2011-03-15 14:53:21 +08:00
|
|
|
#define VENDOR_LACIE 0x00d04b
|
2015-10-18 16:09:40 +08:00
|
|
|
#define VENDOR_TASCAM 0x00022e
|
2015-12-22 08:15:45 +08:00
|
|
|
#define OUI_STANTON 0x001260
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2015-09-20 20:18:55 +08:00
|
|
|
#define MODEL_SATELLITE 0x00200f
|
|
|
|
|
2011-03-15 14:53:21 +08:00
|
|
|
#define SPECIFIER_1394TA 0x00a02d
|
|
|
|
#define VERSION_AVC 0x010001
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
|
2011-03-15 14:53:21 +08:00
|
|
|
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
2014-11-28 23:59:25 +08:00
|
|
|
MODULE_ALIAS("snd-firewire-speakers");
|
2015-12-22 08:15:45 +08:00
|
|
|
MODULE_ALIAS("snd-scs1x");
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2015-12-16 19:37:57 +08:00
|
|
|
struct compat_info {
|
|
|
|
const char *driver_name;
|
|
|
|
const char *vendor_name;
|
|
|
|
const char *model_name;
|
|
|
|
};
|
|
|
|
|
2014-12-08 23:10:45 +08:00
|
|
|
static bool detect_loud_models(struct fw_unit *unit)
|
|
|
|
{
|
|
|
|
const char *const models[] = {
|
|
|
|
"Onyxi",
|
|
|
|
"Onyx-i",
|
ALSA: oxfw: add support for Mackie Onyx 1640i
As of kernel 4.10, ALSA OXFW driver has no entry for Onyx 1640i produced
by Mackie (Loud Technologies). This commit supplement it.
I note that there're two models produced by Mackie (Loud Technologies),
which have the same name 'Onyx 1640i'. The former model based on OXFW970,
the latter model based on Dice. This is probably due to low quality of
communication of OXFW series.
Additionally, the tester reports his or her experiences to get unexpected
result at higher sampling transmission frequency as 88.2/96.0 kHz. We
didn't have further investigation yet[0].
$ ./linux-firewire-utils/src/crpp < config_rom
ROM header and bus information block
-----------------------------------------------------------------
400 042525ce bus_info_length 4, crc_length 37, crc 9678
404 31333934 bus_name "1394"
408 20ff5003 irmc 0, cmc 0, isc 1, bmc 0, cyc_clk_acc 255, max_rec 5 (64)
40c 000ff205 company_id 000ff2 |
410 00000fcf device_id 0500000fcf | EUI-64 000ff20500000fcf
root directory
-----------------------------------------------------------------
414 0006c1b7 directory_length 6, crc 49591
418 03000ff2 vendor
41c 8100000a --> descriptor leaf at 444
420 17001640 model
424 81000011 --> descriptor leaf at 468
428 0c0083c0 node capabilities per IEEE 1394
42c d1000001 --> unit directory at 430
unit directory at 430
-----------------------------------------------------------------
430 00040b97 directory_length 4, crc 2967
434 1200a02d specifier id: 1394 TA
438 13010001 version: AV/C
43c 17001640 model
440 81000010 --> descriptor leaf at 480
descriptor leaf at 444
-----------------------------------------------------------------
444 0008a886 leaf_length 8, crc 43142
448 00000000 textual descriptor
44c 00000000 minimal ASCII
450 4c6f7564 "Loud"
454 20546563 " Tec"
458 686e6f6c "hnol"
45c 6f676965 "ogie"
460 7320496e "s In"
464 632e0000 "c."
descriptor leaf at 468
-----------------------------------------------------------------
468 00059fcf leaf_length 5, crc 40911
46c 00000000 textual descriptor
470 00000000 minimal ASCII
474 4f6e7978 "Onyx"
478 20313634 " 164"
47c 30690000 "0i"
descriptor leaf at 480
-----------------------------------------------------------------
480 00059fcf leaf_length 5, crc 40911
484 00000000 textual descriptor
488 00000000 minimal ASCII
48c 4f6e7978 "Onyx"
490 20313634 " 164"
494 30690000 "0i"
[0]: [FFADO-user] Mackie 1640i issues (finer details)
https://sourceforge.net/p/ffado/mailman/message/35229260/
Tested-by: Seth O'Bannion <saobannion@gmail.com>
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2017-01-03 10:36:08 +08:00
|
|
|
"Onyx 1640i",
|
2014-12-08 23:10:45 +08:00
|
|
|
"d.Pro",
|
|
|
|
"Mackie Onyx Satellite",
|
|
|
|
"Tapco LINK.firewire 4x6",
|
|
|
|
"U.420"};
|
|
|
|
char model[32];
|
|
|
|
unsigned int i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = fw_csr_string(unit->directory, CSR_MODEL,
|
|
|
|
model, sizeof(model));
|
|
|
|
if (err < 0)
|
2014-12-13 03:28:10 +08:00
|
|
|
return false;
|
2014-12-08 23:10:45 +08:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(models); i++) {
|
|
|
|
if (strcmp(models[i], model) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (i < ARRAY_SIZE(models));
|
|
|
|
}
|
|
|
|
|
2014-12-08 23:10:40 +08:00
|
|
|
static int name_card(struct snd_oxfw *oxfw)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2014-12-08 23:10:40 +08:00
|
|
|
struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
|
2015-12-16 19:37:57 +08:00
|
|
|
const struct compat_info *info;
|
2014-12-08 23:10:45 +08:00
|
|
|
char vendor[24];
|
|
|
|
char model[32];
|
2014-12-08 23:10:40 +08:00
|
|
|
const char *d, *v, *m;
|
|
|
|
u32 firmware;
|
2011-03-15 14:53:21 +08:00
|
|
|
int err;
|
|
|
|
|
2014-12-08 23:10:45 +08:00
|
|
|
/* get vendor name from root directory */
|
|
|
|
err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR,
|
|
|
|
vendor, sizeof(vendor));
|
|
|
|
if (err < 0)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* get model name from unit directory */
|
|
|
|
err = fw_csr_string(oxfw->unit->directory, CSR_MODEL,
|
|
|
|
model, sizeof(model));
|
|
|
|
if (err < 0)
|
|
|
|
goto end;
|
|
|
|
|
2014-12-08 23:10:40 +08:00
|
|
|
err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST,
|
|
|
|
OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0);
|
|
|
|
if (err < 0)
|
|
|
|
goto end;
|
|
|
|
be32_to_cpus(&firmware);
|
|
|
|
|
2014-12-08 23:10:45 +08:00
|
|
|
/* to apply card definitions */
|
2015-12-15 22:56:20 +08:00
|
|
|
if (oxfw->entry->vendor_id == VENDOR_GRIFFIN ||
|
|
|
|
oxfw->entry->vendor_id == VENDOR_LACIE) {
|
2015-12-16 19:37:57 +08:00
|
|
|
info = (const struct compat_info *)oxfw->entry->driver_data;
|
2015-12-15 22:56:20 +08:00
|
|
|
d = info->driver_name;
|
|
|
|
v = info->vendor_name;
|
|
|
|
m = info->model_name;
|
2014-12-08 23:10:45 +08:00
|
|
|
} else {
|
|
|
|
d = "OXFW";
|
|
|
|
v = vendor;
|
|
|
|
m = model;
|
|
|
|
}
|
2014-12-08 23:10:40 +08:00
|
|
|
|
|
|
|
strcpy(oxfw->card->driver, d);
|
|
|
|
strcpy(oxfw->card->mixername, m);
|
|
|
|
strcpy(oxfw->card->shortname, m);
|
|
|
|
|
|
|
|
snprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
|
|
|
|
"%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
|
|
|
|
v, m, firmware >> 20, firmware & 0xffff,
|
|
|
|
fw_dev->config_rom[3], fw_dev->config_rom[4],
|
|
|
|
dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
|
|
|
|
end:
|
|
|
|
return err;
|
2011-03-15 14:53:21 +08:00
|
|
|
}
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
static void oxfw_free(struct snd_oxfw *oxfw)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2014-12-08 23:10:42 +08:00
|
|
|
unsigned int i;
|
|
|
|
|
2015-02-21 22:55:00 +08:00
|
|
|
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
|
|
|
|
if (oxfw->has_output)
|
|
|
|
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
|
|
|
|
|
2015-02-21 22:54:57 +08:00
|
|
|
fw_unit_put(oxfw->unit);
|
|
|
|
|
2014-12-08 23:10:46 +08:00
|
|
|
for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
|
|
|
|
kfree(oxfw->tx_stream_formats[i]);
|
2014-12-08 23:10:42 +08:00
|
|
|
kfree(oxfw->rx_stream_formats[i]);
|
2014-12-08 23:10:46 +08:00
|
|
|
}
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2015-12-16 19:37:54 +08:00
|
|
|
kfree(oxfw->spec);
|
2014-11-28 23:59:25 +08:00
|
|
|
mutex_destroy(&oxfw->mutex);
|
2011-03-15 14:53:21 +08:00
|
|
|
}
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
/*
|
|
|
|
* This module releases the FireWire unit data after all ALSA character devices
|
|
|
|
* are released by applications. This is for releasing stream data or finishing
|
|
|
|
* transactions safely. Thus at returning from .remove(), this module still keep
|
|
|
|
* references for the unit.
|
|
|
|
*/
|
|
|
|
static void oxfw_card_free(struct snd_card *card)
|
|
|
|
{
|
|
|
|
oxfw_free(card->private_data);
|
|
|
|
}
|
|
|
|
|
2015-12-15 22:56:21 +08:00
|
|
|
static int detect_quirks(struct snd_oxfw *oxfw)
|
2015-09-20 20:18:55 +08:00
|
|
|
{
|
|
|
|
struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
|
|
|
|
struct fw_csr_iterator it;
|
|
|
|
int key, val;
|
|
|
|
int vendor, model;
|
|
|
|
|
2015-12-15 22:56:21 +08:00
|
|
|
/*
|
|
|
|
* Add ALSA control elements for two models to keep compatibility to
|
|
|
|
* old firewire-speaker module.
|
|
|
|
*/
|
2015-12-16 19:37:56 +08:00
|
|
|
if (oxfw->entry->vendor_id == VENDOR_GRIFFIN)
|
|
|
|
return snd_oxfw_add_spkr(oxfw, false);
|
|
|
|
if (oxfw->entry->vendor_id == VENDOR_LACIE)
|
|
|
|
return snd_oxfw_add_spkr(oxfw, true);
|
2015-12-15 22:56:21 +08:00
|
|
|
|
2015-12-22 08:15:45 +08:00
|
|
|
/*
|
|
|
|
* Stanton models supports asynchronous transactions for unique MIDI
|
|
|
|
* messages.
|
|
|
|
*/
|
2015-12-22 08:15:46 +08:00
|
|
|
if (oxfw->entry->vendor_id == OUI_STANTON) {
|
|
|
|
/* No physical MIDI ports. */
|
|
|
|
oxfw->midi_input_ports = 0;
|
|
|
|
oxfw->midi_output_ports = 0;
|
|
|
|
|
|
|
|
/* Output stream exists but no data channels are useful. */
|
|
|
|
oxfw->has_output = false;
|
|
|
|
|
2015-12-22 08:15:45 +08:00
|
|
|
return snd_oxfw_scs1x_add(oxfw);
|
2015-12-22 08:15:46 +08:00
|
|
|
}
|
2015-12-22 08:15:45 +08:00
|
|
|
|
2015-12-15 22:56:20 +08:00
|
|
|
/*
|
|
|
|
* TASCAM FireOne has physical control and requires a pair of additional
|
|
|
|
* MIDI ports.
|
|
|
|
*/
|
|
|
|
if (oxfw->entry->vendor_id == VENDOR_TASCAM) {
|
|
|
|
oxfw->midi_input_ports++;
|
|
|
|
oxfw->midi_output_ports++;
|
2015-12-15 22:56:21 +08:00
|
|
|
return 0;
|
2015-12-15 22:56:20 +08:00
|
|
|
}
|
|
|
|
|
2015-09-20 20:18:55 +08:00
|
|
|
/* Seek from Root Directory of Config ROM. */
|
|
|
|
vendor = model = 0;
|
|
|
|
fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
|
|
|
|
while (fw_csr_iterator_next(&it, &key, &val)) {
|
|
|
|
if (key == CSR_VENDOR)
|
|
|
|
vendor = val;
|
|
|
|
else if (key == CSR_MODEL)
|
|
|
|
model = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mackie Onyx Satellite with base station has a quirk to report a wrong
|
|
|
|
* value in 'dbs' field of CIP header against its format information.
|
|
|
|
*/
|
|
|
|
if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
|
|
|
|
oxfw->wrong_dbs = true;
|
2015-12-15 22:56:21 +08:00
|
|
|
|
|
|
|
return 0;
|
2015-09-20 20:18:55 +08:00
|
|
|
}
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
static void do_registration(struct work_struct *work)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2016-03-31 07:47:07 +08:00
|
|
|
struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work);
|
2011-03-15 14:53:21 +08:00
|
|
|
int err;
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
if (oxfw->registered)
|
|
|
|
return;
|
2014-12-08 23:10:45 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0,
|
|
|
|
&oxfw->card);
|
2011-03-15 14:53:21 +08:00
|
|
|
if (err < 0)
|
2016-03-31 07:47:07 +08:00
|
|
|
return;
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
err = name_card(oxfw);
|
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2017-04-03 20:13:40 +08:00
|
|
|
err = snd_oxfw_stream_discover(oxfw);
|
2014-12-08 23:10:42 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
2017-04-03 20:13:40 +08:00
|
|
|
err = detect_quirks(oxfw);
|
2015-12-15 22:56:21 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
2015-09-20 20:18:55 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream);
|
2014-12-08 23:10:40 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
2016-03-31 07:47:07 +08:00
|
|
|
if (oxfw->has_output) {
|
|
|
|
err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream);
|
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2014-11-28 23:59:28 +08:00
|
|
|
err = snd_oxfw_create_pcm(oxfw);
|
2011-03-15 14:53:21 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-12-08 23:10:43 +08:00
|
|
|
snd_oxfw_proc_init(oxfw);
|
|
|
|
|
2014-12-08 23:10:48 +08:00
|
|
|
err = snd_oxfw_create_midi(oxfw);
|
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-12-08 23:10:49 +08:00
|
|
|
err = snd_oxfw_create_hwdep(oxfw);
|
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
err = snd_card_register(oxfw->card);
|
2011-03-15 14:53:21 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
/*
|
|
|
|
* After registered, oxfw instance can be released corresponding to
|
|
|
|
* releasing the sound card instance.
|
|
|
|
*/
|
|
|
|
oxfw->card->private_free = oxfw_card_free;
|
|
|
|
oxfw->card->private_data = oxfw;
|
|
|
|
oxfw->registered = true;
|
|
|
|
|
|
|
|
return;
|
|
|
|
error:
|
|
|
|
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
|
|
|
|
if (oxfw->has_output)
|
|
|
|
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
|
|
|
|
snd_card_free(oxfw->card);
|
|
|
|
dev_info(&oxfw->unit->device,
|
|
|
|
"Sound card registration failed: %d\n", err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int oxfw_probe(struct fw_unit *unit,
|
|
|
|
const struct ieee1394_device_id *entry)
|
|
|
|
{
|
|
|
|
struct snd_oxfw *oxfw;
|
|
|
|
|
|
|
|
if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit))
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
/* Allocate this independent of sound card instance. */
|
|
|
|
oxfw = kzalloc(sizeof(struct snd_oxfw), GFP_KERNEL);
|
|
|
|
if (oxfw == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
oxfw->entry = entry;
|
|
|
|
oxfw->unit = fw_unit_get(unit);
|
2014-11-28 23:59:25 +08:00
|
|
|
dev_set_drvdata(&unit->device, oxfw);
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
mutex_init(&oxfw->mutex);
|
|
|
|
spin_lock_init(&oxfw->lock);
|
|
|
|
init_waitqueue_head(&oxfw->hwdep_wait);
|
|
|
|
|
|
|
|
/* Allocate and register this sound card later. */
|
|
|
|
INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration);
|
|
|
|
snd_fw_schedule_registration(unit, &oxfw->dwork);
|
|
|
|
|
2011-03-15 14:53:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static void oxfw_bus_reset(struct fw_unit *unit)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2014-11-28 23:59:25 +08:00
|
|
|
struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
if (!oxfw->registered)
|
|
|
|
snd_fw_schedule_registration(unit, &oxfw->dwork);
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
fcp_bus_reset(oxfw->unit);
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
if (oxfw->registered) {
|
|
|
|
mutex_lock(&oxfw->mutex);
|
2014-12-08 23:10:46 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream);
|
|
|
|
if (oxfw->has_output)
|
|
|
|
snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
|
2014-12-08 23:10:46 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
mutex_unlock(&oxfw->mutex);
|
2015-12-22 08:15:45 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
if (oxfw->entry->vendor_id == OUI_STANTON)
|
|
|
|
snd_oxfw_scs1x_update(oxfw);
|
|
|
|
}
|
2011-03-15 14:53:21 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static void oxfw_remove(struct fw_unit *unit)
|
2013-06-10 00:15:00 +08:00
|
|
|
{
|
2014-11-28 23:59:25 +08:00
|
|
|
struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
|
2013-06-10 00:15:00 +08:00
|
|
|
|
2016-03-31 07:47:07 +08:00
|
|
|
/*
|
|
|
|
* Confirm to stop the work for registration before the sound card is
|
|
|
|
* going to be released. The work is not scheduled again because bus
|
|
|
|
* reset handler is not called anymore.
|
|
|
|
*/
|
|
|
|
cancel_delayed_work_sync(&oxfw->dwork);
|
|
|
|
|
|
|
|
if (oxfw->registered) {
|
|
|
|
/* No need to wait for releasing card object in this context. */
|
|
|
|
snd_card_free_when_closed(oxfw->card);
|
|
|
|
} else {
|
|
|
|
/* Don't forget this case. */
|
|
|
|
oxfw_free(oxfw);
|
|
|
|
}
|
2013-06-10 00:15:00 +08:00
|
|
|
}
|
|
|
|
|
2015-12-16 19:37:57 +08:00
|
|
|
static const struct compat_info griffin_firewave = {
|
2013-06-10 00:15:00 +08:00
|
|
|
.driver_name = "FireWave",
|
2014-12-08 23:10:40 +08:00
|
|
|
.vendor_name = "Griffin",
|
|
|
|
.model_name = "FireWave",
|
2013-06-10 00:15:00 +08:00
|
|
|
};
|
|
|
|
|
2015-12-16 19:37:57 +08:00
|
|
|
static const struct compat_info lacie_speakers = {
|
2013-06-10 00:15:00 +08:00
|
|
|
.driver_name = "FWSpeakers",
|
2014-12-08 23:10:40 +08:00
|
|
|
.vendor_name = "LaCie",
|
|
|
|
.model_name = "FireWire Speakers",
|
2013-06-10 00:15:00 +08:00
|
|
|
};
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static const struct ieee1394_device_id oxfw_id_table[] = {
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID |
|
|
|
|
IEEE1394_MATCH_SPECIFIER_ID |
|
|
|
|
IEEE1394_MATCH_VERSION,
|
|
|
|
.vendor_id = VENDOR_GRIFFIN,
|
|
|
|
.model_id = 0x00f970,
|
|
|
|
.specifier_id = SPECIFIER_1394TA,
|
|
|
|
.version = VERSION_AVC,
|
2013-06-10 00:15:00 +08:00
|
|
|
.driver_data = (kernel_ulong_t)&griffin_firewave,
|
2011-03-15 14:53:21 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID |
|
|
|
|
IEEE1394_MATCH_SPECIFIER_ID |
|
|
|
|
IEEE1394_MATCH_VERSION,
|
|
|
|
.vendor_id = VENDOR_LACIE,
|
|
|
|
.model_id = 0x00f970,
|
|
|
|
.specifier_id = SPECIFIER_1394TA,
|
|
|
|
.version = VERSION_AVC,
|
2013-06-10 00:15:00 +08:00
|
|
|
.driver_data = (kernel_ulong_t)&lacie_speakers,
|
2011-03-15 14:53:21 +08:00
|
|
|
},
|
2014-12-08 23:10:45 +08:00
|
|
|
/* Behringer,F-Control Audio 202 */
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
|
|
.vendor_id = VENDOR_BEHRINGER,
|
|
|
|
.model_id = 0x00fc22,
|
|
|
|
},
|
|
|
|
/*
|
|
|
|
* Any Mackie(Loud) models (name string/model id):
|
|
|
|
* Onyx-i series (former models): 0x081216
|
|
|
|
* Mackie Onyx Satellite: 0x00200f
|
|
|
|
* Tapco LINK.firewire 4x6: 0x000460
|
|
|
|
* d.2 pro: Unknown
|
|
|
|
* d.4 pro: Unknown
|
|
|
|
* U.420: Unknown
|
|
|
|
* U.420d: Unknown
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_SPECIFIER_ID |
|
|
|
|
IEEE1394_MATCH_VERSION,
|
|
|
|
.vendor_id = VENDOR_LOUD,
|
|
|
|
.specifier_id = SPECIFIER_1394TA,
|
|
|
|
.version = VERSION_AVC,
|
|
|
|
},
|
2015-10-18 16:09:40 +08:00
|
|
|
/* TASCAM, FireOne */
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
|
|
.vendor_id = VENDOR_TASCAM,
|
|
|
|
.model_id = 0x800007,
|
|
|
|
},
|
2015-12-22 08:15:45 +08:00
|
|
|
/* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
|
|
.vendor_id = OUI_STANTON,
|
|
|
|
.model_id = 0x001000,
|
|
|
|
},
|
|
|
|
/* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */
|
|
|
|
{
|
|
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
|
|
.vendor_id = OUI_STANTON,
|
|
|
|
.model_id = 0x002000,
|
|
|
|
},
|
2011-03-15 14:53:21 +08:00
|
|
|
{ }
|
|
|
|
};
|
2014-11-28 23:59:25 +08:00
|
|
|
MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
|
2011-03-15 14:53:21 +08:00
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static struct fw_driver oxfw_driver = {
|
2011-03-15 14:53:21 +08:00
|
|
|
.driver = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.name = KBUILD_MODNAME,
|
|
|
|
.bus = &fw_bus_type,
|
|
|
|
},
|
2014-11-28 23:59:25 +08:00
|
|
|
.probe = oxfw_probe,
|
|
|
|
.update = oxfw_bus_reset,
|
|
|
|
.remove = oxfw_remove,
|
|
|
|
.id_table = oxfw_id_table,
|
2011-03-15 14:53:21 +08:00
|
|
|
};
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static int __init snd_oxfw_init(void)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2014-11-28 23:59:25 +08:00
|
|
|
return driver_register(&oxfw_driver.driver);
|
2011-03-15 14:53:21 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
static void __exit snd_oxfw_exit(void)
|
2011-03-15 14:53:21 +08:00
|
|
|
{
|
2014-11-28 23:59:25 +08:00
|
|
|
driver_unregister(&oxfw_driver.driver);
|
2011-03-15 14:53:21 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:25 +08:00
|
|
|
module_init(snd_oxfw_init);
|
|
|
|
module_exit(snd_oxfw_exit);
|