From 146a5e3c1ef999f1b1ec841fd86db421f4ca8d6a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 24 May 2015 20:51:45 +0900 Subject: ALSA: bebob: add Digidesign Mbox 2 Pro support This device is based on DM1000E, and BeBoB version 1 firmware is installed. $ cat /proc/asound/cards 0 [Pro ]: BeBoB - Mbox 2 Pro DIGIDESIGN Mbox 2 Pro (id:1, rev:1), GUID 00a07e0100a90000 at fw1.0, S400 $ cat /proc/asound/Pro/firewire/firmware Manufacturer: bridgeCo Protocol Ver: 1 Build Ver: 0 GUID: 0x00A07E0100A90000 Model ID: 0x01 Model Rev: 1 Firmware Date: 20071031 Firmware Time: 034402 Firmware ID: 0xA9 Firmware Ver: 16777215 Base Addr: 0x20080000 Max Size: 1572864 Loader Date: 20051207 Loader Time: 205554 With this patch, ALSA BeBoB driver can start packet streaming to/from this model, while as a default, internal multiplexer of this model is not initialized and generates no sound even if the driver transfers any packets with PCM samples. To hear any sounds from this model, userspace applications should be developed to set parameters to the internal multiplexer. You can see raw information in FFADO website: http://subversion.ffado.org/wiki/AvcModels/DigiDesignMboxPro2 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 611b7dae7ee5..e71bd353f4e7 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -57,6 +57,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_FOCUSRITE 0x0000130e #define VEN_MAUDIO1 0x00000d6c #define VEN_MAUDIO2 0x000007f5 +#define VEN_DIGIDESIGN 0x00a07e #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 @@ -433,6 +434,8 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* M-Audio ProjectMix */ SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, &maudio_special_spec), + /* Digidesign Mbox 2 Pro */ + SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), /* IDs are unknown but able to be supported */ /* Apogee, Mini-ME Firewire */ /* Apogee, Mini-DAC Firewire */ -- cgit v1.2.3-70-g09d2 From 5a6688127082683f8c343da7d326dc22e45f4e4b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:27 +0900 Subject: ALSA: bebob: improve signal mode detection for clock source 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 Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.h | 3 +- sound/firewire/bebob/bebob_stream.c | 78 +++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 9 deletions(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index dfbcd233178c..2a918caa88a1 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 98e4fc8121a1..2ccef4ce050d 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; } -- cgit v1.2.3-70-g09d2 From 13a4f42016fecbf971c3f6e249027a009a83839f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:28 +0900 Subject: ALSA: bebob: apply new enumerator to normalize the type of clock source 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 Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 2a918caa88a1..368b62dea252 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 { -- cgit v1.2.3-70-g09d2 From ba5177131d8cb4b778a43ce995155928be851117 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:29 +0900 Subject: ALSA: bebob: preparation for replacing string literals by normalized representation for model-dependent structures 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 Signed-off-by: Takashi Iwai --- 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(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c index fc67c1b7cb5b..45c8f76d8187 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 9ee25a63f684..7a43afcfa9bd 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 ad635004d699..3b64d8db8e14 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 ef1fe3823a9c..2f59512ad91e 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, }; -- cgit v1.2.3-70-g09d2 From 3e254b16b65dbbcc2528781070e1be0f7945f220 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:30 +0900 Subject: ALSA: bebob: use normalized representation for the type of clock source 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 Signed-off-by: Takashi Iwai --- 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(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 368b62dea252..73317d88cc80 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 4a55561ed4ec..e3f65a0698c7 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 335da64506e0..301cc6a93945 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 2ccef4ce050d..c8af8ffe2d53 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; } } -- cgit v1.2.3-70-g09d2 From 554d8983a07d853bc4761c575db2f1bbb2f14372 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:31 +0900 Subject: ALSA: bebob: obsolete string literal expression for clock source The old string literals were completely replaced by new normalized representation. This commit obsoletes it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- 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(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 73317d88cc80..11362b30ee5b 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 45c8f76d8187..a1a39494ea6c 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 7a43afcfa9bd..057495d54ab0 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 3b64d8db8e14..9242e33d2cf1 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 2f59512ad91e..58101702410b 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 = { -- cgit v1.2.3-70-g09d2 From 05773792716e5a75b0f4bf4edcdc1e9c3b199ab8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:32 +0900 Subject: ALSA: bebob: add SYT-Match support 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 Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_pcm.c | 5 ----- sound/firewire/bebob/bebob_stream.c | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index e3f65a0698c7..e0a6b065952f 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 c8af8ffe2d53..5335c300728c 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; } -- cgit v1.2.3-70-g09d2 From 7b4d7dcfa89e75f69547fbacfbf09a1d6c242a6b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:33 +0900 Subject: ALSA: bebob: add 'version' member for BeBoB protocol version 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 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.c | 8 ++++++++ sound/firewire/bebob/bebob.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index e71bd353f4e7..920571bc3c60 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 11362b30ee5b..1520854b76d7 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 -- cgit v1.2.3-70-g09d2 From 9a73195e614bf01722331c820c260b9cb77e634e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:34 +0900 Subject: ALSA: bebob: expand timeout for DM1500 quirk 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 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 5335c300728c..9c810f9ec8d6 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 /* -- cgit v1.2.3-70-g09d2 From c4d860a0d256663937b51468ea13de3c2cd2a09d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:35 +0900 Subject: ALSA: bebob: loosen up severity of checking continuity for BeBoB v3 quirk 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 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 9c810f9ec8d6..d0df6c17f7f7 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 -- cgit v1.2.3-70-g09d2 From 8d1c2694e45bd5a1b7e79734952e8dfb6f2974a6 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:36 +0900 Subject: ALSA: bebob: keep duplex streams always to keep internal multiplexer properly 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 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- 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(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 1520854b76d7..d23caca7f369 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 63343d578df3..5681143925cd 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 e0a6b065952f..7a2c1f53bc44 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 d0df6c17f7f7..5be5242e1ed8 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); -- cgit v1.2.3-70-g09d2 From cf8a471909dd6a0df3efe2586cab5323184b4a7d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 14 Jun 2015 12:49:37 +0900 Subject: ALSA: bebob: add support for Behringer FCA 610/1616 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 Signed-off-by: Takashi Iwai --- sound/firewire/Kconfig | 1 + sound/firewire/bebob/bebob.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'sound/firewire/bebob') diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 2a0a9aa3518f..8850b7de1d38 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 920571bc3c60..27a04ac8ffee 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 */ -- cgit v1.2.3-70-g09d2