[alsa-devel] [PATCH 00/11] ALSA: bebob: improve support for DM1500/BeBoBv3
Hi,
This patchset updates my previous one.
[alsa-devel] [RFC][PATCH 00/11] improve support for DM1500/BeBoBv3 http://mailman.alsa-project.org/pipermail/alsa-devel/2015-June/093320.html
Changes since the RFC: * re-gain missing enumerator member * update commit comments
I hope them to be merged into upstream.
Takashi Sakamoto (11): ALSA: bebob: improve signal mode detection for clock source ALSA: bebob: apply new enumerator to normalize the type of clock source ALSA: bebob: preparation for replacing string literals by normalized representation for model-dependent structures ALSA: bebob: use normalized representation for the type of clock source ALSA: bebob: obsolete string literal expression for clock source ALSA: bebob: add SYT-Match support ALSA: bebob: add 'version' member for BeBoB protocol version ALSA: bebob: expand timeout for DM1500 quirk ALSA: bebob: loosen up severity of checking continuity for BeBoB v3 quirk ALSA: bebob: keep duplex streams always to keep internal multiplexer properly ALSA: bebob: add support for Behringer FCA 610/1616
sound/firewire/Kconfig | 1 + sound/firewire/bebob/bebob.c | 14 ++- sound/firewire/bebob/bebob.h | 20 +++-- sound/firewire/bebob/bebob_focusrite.c | 33 +++++--- sound/firewire/bebob/bebob_maudio.c | 23 +++-- sound/firewire/bebob/bebob_midi.c | 8 +- sound/firewire/bebob/bebob_pcm.c | 14 +-- sound/firewire/bebob/bebob_proc.c | 22 ++--- sound/firewire/bebob/bebob_stream.c | 150 ++++++++++++++++++++++++--------- sound/firewire/bebob/bebob_terratec.c | 30 +++++-- sound/firewire/bebob/bebob_yamaha.c | 20 ++++- 11 files changed, 235 insertions(+), 100 deletions(-)
With BeBoB version 3, current ALSA BeBoB driver detects the type of current clock signal source wrongly. This is due to a lack of proper implementation to parse the information.
This commit renews the parser. As a result, this driver detects SYT-Match clock signal, thus it can start streams with two modes; SYT-Match mode and the others. SYT-Match mode will be supported in future commits.
There's a constrain about detected internal/external clock source. When detecting external clock source, this driver allows userspace applications to use current sampling rate only. This is due to consider abour synchronization to external clock sources such as S/PDIF, ADAT or word-clock.
According to several information from some devices, I guesss that the internal clock of most devices synchronize to IEEE 1394 cycle start packet. In this case, by a usual way, it's detect as 'Sync type of output Music Sub-Unit' connected to 'Sync type of PCR output Unit (oPCR)', and this driver judges it as internal clock. Therefore, userspace applications is allowed to request arbitrary supported sampling rates.
On the other hand, several devices based on BeBoB version 3 have additional internal clock. In this case, by a usual way, it's detect as 'Sync/Additional type of External input Unit'. Unfortunately, there's no way to distinguish this sync type from the other external clock sources such as word-clock. In this case, this driver handles it as external and userspace applications is forced to use current sampling rate.
I note that when the source of clock is detected as 'Isochronous stream type of input PCR[0]', it's under 'SYT-Match' mode. In this mode, the synchronization clock is generated according to SYT-series in received packets. In this case, this driver generates the series by myself. I experienced this mode often make the device silent suddenly during playbacking. This means that the mode is easy to lost synchronization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 3 +- sound/firewire/bebob/bebob_stream.c | 78 +++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index dfbcd23..2a918ca 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -159,7 +159,8 @@ enum avc_bridgeco_plug_type { AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, - AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05 + AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05, + AVC_BRIDGECO_PLUG_TYPE_ADDITION = 0x06 }; static inline void avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 98e4fc8..2ccef4ce 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -122,6 +122,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; unsigned int id; + enum avc_bridgeco_plug_type type; int err = 0;
*internal = false; @@ -182,14 +183,75 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) goto end; }
- /* - * If source of clock is internal CSR, Music Sub Unit Sync Input is - * a destination of Music Sub Unit Sync Output. - */ - *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) && - (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) && - (input[2] == 0x0c) && - (input[3] == 0x00)); + /* The source from any output plugs is for one purpose only. */ + if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) { + /* + * In BeBoB architecture, the source from music subunit may + * bypass from oPCR[0]. This means that this source gives + * synchronization to IEEE 1394 cycle start packet. + */ + if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && + input[2] == 0x0c) { + *internal = true; + goto end; + } + /* The source from any input units is for several purposes. */ + } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) { + if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) { + if (input[3] == 0x00) { + /* + * This source comes from iPCR[0]. This means + * that presentation timestamp calculated by + * SYT series of the received packets. In + * short, this driver is the master of + * synchronization. + */ + err = -EIO; + goto end; + } else { + /* + * This source comes from iPCR[1-29]. This + * means that the synchronization stream is not + * the Audio/MIDI compound stream. + */ + *internal = false; + goto end; + } + } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { + /* Check type of this plug. */ + avc_bridgeco_fill_unit_addr(addr, + AVC_BRIDGECO_PLUG_DIR_IN, + AVC_BRIDGECO_PLUG_UNIT_EXT, + input[3]); + err = avc_bridgeco_get_plug_type(bebob->unit, addr, + &type); + if (err < 0) + goto end; + + if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) { + /* + * SPDIF/ADAT or sometimes (not always) word + * clock. + */ + *internal = false; + goto end; + } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { + /* Often word clock. */ + *internal = false; + goto end; + } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { + /* + * Not standard. + * Mostly, additional internal clock. + */ + *internal = true; + goto end; + } + } + } + + /* Not supported. */ + err = -EIO; end: return err; }
Previous commit allows this driver to detect several types of clock source, while there's no normalized expression for it.
This commit adds a new enumerator for this purpose.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 2a918ca..368b62d 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -50,9 +50,15 @@ extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES];
/* device specific operations */ #define SND_BEBOB_CLOCK_INTERNAL "Internal" +enum snd_bebob_clock_type { + SND_BEBOB_CLOCK_TYPE_INTERNAL = 0, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, + SND_BEBOB_CLOCK_TYPE_SYT, +}; struct snd_bebob_clock_spec { unsigned int num; const char *const *labels; + enum snd_bebob_clock_type *types; int (*get)(struct snd_bebob *bebob, unsigned int *id); }; struct snd_bebob_rate_spec {
Previous commit adds a enumerator as a normalized representation of clock source, while model-dependent structures still use string literals for this purpose.
This commit is a preparation for replacement.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_focusrite.c | 27 +++++++++++++++++++++++---- sound/firewire/bebob/bebob_maudio.c | 13 ++++++++++--- sound/firewire/bebob/bebob_terratec.c | 26 +++++++++++++++++++++++--- sound/firewire/bebob/bebob_yamaha.c | 18 ++++++++++++++++-- 4 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c index fc67c1b..45c8f76 100644 --- a/sound/firewire/bebob/bebob_focusrite.c +++ b/sound/firewire/bebob/bebob_focusrite.c @@ -106,9 +106,21 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) static const char *const saffirepro_10_clk_src_labels[] = { SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" }; +static enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ +}; static const char *const saffirepro_26_clk_src_labels[] = { SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" }; +static enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT1 */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT2 */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ +}; /* Value maps between registers and labels for SaffirePro 10/26. */ static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { /* SaffirePro 10 */ @@ -178,7 +190,7 @@ saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) goto end;
/* depending on hardware, use a different mapping */ - if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) + if (bebob->spec->clock->types == saffirepro_10_clk_src_types) map = saffirepro_clk_maps[0]; else map = saffirepro_clk_maps[1]; @@ -198,6 +210,10 @@ struct snd_bebob_spec saffire_le_spec; static const char *const saffire_both_clk_src_labels[] = { SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" }; +static enum snd_bebob_clock_type saffire_both_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, +}; static int saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) { @@ -259,8 +275,9 @@ static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { }; /* Saffire Pro 26 I/O */ static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { - .num = ARRAY_SIZE(saffirepro_26_clk_src_labels), + .num = ARRAY_SIZE(saffirepro_26_clk_src_types), .labels = saffirepro_26_clk_src_labels, + .types = saffirepro_26_clk_src_types, .get = &saffirepro_both_clk_src_get, }; struct snd_bebob_spec saffirepro_26_spec = { @@ -270,8 +287,9 @@ struct snd_bebob_spec saffirepro_26_spec = { }; /* Saffire Pro 10 I/O */ static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { - .num = ARRAY_SIZE(saffirepro_10_clk_src_labels), + .num = ARRAY_SIZE(saffirepro_10_clk_src_types), .labels = saffirepro_10_clk_src_labels, + .types = saffirepro_10_clk_src_types, .get = &saffirepro_both_clk_src_get, }; struct snd_bebob_spec saffirepro_10_spec = { @@ -285,8 +303,9 @@ static struct snd_bebob_rate_spec saffire_both_rate_spec = { .set = &snd_bebob_stream_set_rate, }; static struct snd_bebob_clock_spec saffire_both_clk_spec = { - .num = ARRAY_SIZE(saffire_both_clk_src_labels), + .num = ARRAY_SIZE(saffire_both_clk_src_types), .labels = saffire_both_clk_src_labels, + .types = saffire_both_clk_src_types, .get = &saffire_both_clk_src_get, }; /* Saffire LE */ diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 9ee25a6..7a43afc 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -343,6 +343,12 @@ end: static const char *const special_clk_labels[] = { SND_BEBOB_CLOCK_INTERNAL " with Digital Mute", "Digital", "Word Clock", SND_BEBOB_CLOCK_INTERNAL}; +static enum snd_bebob_clock_type special_clk_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, /* With digital mute */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* SPDIF/ADAT */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ + SND_BEBOB_CLOCK_TYPE_INTERNAL, +}; static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) { struct special_params *params = bebob->maudio_special_quirk; @@ -352,7 +358,7 @@ static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) static int special_clk_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *einf) { - return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_labels), + return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_types), special_clk_labels); } static int special_clk_ctl_get(struct snd_kcontrol *kctl, @@ -371,7 +377,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, int err, id;
id = uval->value.enumerated.item[0]; - if (id >= ARRAY_SIZE(special_clk_labels)) + if (id >= ARRAY_SIZE(special_clk_types)) return -EINVAL;
mutex_lock(&bebob->mutex); @@ -708,8 +714,9 @@ static struct snd_bebob_rate_spec special_rate_spec = { .set = &special_set_rate, }; static struct snd_bebob_clock_spec special_clk_spec = { - .num = ARRAY_SIZE(special_clk_labels), + .num = ARRAY_SIZE(special_clk_types), .labels = special_clk_labels, + .types = special_clk_types, .get = &special_clk_get, }; static struct snd_bebob_meter_spec special_meter_spec = { diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c index ad63500..3b64d8d 100644 --- a/sound/firewire/bebob/bebob_terratec.c +++ b/sound/firewire/bebob/bebob_terratec.c @@ -11,6 +11,11 @@ static const char *const phase88_rack_clk_src_labels[] = { SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock" }; +static enum snd_bebob_clock_type phase88_rack_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ +}; static int phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id) { @@ -37,10 +42,23 @@ end: static const char *const phase24_series_clk_src_labels[] = { SND_BEBOB_CLOCK_INTERNAL, "Digital In" }; +static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ +}; static int phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) { - return avc_audio_get_selector(bebob->unit, 0, 4, id); + int err; + + err = avc_audio_get_selector(bebob->unit, 0, 4, id); + if (err < 0) + return err; + + if (*id >= ARRAY_SIZE(phase24_series_clk_src_types)) + return -EIO; + + return 0; }
static struct snd_bebob_rate_spec phase_series_rate_spec = { @@ -50,8 +68,9 @@ static struct snd_bebob_rate_spec phase_series_rate_spec = {
/* PHASE 88 Rack FW */ static struct snd_bebob_clock_spec phase88_rack_clk = { - .num = ARRAY_SIZE(phase88_rack_clk_src_labels), + .num = ARRAY_SIZE(phase88_rack_clk_src_types), .labels = phase88_rack_clk_src_labels, + .types = phase88_rack_clk_src_types, .get = &phase88_rack_clk_src_get, }; struct snd_bebob_spec phase88_rack_spec = { @@ -62,8 +81,9 @@ struct snd_bebob_spec phase88_rack_spec = {
/* 'PHASE 24 FW' and 'PHASE X24 FW' */ static struct snd_bebob_clock_spec phase24_series_clk = { - .num = ARRAY_SIZE(phase24_series_clk_src_labels), + .num = ARRAY_SIZE(phase24_series_clk_src_types), .labels = phase24_series_clk_src_labels, + .types = phase24_series_clk_src_types, .get = &phase24_series_clk_src_get, }; struct snd_bebob_spec phase24_series_spec = { diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c index ef1fe38..2f59512 100644 --- a/sound/firewire/bebob/bebob_yamaha.c +++ b/sound/firewire/bebob/bebob_yamaha.c @@ -29,13 +29,27 @@ */
static const char *const clk_src_labels[] = {SND_BEBOB_CLOCK_INTERNAL, "SPDIF"}; +static enum snd_bebob_clock_type clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ +}; static int clk_src_get(struct snd_bebob *bebob, unsigned int *id) { - return avc_audio_get_selector(bebob->unit, 0, 4, id); + int err; + + err = avc_audio_get_selector(bebob->unit, 0, 4, id); + if (err < 0) + return err; + + if (*id >= ARRAY_SIZE(clk_src_types)) + return -EIO; + + return 0; } static struct snd_bebob_clock_spec clock_spec = { - .num = ARRAY_SIZE(clk_src_labels), + .num = ARRAY_SIZE(clk_src_types), + .types = clk_src_types, .labels = clk_src_labels, .get = &clk_src_get, };
This commit changes function prototype and its processing. As a result, function caller can execute additional processing according to detected clock source.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 4 ++-- sound/firewire/bebob/bebob_pcm.c | 11 ++++++++--- sound/firewire/bebob/bebob_proc.c | 22 ++++++++++++---------- sound/firewire/bebob/bebob_stream.c | 27 +++++++++++---------------- 4 files changed, 33 insertions(+), 31 deletions(-)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 368b62d..73317d8 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -212,8 +212,8 @@ int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, /* for AMDTP streaming */ int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate); int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate); -int snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, - bool *internal); +int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, + enum snd_bebob_clock_type *src); int snd_bebob_stream_discover(struct snd_bebob *bebob); int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 4a55561..e3f65a0 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -157,7 +157,7 @@ pcm_open(struct snd_pcm_substream *substream) struct snd_bebob *bebob = substream->private_data; struct snd_bebob_rate_spec *spec = bebob->spec->rate; unsigned int sampling_rate; - bool internal; + enum snd_bebob_clock_type src; int err;
err = snd_bebob_stream_lock_try(bebob); @@ -168,15 +168,20 @@ pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked;
- err = snd_bebob_stream_check_internal_clock(bebob, &internal); + err = snd_bebob_stream_get_clock_src(bebob, &src); if (err < 0) goto err_locked; + /* SYT-Match is not supported. */ + if (src == SND_BEBOB_CLOCK_TYPE_SYT) { + err = -EBUSY; + goto err_locked; + }
/* * When source of clock is internal or any PCM stream are running, * the available sampling rate is limited at current sampling rate. */ - if (!internal || + if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || amdtp_stream_pcm_running(&bebob->tx_stream) || amdtp_stream_pcm_running(&bebob->rx_stream)) { err = spec->get(bebob, &sampling_rate); diff --git a/sound/firewire/bebob/bebob_proc.c b/sound/firewire/bebob/bebob_proc.c index 335da64..301cc6a 100644 --- a/sound/firewire/bebob/bebob_proc.c +++ b/sound/firewire/bebob/bebob_proc.c @@ -132,25 +132,27 @@ static void proc_read_clock(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { + static const char *const clk_labels[] = { + "Internal", + "External", + "SYT-Match", + }; struct snd_bebob *bebob = entry->private_data; struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; - unsigned int rate, id; - bool internal; + enum snd_bebob_clock_type src; + unsigned int rate;
if (rate_spec->get(bebob, &rate) >= 0) snd_iprintf(buffer, "Sampling rate: %d\n", rate);
- if (clk_spec) { - if (clk_spec->get(bebob, &id) >= 0) + if (snd_bebob_stream_get_clock_src(bebob, &src) >= 0) { + if (clk_spec) snd_iprintf(buffer, "Clock Source: %s\n", - clk_spec->labels[id]); - } else { - if (snd_bebob_stream_check_internal_clock(bebob, - &internal) >= 0) + clk_labels[src]); + else snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", - (internal) ? "Internal" : "External", - bebob->sync_input_plug); + clk_labels[src], bebob->sync_input_plug); } }
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 2ccef4ce..c8af8ff 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -116,8 +116,8 @@ end: return err; }
-int -snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) +int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, + enum snd_bebob_clock_type *src) { struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; @@ -125,8 +125,6 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) enum avc_bridgeco_plug_type type; int err = 0;
- *internal = false; - /* 1.The device has its own operation to switch source of clock */ if (clk_spec) { err = clk_spec->get(bebob, &id); @@ -144,10 +142,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) goto end; }
- if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, - strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) - *internal = true; - + *src = clk_spec->types[id]; goto end; }
@@ -156,7 +151,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * to use internal clock always */ if (bebob->sync_input_plug < 0) { - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; }
@@ -179,7 +174,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * Here check the first field. This field is used for direction. */ if (input[0] == 0xff) { - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; }
@@ -192,7 +187,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) */ if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && input[2] == 0x0c) { - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; } /* The source from any input units is for several purposes. */ @@ -206,7 +201,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * short, this driver is the master of * synchronization. */ - err = -EIO; + *src = SND_BEBOB_CLOCK_TYPE_SYT; goto end; } else { /* @@ -214,7 +209,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * means that the synchronization stream is not * the Audio/MIDI compound stream. */ - *internal = false; + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; goto end; } } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { @@ -233,18 +228,18 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * SPDIF/ADAT or sometimes (not always) word * clock. */ - *internal = false; + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; goto end; } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { /* Often word clock. */ - *internal = false; + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; goto end; } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { /* * Not standard. * Mostly, additional internal clock. */ - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; } }
The old string literals were completely replaced by new normalized representation.
This commit obsoletes it.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 1 - sound/firewire/bebob/bebob_focusrite.c | 12 ------------ sound/firewire/bebob/bebob_maudio.c | 10 ++++++---- sound/firewire/bebob/bebob_terratec.c | 8 -------- sound/firewire/bebob/bebob_yamaha.c | 2 -- 5 files changed, 6 insertions(+), 27 deletions(-)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 73317d8..11362b3 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -49,7 +49,6 @@ struct snd_bebob_stream_formation { extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES];
/* device specific operations */ -#define SND_BEBOB_CLOCK_INTERNAL "Internal" enum snd_bebob_clock_type { SND_BEBOB_CLOCK_TYPE_INTERNAL = 0, SND_BEBOB_CLOCK_TYPE_EXTERNAL, diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c index 45c8f76..a1a3949 100644 --- a/sound/firewire/bebob/bebob_focusrite.c +++ b/sound/firewire/bebob/bebob_focusrite.c @@ -103,17 +103,11 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) &data, sizeof(__be32), 0); }
-static const char *const saffirepro_10_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" -}; static enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ }; -static const char *const saffirepro_26_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" -}; static enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ @@ -207,9 +201,6 @@ end: }
struct snd_bebob_spec saffire_le_spec; -static const char *const saffire_both_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" -}; static enum snd_bebob_clock_type saffire_both_clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, @@ -276,7 +267,6 @@ static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { /* Saffire Pro 26 I/O */ static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { .num = ARRAY_SIZE(saffirepro_26_clk_src_types), - .labels = saffirepro_26_clk_src_labels, .types = saffirepro_26_clk_src_types, .get = &saffirepro_both_clk_src_get, }; @@ -288,7 +278,6 @@ struct snd_bebob_spec saffirepro_26_spec = { /* Saffire Pro 10 I/O */ static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { .num = ARRAY_SIZE(saffirepro_10_clk_src_types), - .labels = saffirepro_10_clk_src_labels, .types = saffirepro_10_clk_src_types, .get = &saffirepro_both_clk_src_get, }; @@ -304,7 +293,6 @@ static struct snd_bebob_rate_spec saffire_both_rate_spec = { }; static struct snd_bebob_clock_spec saffire_both_clk_spec = { .num = ARRAY_SIZE(saffire_both_clk_src_types), - .labels = saffire_both_clk_src_labels, .types = saffire_both_clk_src_types, .get = &saffire_both_clk_src_get, }; diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 7a43afc..057495d 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -340,9 +340,6 @@ end: }
/* Clock source control for special firmware */ -static const char *const special_clk_labels[] = { - SND_BEBOB_CLOCK_INTERNAL " with Digital Mute", "Digital", - "Word Clock", SND_BEBOB_CLOCK_INTERNAL}; static enum snd_bebob_clock_type special_clk_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, /* With digital mute */ SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* SPDIF/ADAT */ @@ -358,6 +355,12 @@ static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) static int special_clk_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *einf) { + static const char *const special_clk_labels[] = { + "Internal with Digital Mute", + "Digital", + "Word Clock", + "Internal" + }; return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_types), special_clk_labels); } @@ -715,7 +718,6 @@ static struct snd_bebob_rate_spec special_rate_spec = { }; static struct snd_bebob_clock_spec special_clk_spec = { .num = ARRAY_SIZE(special_clk_types), - .labels = special_clk_labels, .types = special_clk_types, .get = &special_clk_get, }; diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c index 3b64d8d..9242e33 100644 --- a/sound/firewire/bebob/bebob_terratec.c +++ b/sound/firewire/bebob/bebob_terratec.c @@ -8,9 +8,6 @@
#include "./bebob.h"
-static const char *const phase88_rack_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock" -}; static enum snd_bebob_clock_type phase88_rack_clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ @@ -39,9 +36,6 @@ end: return err; }
-static const char *const phase24_series_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "Digital In" -}; static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ @@ -69,7 +63,6 @@ static struct snd_bebob_rate_spec phase_series_rate_spec = { /* PHASE 88 Rack FW */ static struct snd_bebob_clock_spec phase88_rack_clk = { .num = ARRAY_SIZE(phase88_rack_clk_src_types), - .labels = phase88_rack_clk_src_labels, .types = phase88_rack_clk_src_types, .get = &phase88_rack_clk_src_get, }; @@ -82,7 +75,6 @@ struct snd_bebob_spec phase88_rack_spec = { /* 'PHASE 24 FW' and 'PHASE X24 FW' */ static struct snd_bebob_clock_spec phase24_series_clk = { .num = ARRAY_SIZE(phase24_series_clk_src_types), - .labels = phase24_series_clk_src_labels, .types = phase24_series_clk_src_types, .get = &phase24_series_clk_src_get, }; diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c index 2f59512..5810170 100644 --- a/sound/firewire/bebob/bebob_yamaha.c +++ b/sound/firewire/bebob/bebob_yamaha.c @@ -28,7 +28,6 @@ * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. */
-static const char *const clk_src_labels[] = {SND_BEBOB_CLOCK_INTERNAL, "SPDIF"}; static enum snd_bebob_clock_type clk_src_types[] = { SND_BEBOB_CLOCK_TYPE_INTERNAL, SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ @@ -50,7 +49,6 @@ clk_src_get(struct snd_bebob *bebob, unsigned int *id) static struct snd_bebob_clock_spec clock_spec = { .num = ARRAY_SIZE(clk_src_types), .types = clk_src_types, - .labels = clk_src_labels, .get = &clk_src_get, }; static struct snd_bebob_rate_spec rate_spec = {
In previous commits, this driver can detect the source of clock as mush as possible. SYT-Match mode is also available.
This commit purge the restriction.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_pcm.c | 5 ----- sound/firewire/bebob/bebob_stream.c | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index e3f65a0..e0a6b06 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -171,11 +171,6 @@ pcm_open(struct snd_pcm_substream *substream) err = snd_bebob_stream_get_clock_src(bebob, &src); if (err < 0) goto err_locked; - /* SYT-Match is not supported. */ - if (src == SND_BEBOB_CLOCK_TYPE_SYT) { - err = -EBUSY; - goto err_locked; - }
/* * When source of clock is internal or any PCM stream are running, diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index c8af8ff..5335c30 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -474,8 +474,24 @@ destroy_both_connections(struct snd_bebob *bebob) static int get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) { - /* currently this module doesn't support SYT-Match mode */ - *sync_mode = CIP_SYNC_TO_DEVICE; + enum snd_bebob_clock_type src; + int err; + + err = snd_bebob_stream_get_clock_src(bebob, &src); + if (err < 0) + return err; + + switch (src) { + case SND_BEBOB_CLOCK_TYPE_INTERNAL: + case SND_BEBOB_CLOCK_TYPE_EXTERNAL: + *sync_mode = CIP_SYNC_TO_DEVICE; + break; + default: + case SND_BEBOB_CLOCK_TYPE_SYT: + *sync_mode = 0; + break; + } + return 0; }
BeBoB installed devices have BeBoB register area. This area stores basic information about its firmware. A register has its protocol version.
This commit adds 'version' member and store the device's protocol version to handle v3 quirks in following commits.
Tested-by: Kim Tore Jensen kim@incendio.no Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.c | 8 ++++++++ sound/firewire/bebob/bebob.h | 3 +++ 2 files changed, 11 insertions(+)
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index e71bd35..920571b 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -33,6 +33,7 @@ static DEFINE_MUTEX(devices_mutex); static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
/* Offsets from information register. */ +#define INFO_OFFSET_BEBOB_VERSION 0x08 #define INFO_OFFSET_GUID 0x10 #define INFO_OFFSET_HW_MODEL_ID 0x18 #define INFO_OFFSET_HW_MODEL_REVISION 0x1c @@ -73,6 +74,7 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) u32 hw_id; u32 data[2] = {0}; u32 revision; + u32 version; int err;
/* get vendor name from root directory */ @@ -105,6 +107,12 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) if (err < 0) goto end;
+ err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_BEBOB_VERSION, + &version); + if (err < 0) + goto end; + bebob->version = version; + strcpy(bebob->card->driver, "BeBoB"); strcpy(bebob->card->shortname, model); strcpy(bebob->card->mixername, model); diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 11362b3..1520854 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -115,6 +115,9 @@ struct snd_bebob { /* for M-Audio special devices */ void *maudio_special_quirk; bool deferred_registration; + + /* For BeBoB version quirk. */ + unsigned int version; };
static inline int
Behringer FCA610 and UFX1604 is confirmed to require more time till transmitting packets after establishing connections. This seems to be a quirk of DM1500 ASIC which ArchWave produced.
For this quirk, this commit extends the time to wait up to 2 seconds. As a result, in worst cases, below userspace functions require 2 seconds to return. - snd_pcm_prepare() - snd_pcm_hw_params() - snd_pcm_recover()
Tested-by: Kim Tore Jensen kim@incendio.no Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 5335c30..9c810f9 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -8,7 +8,7 @@
#include "./bebob.h"
-#define CALLBACK_TIMEOUT 1000 +#define CALLBACK_TIMEOUT 2000 #define FW_ISO_RESOURCE_DELAY 1000
/*
PrismSound Orpheus, Behringer UFX1604 and FCA610 work with BeBoB v3, and they're confirmed to transmit discontinuous packets in the beginning of streaming.
payload CIP headers 8 0x00070000 0x9002FFFF 8 0x00070000 0x9002FFFF 8 0x00070000 0x9002FFFF 8 0x00070008 0x9002FFFF <- 8 0x00070008 0x9002FFFF 8 0x00070008 0x9002FFFF 8 0x00070008 0x9002FFFF 8 0x00070008 0x9002FFFF 8 0x00070008 0x9002FFFF 232 0x00070000 0x9002E798 <- 232 0x00070008 0x9002FB99 232 0x00070010 0x90021398 8 0x00070018 0x9002FFFF (This sample was got with Behringer FCA610 and FFADO library.)
This commit sets CIP_EMPTY_HAS_WRONG_DBC and CIP_SKIP_DBC_ZERO_CHECK to ignore these discontinuities.
Tested-by: Kim Tore Jensen kim@incendio.no Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 9c810f9..d0df6c1 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -540,6 +540,17 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) /* See comments in next function */ init_completion(&bebob->bus_reset); bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; + + /* + * BeBoB v3 transfers packets with these qurks: + * - In the beginning of streaming, the value of dbc is incremented + * even if no data blocks are transferred. + * - The value of dbc is reset suddenly. + */ + if (bebob->version > 2) + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | + CIP_SKIP_DBC_ZERO_CHECK; + /* * At high sampling rate, M-Audio special firmware transmits empty * packet with the value of dbc incremented by 8 but the others are
Behringer FCA610 transmits packets with periodic noisy PCM samples when receiving no streams, and generates a bit noisy sound.
ALSA BeBoB driver is programmed to establish both in/out connections when starting streaming, then transfers packets as userspace applications requested. This means that there's a case that one of incoming/outgoing streams is running, to save CPU and bandwidth usage. Although, it's natural to start transferring packets in both direction.
This commit makes this driver to keeps duplex streams always.
Tested-by: Kim Tore Jensen kim@incendio.no Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 3 +-- sound/firewire/bebob/bebob_midi.c | 8 ++++---- sound/firewire/bebob/bebob_pcm.c | 8 ++++---- sound/firewire/bebob/bebob_stream.c | 24 +++++++----------------- 4 files changed, 16 insertions(+), 27 deletions(-)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 1520854..d23caca 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -97,8 +97,7 @@ struct snd_bebob { struct amdtp_stream rx_stream; struct cmp_connection out_conn; struct cmp_connection in_conn; - atomic_t capture_substreams; - atomic_t playback_substreams; + atomic_t substreams_counter;
struct snd_bebob_stream_formation tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index 63343d5..5681143 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end;
- atomic_inc(&bebob->capture_substreams); + atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); if (err < 0) snd_bebob_stream_lock_release(bebob); @@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end;
- atomic_inc(&bebob->playback_substreams); + atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); if (err < 0) snd_bebob_stream_lock_release(bebob); @@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data;
- atomic_dec(&bebob->capture_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob); @@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data;
- atomic_dec(&bebob->playback_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob); diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index e0a6b06..7a2c1f5 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -213,7 +213,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&bebob->capture_substreams); + atomic_inc(&bebob->substreams_counter); amdtp_stream_set_pcm_format(&bebob->tx_stream, params_format(hw_params)); return snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -226,7 +226,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&bebob->playback_substreams); + atomic_inc(&bebob->substreams_counter); amdtp_stream_set_pcm_format(&bebob->rx_stream, params_format(hw_params)); return snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -239,7 +239,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream) struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&bebob->capture_substreams); + atomic_dec(&bebob->substreams_counter);
snd_bebob_stream_stop_duplex(bebob);
@@ -251,7 +251,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream) struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&bebob->playback_substreams); + atomic_dec(&bebob->substreams_counter);
snd_bebob_stream_stop_duplex(bebob);
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index d0df6c1..5be5242 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -574,7 +574,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) { struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; struct amdtp_stream *master, *slave; - atomic_t *slave_substreams; enum cip_flags sync_mode; unsigned int curr_rate; bool updated = false; @@ -599,8 +598,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) mutex_lock(&bebob->mutex);
/* Need no substreams */ - if (atomic_read(&bebob->playback_substreams) == 0 && - atomic_read(&bebob->capture_substreams) == 0) + if (atomic_read(&bebob->substreams_counter) == 0) goto end;
err = get_sync_mode(bebob, &sync_mode); @@ -609,11 +607,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) if (sync_mode == CIP_SYNC_TO_DEVICE) { master = &bebob->tx_stream; slave = &bebob->rx_stream; - slave_substreams = &bebob->playback_substreams; } else { master = &bebob->rx_stream; slave = &bebob->tx_stream; - slave_substreams = &bebob->capture_substreams; }
/* @@ -714,7 +710,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) }
/* start slave if needed */ - if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { + if (!amdtp_stream_running(slave)) { err = start_stream(bebob, slave, rate); if (err < 0) { dev_err(&bebob->unit->device, @@ -740,31 +736,25 @@ end: void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) { struct amdtp_stream *master, *slave; - atomic_t *master_substreams, *slave_substreams;
if (bebob->master == &bebob->rx_stream) { slave = &bebob->tx_stream; master = &bebob->rx_stream; - slave_substreams = &bebob->capture_substreams; - master_substreams = &bebob->playback_substreams; } else { slave = &bebob->rx_stream; master = &bebob->tx_stream; - slave_substreams = &bebob->playback_substreams; - master_substreams = &bebob->capture_substreams; }
mutex_lock(&bebob->mutex);
- if (atomic_read(slave_substreams) == 0) { + if (atomic_read(&bebob->substreams_counter) == 0) { + amdtp_stream_pcm_abort(master); + amdtp_stream_stop(master); + amdtp_stream_pcm_abort(slave); amdtp_stream_stop(slave);
- if (atomic_read(master_substreams) == 0) { - amdtp_stream_pcm_abort(master); - amdtp_stream_stop(master); - break_both_connections(bebob); - } + break_both_connections(bebob); }
mutex_unlock(&bebob->mutex);
They're based on DM1500 (ArchWave produced), and BeBoB version 3 is installed.
$ cat /proc/asound/FCA610/firewire/firmware Manufacturer: bridgeCo Protocol Ver: 3 Build Ver: 0 GUID: 0x001564000002AD73 Model ID: 0x03 Model Rev: 0 Firmware Date: 20121102 Firmware Time: 153431 Firmware ID: 0x610 Firmware Ver: 8348 Base Addr: 0x400C0080 Max Size: 1422624 Loader Date: 20121015 Loader Time: 104710
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/Kconfig | 1 + sound/firewire/bebob/bebob.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 2a0a9aa..8850b7d 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -95,6 +95,7 @@ config SND_BEBOB * Tascam IF-FW/DM * Behringer XENIX UFX 1204/1604 * Behringer Digital Mixer X32 series (X-UF Card) + * Behringer FCA610/1616 * Apogee Rosetta 200/400 (X-FireWire card) * Apogee DA/AD/DD-16X (X-FireWire card) * Apogee Ensemble diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 920571b..27a04ac 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -373,6 +373,10 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), /* Behringer, Digital Mixer X32 series (X-UF Card) */ SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), + /* Behringer, F-Control Audio 1616 */ + SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x001616, &spec_normal), + /* Behringer, F-Control Audio 610 */ + SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x000610, &spec_normal), /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), @@ -447,8 +451,6 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* IDs are unknown but able to be supported */ /* Apogee, Mini-ME Firewire */ /* Apogee, Mini-DAC Firewire */ - /* Behringer, F-Control Audio 1616 */ - /* Behringer, F-Control Audio 610 */ /* Cakawalk, Sonar Power Studio 66 */ /* CME, UF400e */ /* ESI, Quotafire XL */
At Sun, 14 Jun 2015 12:49:26 +0900, Takashi Sakamoto wrote:
Hi,
This patchset updates my previous one.
[alsa-devel] [RFC][PATCH 00/11] improve support for DM1500/BeBoBv3 http://mailman.alsa-project.org/pipermail/alsa-devel/2015-June/093320.html
Changes since the RFC:
- re-gain missing enumerator member
- update commit comments
I hope them to be merged into upstream.
Applied all patches. Thanks.
Takashi
Takashi Sakamoto (11): ALSA: bebob: improve signal mode detection for clock source ALSA: bebob: apply new enumerator to normalize the type of clock source ALSA: bebob: preparation for replacing string literals by normalized representation for model-dependent structures ALSA: bebob: use normalized representation for the type of clock source ALSA: bebob: obsolete string literal expression for clock source ALSA: bebob: add SYT-Match support ALSA: bebob: add 'version' member for BeBoB protocol version ALSA: bebob: expand timeout for DM1500 quirk ALSA: bebob: loosen up severity of checking continuity for BeBoB v3 quirk ALSA: bebob: keep duplex streams always to keep internal multiplexer properly ALSA: bebob: add support for Behringer FCA 610/1616
sound/firewire/Kconfig | 1 + sound/firewire/bebob/bebob.c | 14 ++- sound/firewire/bebob/bebob.h | 20 +++-- sound/firewire/bebob/bebob_focusrite.c | 33 +++++--- sound/firewire/bebob/bebob_maudio.c | 23 +++-- sound/firewire/bebob/bebob_midi.c | 8 +- sound/firewire/bebob/bebob_pcm.c | 14 +-- sound/firewire/bebob/bebob_proc.c | 22 ++--- sound/firewire/bebob/bebob_stream.c | 150 ++++++++++++++++++++++++--------- sound/firewire/bebob/bebob_terratec.c | 30 +++++-- sound/firewire/bebob/bebob_yamaha.c | 20 ++++- 11 files changed, 235 insertions(+), 100 deletions(-)
-- 2.1.4
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto