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 restriction about detected internal/external clock source. When detecting external clock source, this driver don't manage to change sampling rate as userspace applications request. This is due to consider abour synchronization to external clock sources as S/PDIF, ADAT or word clock.
To judge depending on 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 like 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_stream.c | 78 +++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 8 deletions(-)
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; }