return error_ppm;
 }
 
+static inline u32 davinci_mcasp_tx_delay(struct davinci_mcasp *mcasp)
+{
+       if (!mcasp->txnumevt)
+               return 0;
+
+       return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_WFIFOSTS_OFFSET);
+}
+
+static inline u32 davinci_mcasp_rx_delay(struct davinci_mcasp *mcasp)
+{
+       if (!mcasp->rxnumevt)
+               return 0;
+
+       return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_RFIFOSTS_OFFSET);
+}
+
+static snd_pcm_sframes_t davinci_mcasp_delay(
+                       struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *cpu_dai)
+{
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 fifo_use;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               fifo_use = davinci_mcasp_tx_delay(mcasp);
+       else
+               fifo_use = davinci_mcasp_rx_delay(mcasp);
+
+       /*
+        * Divide the used locations with the channel count to get the
+        * FIFO usage in samples (don't care about partial samples in the
+        * buffer).
+        */
+       return fifo_use / substream->runtime->channels;
+}
+
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params,
                                        struct snd_soc_dai *cpu_dai)
        .startup        = davinci_mcasp_startup,
        .shutdown       = davinci_mcasp_shutdown,
        .trigger        = davinci_mcasp_trigger,
+       .delay          = davinci_mcasp_delay,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
        .set_clkdiv     = davinci_mcasp_set_clkdiv,