Merge remote branch 'alsa/devel' into topic/misc
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index ee16122..8b611a5 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -271,6 +271,7 @@
 	int overrange;
 	snd_pcm_uframes_t avail_max;
 	snd_pcm_uframes_t hw_ptr_base;	/* Position at buffer restart */
+	snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
 	unsigned long hw_ptr_jiffies;	/* Time when hw_ptr is updated */
 	snd_pcm_sframes_t delay;	/* extra delay; typically FIFO size */
 
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 255ad91..82d4e33 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -635,8 +635,7 @@
 static inline
 snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
 {
-	snd_pcm_uframes_t ptr = runtime->status->hw_ptr;
-	return ptr - (ptr % runtime->period_size);
+	return runtime->hw_ptr_interrupt;
 }
 
 /* define extended formats in the recent OSS versions (if any) */
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 272f15d..b546ac2 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -325,8 +325,7 @@
 	if (in_interrupt) {
 		/* we know that one period was processed */
 		/* delta = "expected next hw_ptr" for in_interrupt != 0 */
-		delta = old_hw_ptr - (old_hw_ptr % runtime->period_size)
-			+ runtime->period_size;
+		delta = runtime->hw_ptr_interrupt + runtime->period_size;
 		if (delta > new_hw_ptr) {
 			hw_base += runtime->buffer_size;
 			if (hw_base >= runtime->boundary)
@@ -437,6 +436,10 @@
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
+	if (in_interrupt) {
+		runtime->hw_ptr_interrupt = new_hw_ptr -
+				(new_hw_ptr % runtime->period_size);
+	}
 	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
 	runtime->hw_ptr_jiffies = jiffies;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b53fa84..b79c777 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1252,6 +1252,8 @@
 	if (err < 0)
 		return err;
 	runtime->hw_ptr_base = 0;
+	runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
+		runtime->status->hw_ptr % runtime->period_size;
 	runtime->silence_start = runtime->status->hw_ptr;
 	runtime->silence_filled = 0;
 	return 0;
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index cecd3c1..865715e 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -2458,6 +2458,12 @@
 	{ }
 };
 
+static struct hda_verb ad1988_spdif_in_init_verbs[] = {
+	/* unmute SPDIF input pin */
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{ }
+};
+
 /* AD1989 has no ADC -> SPDIF route */
 static struct hda_verb ad1989_spdif_init_verbs[] = {
 	/* SPDIF-1 out pin */
@@ -3193,8 +3199,11 @@
 				ad1988_spdif_init_verbs;
 		}
 	}
-	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
+	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
 		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
+		spec->init_verbs[spec->num_init_verbs++] =
+			ad1988_spdif_in_init_verbs;
+	}
 
 	codec->patch_ops = ad198x_patch_ops;
 	switch (board_config) {