diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2016-02-27 15:01:21 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-28 12:56:24 +0300 |
commit | 1387e3eafa94837342b044b429b79830998009ac (patch) | |
tree | 2e3d3a6d944a97be98f07584c90212b1d5627419 | |
parent | d61b04f801e6005182d432ebe4a0211c1d6feadd (diff) | |
download | linux-1387e3eafa94837342b044b429b79830998009ac.tar.xz |
ALSA: dice: drop duplex streams synchronization to transfer own time stamps
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>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/firewire/dice/dice-stream.c | 42 |
1 files changed, 2 insertions, 40 deletions
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index a64b3cc76bf1..df035b1dd44a 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, |