On Thursday 22 April 2010 20:57:54 ext Liam Girdwood wrote:
+#define SAMPLES_TO_US(rate, samples) \
- (1000000000 / ((rate * 1000) / samples))
+#define US_TO_SAMPLES(rate, ns) \
- (rate / (1000000 / ns))
Is it microseconds or nanoseconds here (us or ns) ?
It is microseconds (us). I have initially used nanoseconds, but it was a bit overkill, and using usec gives close enough resolution. I'll change the ns to us in the macro.
+static snd_pcm_sframes_t dac33_dai_delay(
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
+{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
- struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
- unsigned long long t0, t1, t_now;
- unsigned int time_delta;
- int samples_out, samples_in, samples;
- snd_pcm_sframes_t delay = 0;
- switch (dac33->fifo_mode) {
- case DAC33_FIFO_BYPASS:
break;
- case DAC33_FIFO_MODE1:
spin_lock(&dac33->lock);
t0 = dac33->t_stamp1;
t1 = dac33->t_stamp2;
spin_unlock(&dac33->lock);
t_now = ktime_to_us(ktime_get());
/* We have not started to fill the FIFO yet, delay is 0 */
if (!t1)
goto out;
We may need some logic here to handle any underruns (e.g. recalc our delay based on underrun), as ALSA will re-call prepare() and there may still be data playing through the DAC33 FIFO.
I guess we anyway have the problem with the stopping. Trigger:stop can come anytime, and we supposed to stop even if the FIFO is almost full. What happens now, is that I only set the codec to FLUSH mode, which will allow us to play the remaining samples out, but the codec will not ask for new samples. The codec than will be stopped at set_bias:STANDBY, so we will eventually play out everything.
What this timestamping will allow us to do is to detect the underrun situation inside of the codec, and try to recover from it. If underrun happens, than the codec will not ask for new data (the alarm interrupt will not re-trigger). This breaks the playback. In this case we have to go back to prefill state, and that should solve the problem, but I have not analyzed the pattern, which leads to deadlock (but I have seen it several times).
Have you tried forcing underruns to see how it behaves ?
No I have not forced it, but it happened few times, especially when there were heavy traffic on the I2C bus. What happens is that I actually reset the codec in pcm_prepare, so we do loose some samples for sure.
When the codec is in mode1, the interrupts (and the nSample writes) are not in a constant distance, over time the delays are compensated by this movement of the burst starts. Overnight playback tests resulted no underruns so far.
Liam