diff mbox

[01/11] ALSA: bebob: improve signal mode detection for clock source

Message ID 1433773868-17505-2-git-send-email-o-takashi@sakamocchi.jp (mailing list archive)
State Superseded
Delegated to: Takashi Iwai
Headers show

Commit Message

Takashi Sakamoto June 8, 2015, 2:30 p.m. UTC
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 mbox

Patch

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;
 }