[alsa-devel] [PATCH 1/2] ALSA: hda - Add fixed codec delay to runtime delay.

Takashi Iwai tiwai at suse.de
Fri Apr 5 07:39:44 CEST 2013


At Thu, 4 Apr 2013 09:21:34 -0700,
Dylan Reid wrote:
> 
> On Thu, Apr 4, 2013 at 12:10 AM, Takashi Iwai <tiwai at suse.de> wrote:
> > At Wed,  3 Apr 2013 08:30:03 -0700,
> > Dylan Reid wrote:
> >>
> >> Allow a codec to specify a delay in addition to the delay before
> >> samples are passed through DMA.  Some codecs have large processing
> >> delays because of built-in DSPs that require codec-side buffers of
> >> many milliseconds.  Default to zero delay if the codec doesn't specify
> >> a callback to get the processing delay.
> >>
> >> Signed-off-by: Dylan Reid <dgreid at chromium.org>
> >> ---
> >>  sound/pci/hda/hda_codec.c | 17 +++++++++++++++++
> >>  sound/pci/hda/hda_codec.h |  4 ++++
> >>  sound/pci/hda/hda_intel.c |  2 ++
> >>  3 files changed, 23 insertions(+)
> >>
> >> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> >> index 17286b3..1d792dd 100644
> >> --- a/sound/pci/hda/hda_codec.c
> >> +++ b/sound/pci/hda/hda_codec.c
> >> @@ -3724,6 +3724,23 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
> >>  }
> >>  EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
> >>
> >> +/**
> >> + * snd_hda_codec_processing_delay - get the fixed delay through the codec
> >> + * @codec: HD-audio codec
> >> + * @stream: playback or capture
> >> + *
> >> + * This is needed for codecs that contain DSPs that cause long delays.
> >> + */
> >> +unsigned int snd_hda_codec_processing_delay(struct hda_codec *codec,
> >> +                                         unsigned int stream)
> >> +{
> >> +     if (codec->patch_ops.get_processing_delay)
> >> +             return codec->patch_ops.get_processing_delay(codec, stream);
> >> +
> >> +     return 0;
> >> +}
> >> +EXPORT_SYMBOL_HDA(snd_hda_codec_processing_delay);
> >
> > In the second thought, it would fit more better to pcm_ops than codec
> > patch_ops.  That is, the change would be like below.
> 
> Yes this looks better.  I'll modify the subsequent patch and run our
> latency tests on it to make sure it works then resend based on this.

I found a missing substream->runtime check (the function may be called
even without running the PCM).  The revised patch below was committed
to for-next branch in the end.


thanks,

Takashi

---
From: Takashi Iwai <tiwai at suse.de>
Subject: [PATCH] ALSA: hda - Introduce get_delay codec PCM ops

Add a new codec PCM ops, get_delay(), to obtain the codec/stream-
specific PCM delay count.  When it's NULL, nothing changes.

This new feature was requested for CA0132, which has significant
delays in the path depending on the running DSP code.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 sound/pci/hda/hda_codec.h |  3 +++
 sound/pci/hda/hda_intel.c | 18 ++++++++++++++----
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 23ca172..c93f902 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -757,6 +757,9 @@ struct hda_pcm_ops {
 		       struct snd_pcm_substream *substream);
 	int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
 		       struct snd_pcm_substream *substream);
+	unsigned int (*get_delay)(struct hda_pcm_stream *info,
+				  struct hda_codec *codec,
+				  struct snd_pcm_substream *substream);
 };
 
 /* PCM information for each substream */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 418bfc0..735567e 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2349,8 +2349,11 @@ static unsigned int azx_get_position(struct azx *chip,
 				     struct azx_dev *azx_dev,
 				     bool with_check)
 {
+	struct snd_pcm_substream *substream = azx_dev->substream;
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	unsigned int pos;
-	int stream = azx_dev->substream->stream;
+	int stream = substream->stream;
+	struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
 	int delay = 0;
 
 	switch (chip->position_fix[stream]) {
@@ -2381,7 +2384,7 @@ static unsigned int azx_get_position(struct azx *chip,
 		pos = 0;
 
 	/* calculate runtime delay from LPIB */
-	if (azx_dev->substream->runtime &&
+	if (substream->runtime &&
 	    chip->position_fix[stream] == POS_FIX_POSBUF &&
 	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
 		unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
@@ -2399,9 +2402,16 @@ static unsigned int azx_get_position(struct azx *chip,
 			delay = 0;
 			chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
 		}
-		azx_dev->substream->runtime->delay =
-			bytes_to_frames(azx_dev->substream->runtime, delay);
+		delay = bytes_to_frames(substream->runtime, delay);
 	}
+
+	if (substream->runtime) {
+		if (hinfo->ops.get_delay)
+			delay += hinfo->ops.get_delay(hinfo, apcm->codec,
+						      substream);
+		substream->runtime->delay = delay;
+	}
+
 	trace_azx_get_position(chip, azx_dev, pos, delay);
 	return pos;
 }
-- 
1.8.1.4



More information about the Alsa-devel mailing list