ALSA: hda - Introduce get_delay codec PCM ops
authorTakashi Iwai <tiwai@suse.de>
Fri, 5 Apr 2013 05:27:45 +0000 (07:27 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 5 Apr 2013 05:33:32 +0000 (07:33 +0200)
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@suse.de>
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c

index 23ca1722aff1c169eedaf4e2b9a65c731ad349a6..c93f9021f45212d523e8928db45bcef6f65c4576 100644 (file)
@@ -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 */
index 418bfc0eb0a3127234899aa6f84586feaa19eeef..735567e86f744ff2280eba3d6f895994edf5ebce 100644 (file)
@@ -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;
 }