On Sat, 27 Feb 2016 13:01:21 +0100, Takashi Sakamoto wrote:
This commit drops implementation of duplex streams synchronization from ALSA dice driver, due to a reason of hardware design. This patch allows dice-based units to generate sounds correctly when isochronous packet streaming starts at first time.
In IEC 61883-6:2005, CIP packetization layer for AM824 data format utilizes the value of SYT field in CIP header of received packet for a reference to phase lock loop. Figure 3 in clause 4.3 describes it. The value is an offset from cycle_time field of every cycle start packet from cycle master on IEEE 1394 bus. The time calculated with these two fields is called as 'presentation timestamp' which represents the time to play data included in the packet.
Although, this idea includes some problems due to accuracy of timekeep in cycle master, accuracy of transmission of cycle start packet on the bus with the other units, accuracy of sampling clock in data transmitter side and accuracy of replay in data receiver side. In most case, these accuracies somewhat worse because there's no such ideal hardwares in this world.
For the issues, ASICs for Dice include Jitter Elimination Technologies (JET) PLL. The PLL can handle several sources of clock and compensate it with high-precision internal clock source. The sequence of value in syt field of received AMDTP packets is one of the sources, therefore transmitters on IEEE 1394 bus should transfer it.
On the other hand, current ALSA dice driver is programmed with a mode of duplex streams with synchronization. In this mode, the driver outputs packets after some incoming packets are handled, to re-use the value of SYT field in incoming packets to the value for outgoing packets. This mode is enabled when source signal of sampling clock is set to internal, and this is a major use case. Thus, in most cases, the unit receives no packets during a short time after packet streaming starts.
As long as I experienced, this causes the units to generate no sounds at first time to receive packets. This issue occurs only with Dice II. I guess this is due to a quirk of the PLL. In short, the PLL cannot generate firm signals to ADCs/DACs or the other ICs when no packets are received in the beginning of packet streaming. While, on second time or later, the unit generates sound correctly. I guess that starting packet streaming at first time sets the PLL correctly.
Well, still based on my hypothesis and no way to prove it, this commit drops duplex streams synchronization from this driver. At least, the PLL requires the sequence of value in SYT field of received AMDTP packets as one of source of clock signals with internal clock source.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp
Applied, thanks.
Takashi
sound/firewire/dice/dice-stream.c | 42 ++------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-)
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index a64b3cc..df035b1 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -191,53 +191,17 @@ end: return err; }
-static int get_sync_mode(struct snd_dice *dice, enum cip_flags *sync_mode) -{
- u32 source;
- int err;
- err = snd_dice_transaction_get_clock_source(dice, &source);
- if (err < 0)
goto end;
- switch (source) {
- /* So-called 'SYT Match' modes, sync_to_syt value of packets received */
- case CLOCK_SOURCE_ARX4: /* in 4th stream */
- case CLOCK_SOURCE_ARX3: /* in 3rd stream */
- case CLOCK_SOURCE_ARX2: /* in 2nd stream */
err = -ENOSYS;
break;
- case CLOCK_SOURCE_ARX1: /* in 1st stream, which this driver uses */
*sync_mode = 0;
break;
- default:
*sync_mode = CIP_SYNC_TO_DEVICE;
break;
- }
-end:
- return err;
-}
int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) { struct amdtp_stream *master, *slave; unsigned int curr_rate;
enum cip_flags sync_mode; int err = 0;
if (dice->substreams_counter == 0) goto end;
err = get_sync_mode(dice, &sync_mode);
if (err < 0)
goto end;
if (sync_mode == CIP_SYNC_TO_DEVICE) {
master = &dice->tx_stream;
slave = &dice->rx_stream;
} else {
master = &dice->rx_stream;
slave = &dice->tx_stream;
}
master = &dice->rx_stream;
slave = &dice->tx_stream;
/* Some packet queueing errors. */ if (amdtp_streaming_error(master) || amdtp_streaming_error(slave))
@@ -261,8 +225,6 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate) stop_stream(dice, slave); snd_dice_transaction_clear_enable(dice);
amdtp_stream_set_sync(sync_mode, master, slave);
- err = ensure_phase_lock(dice); if (err < 0) { dev_err(&dice->unit->device,
-- 2.5.0