Merge branch 'for-2.6.34' of git://opensource.wolfsonmicro.com/linux-2.6-asoc into topic/asoc
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 5532579..d9cb984 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -35,22 +35,25 @@
 struct imx_pcm_runtime_data {
 	int period;
 	int periods;
-	unsigned long dma_addr;
-	int dma;
 	unsigned long offset;
+	unsigned long last_offset;
 	unsigned long size;
-	unsigned long period_cnt;
-	void *buf;
 	struct timer_list timer;
-	int period_time;
+	int poll_time;
 };
 
+static inline void imx_ssi_set_next_poll(struct imx_pcm_runtime_data *iprtd)
+{
+	iprtd->timer.expires = jiffies + iprtd->poll_time;
+}
+
 static void imx_ssi_timer_callback(unsigned long data)
 {
 	struct snd_pcm_substream *substream = (void *)data;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 	struct pt_regs regs;
+	unsigned long delta;
 
 	get_fiq_regs(&regs);
 
@@ -59,9 +62,25 @@
 	else
 		iprtd->offset = regs.ARM_r9 & 0xffff;
 
-	iprtd->timer.expires = jiffies + iprtd->period_time;
+	/* How much data have we transferred since the last period report? */
+	if (iprtd->offset >= iprtd->last_offset)
+		delta = iprtd->offset - iprtd->last_offset;
+	else
+		delta = runtime->buffer_size + iprtd->offset
+			- iprtd->last_offset;
+
+	/* If we've transferred at least a period then report it and
+	 * reset our poll time */
+	if (delta >= runtime->period_size) {
+		snd_pcm_period_elapsed(substream);
+		iprtd->last_offset = iprtd->offset;
+
+		imx_ssi_set_next_poll(iprtd);
+	}
+
+	/* Restart the timer; if we didn't report we'll run on the next tick */
 	add_timer(&iprtd->timer);
-	snd_pcm_period_elapsed(substream);
+
 }
 
 static struct fiq_handler fh = {
@@ -76,9 +95,10 @@
 
 	iprtd->size = params_buffer_bytes(params);
 	iprtd->periods = params_periods(params);
-	iprtd->period = params_period_bytes(params);
+	iprtd->period = params_period_bytes(params) ;
 	iprtd->offset = 0;
-	iprtd->period_time = HZ / (params_rate(params) / params_period_size(params));
+	iprtd->last_offset = 0;
+	iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params));
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
@@ -114,7 +134,7 @@
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		iprtd->timer.expires = jiffies + iprtd->period_time;
+		imx_ssi_set_next_poll(iprtd);
 		add_timer(&iprtd->timer);
 		if (++fiq_enable == 1)
 			enable_fiq(imx_pcm_fiq);