Commit 5a668812 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

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: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 88f1236b
......@@ -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],
......
......@@ -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;
}
/* 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) {
/*
* If source of clock is internal CSR, Music Sub Unit Sync Input is
* a destination of Music Sub Unit Sync Output.
* Not standard.
* Mostly, additional internal clock.
*/
*internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) &&
(input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) &&
(input[2] == 0x0c) &&
(input[3] == 0x00));
*internal = true;
goto end;
}
}
}
/* Not supported. */
err = -EIO;
end:
return err;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment