diff options
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/Kconfig | 2 | ||||
-rw-r--r-- | sound/firewire/motu/motu-protocol-v3.c | 9 | ||||
-rw-r--r-- | sound/firewire/motu/motu.c | 2 | ||||
-rw-r--r-- | sound/firewire/motu/motu.h | 1 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw-stream.c | 100 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.c | 10 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.h | 7 |
7 files changed, 105 insertions, 26 deletions
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 22b6c77968..5973c25c2a 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -175,6 +175,8 @@ config SND_FIREWIRE_MOTU * 8pre * 828mk3 (FireWire only) * 828mk3 (Hybrid) + * 896mk3 (FireWire only) + * 896mk3 (Hybrid) * Ultralite mk3 (FireWire only) * Ultralite mk3 (Hybrid) * Traveler mk3 diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 8a0426920a..7254fdfe04 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -261,6 +261,7 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) if (motu->spec == &snd_motu_spec_828mk3_fw || motu->spec == &snd_motu_spec_828mk3_hybrid || + motu->spec == &snd_motu_spec_896mk3 || motu->spec == &snd_motu_spec_traveler_mk3 || motu->spec == &snd_motu_spec_track16) return detect_packet_formats_with_opt_ifaces(motu, data); @@ -288,6 +289,14 @@ const struct snd_motu_spec snd_motu_spec_828mk3_hybrid = { .rx_fixed_pcm_chunks = {14, 14, 14}, // Additional 4 dummy chunks at higher rate. }; +const struct snd_motu_spec snd_motu_spec_896mk3 = { + .name = "896mk3", + .protocol_version = SND_MOTU_PROTOCOL_V3, + .flags = SND_MOTU_SPEC_COMMAND_DSP, + .tx_fixed_pcm_chunks = {18, 14, 10}, + .rx_fixed_pcm_chunks = {18, 14, 10}, +}; + const struct snd_motu_spec snd_motu_spec_traveler_mk3 = { .name = "TravelerMk3", .protocol_version = SND_MOTU_PROTOCOL_V3, diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index d73599eb7d..d14ab5dd5b 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -168,10 +168,12 @@ static const struct ieee1394_device_id motu_id_table[] = { SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3_fw), // FireWire only. + SND_MOTU_DEV_ENTRY(0x000017, &snd_motu_spec_896mk3), // FireWire only. SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only. SND_MOTU_DEV_ENTRY(0x00001b, &snd_motu_spec_traveler_mk3), SND_MOTU_DEV_ENTRY(0x000030, &snd_motu_spec_ultralite_mk3), // Hybrid. SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3_hybrid), // Hybrid. + SND_MOTU_DEV_ENTRY(0x000037, &snd_motu_spec_896mk3), // Hybrid. SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), SND_MOTU_DEV_ENTRY(0x000039, &snd_motu_spec_track16), SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 3b1dc98a7b..c66be0a89c 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -138,6 +138,7 @@ extern const struct snd_motu_spec snd_motu_spec_8pre; extern const struct snd_motu_spec snd_motu_spec_828mk3_fw; extern const struct snd_motu_spec snd_motu_spec_828mk3_hybrid; +extern const struct snd_motu_spec snd_motu_spec_896mk3; extern const struct snd_motu_spec snd_motu_spec_traveler_mk3; extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3; extern const struct snd_motu_spec snd_motu_spec_audio_express; diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index f4a702def3..00f7feb91f 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -177,6 +177,8 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) flags |= CIP_JUMBO_PAYLOAD; if (oxfw->quirks & SND_OXFW_QUIRK_WRONG_DBS) flags |= CIP_WRONG_DBS; + if (oxfw->quirks & SND_OXFW_QUIRK_DBC_IS_TOTAL_PAYLOAD_QUADLETS) + flags |= CIP_DBC_IS_END_EVENT | CIP_DBC_IS_PAYLOAD_QUADLETS; } else { conn = &oxfw->in_conn; c_dir = CMP_INPUT; @@ -486,26 +488,57 @@ int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, struct snd_oxfw_stream_formation *formation) { - u8 *format; - unsigned int len; int err; - len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; - format = kmalloc(len, GFP_KERNEL); - if (format == NULL) - return -ENOMEM; + if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) { + u8 *format; + unsigned int len; - err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len); - if (err < 0) - goto end; - if (len < 3) { - err = -EIO; - goto end; + len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; + format = kmalloc(len, GFP_KERNEL); + if (format == NULL) + return -ENOMEM; + + err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len); + if (err >= 0) { + if (len < 3) + err = -EIO; + else + err = snd_oxfw_stream_parse_format(format, formation); + } + + kfree(format); + } else { + // Miglia Harmony Audio does not support Extended Stream Format Information + // command. Use the duplicated hard-coded format, instead. + unsigned int rate; + u8 *const *formats; + int i; + + err = avc_general_get_sig_fmt(oxfw->unit, &rate, dir, 0); + if (err < 0) + return err; + + if (dir == AVC_GENERAL_PLUG_DIR_IN) + formats = oxfw->rx_stream_formats; + else + formats = oxfw->tx_stream_formats; + + for (i = 0; (i < SND_OXFW_STREAM_FORMAT_ENTRIES); ++i) { + if (!formats[i]) + continue; + + err = snd_oxfw_stream_parse_format(formats[i], formation); + if (err < 0) + continue; + + if (formation->rate == rate) + break; + } + if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) + return -EIO; } - err = snd_oxfw_stream_parse_format(format, formation); -end: - kfree(format); return err; } @@ -515,7 +548,7 @@ end: * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA) * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005 */ -int snd_oxfw_stream_parse_format(u8 *format, +int snd_oxfw_stream_parse_format(const u8 *format, struct snd_oxfw_stream_formation *formation) { unsigned int i, e, channels, type; @@ -600,14 +633,33 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, unsigned int i, eid; int err; - /* get format at current sampling rate */ - err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len); - if (err < 0) { - dev_err(&oxfw->unit->device, - "fail to get current stream format for isoc %s plug %d:%d\n", - (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", - pid, err); - goto end; + // get format at current sampling rate. + if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) { + err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len); + if (err < 0) { + dev_err(&oxfw->unit->device, + "fail to get current stream format for isoc %s plug %d:%d\n", + (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", + pid, err); + goto end; + } + } else { + // Miglia Harmony Audio does not support Extended Stream Format Information + // command. Use the hard-coded format, instead. + buf[0] = 0x90; + buf[1] = 0x40; + buf[2] = avc_stream_rate_table[0]; + buf[3] = 0x00; + buf[4] = 0x01; + + if (dir == AVC_GENERAL_PLUG_DIR_IN) + buf[5] = 0x08; + else + buf[5] = 0x02; + + buf[6] = 0x06; + + *len = 7; } /* parse and set stream format */ diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 241a697ce2..98ae0e8cba 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -21,6 +21,7 @@ #define VENDOR_TASCAM 0x00022e #define OUI_STANTON 0x001260 #define OUI_APOGEE 0x0003db +#define OUI_OXFORD 0x0030e0 #define MODEL_SATELLITE 0x00200f #define MODEL_SCS1M 0x001000 @@ -232,6 +233,11 @@ static int oxfw_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent if (err < 0) goto error; + if (entry->vendor_id == OUI_OXFORD && entry->model_id == 0x00f970) { + oxfw->quirks |= SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED | + SND_OXFW_QUIRK_DBC_IS_TOTAL_PAYLOAD_QUADLETS; + } + err = snd_oxfw_stream_discover(oxfw); if (err < 0) goto error; @@ -330,6 +336,9 @@ static const struct ieee1394_device_id oxfw_id_table[] = { // OXFW_DEV_ENTRY(VENDOR_GRIFFIN, 0x00f970, &griffin_firewave), OXFW_DEV_ENTRY(VENDOR_LACIE, 0x00f970, &lacie_speakers), + // Miglia HarmonyAudio (HA02). The numeric vendor ID is ASIC vendor and the model ID is the + // default value of ASIC. + OXFW_DEV_ENTRY(OUI_OXFORD, 0x00f970, NULL), // Behringer,F-Control Audio 202. The value of SYT field is not reliable at all. OXFW_DEV_ENTRY(VENDOR_BEHRINGER, 0x00fc22, NULL), // Loud Technologies, Tapco Link.FireWire 4x6. The value of SYT field is always 0xffff. @@ -337,7 +346,6 @@ static const struct ieee1394_device_id oxfw_id_table[] = { // Loud Technologies, Mackie Onyx Satellite. Although revised version of firmware is // installed to avoid the postpone, the value of SYT field is always 0xffff. OXFW_DEV_ENTRY(VENDOR_LOUD, MODEL_SATELLITE, NULL), - // Miglia HarmonyAudio. Not yet identified. // // OXFW971 devices: diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index d728e451a2..39ea9a6dde 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -52,6 +52,11 @@ enum snd_oxfw_quirk { // performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO // are ignored, thus driver should transfer packets with timestamp. SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20, + // Miglia Harmony Audio does not support AV/C Stream Format Information command. + SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED = 0x40, + // Miglia Harmony Audio transmits CIP in which the value of dbc field expresses the number + // of accumulated payload quadlets including the packet. + SND_OXFW_QUIRK_DBC_IS_TOTAL_PAYLOAD_QUADLETS = 0x80, }; /* This is an arbitrary number for convinience. */ @@ -136,7 +141,7 @@ struct snd_oxfw_stream_formation { unsigned int pcm; unsigned int midi; }; -int snd_oxfw_stream_parse_format(u8 *format, +int snd_oxfw_stream_parse_format(const u8 *format, struct snd_oxfw_stream_formation *formation); int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, |