[alsa-devel] [PATCH 5/5] ASoC: tlv320dac33: FIFO caused delay reporting

Peter Ujfalusi peter.ujfalusi at nokia.com
Fri Apr 23 07:52:32 CEST 2010


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

-- 
Péter


More information about the Alsa-devel mailing list