aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-06-16 11:38:46 -0400
committerTakashi Iwai <tiwai@suse.de>2009-06-16 11:38:46 -0400
commitb909005ce15886e9f3283b876e17901f8057d2f7 (patch)
tree344ff0dcca3daf270f382eaee038a6f68b0fc083
parent7998d90a143d0f8fbbb45282d5900a844de9bc16 (diff)
parentf708eb1d71dc8ffb184da9f0bc53461c6dc10653 (diff)
Merge branch 'topic/intel8x0' into for-linus
* topic/intel8x0: ALSA: intel8x0 - Fix PCM position craziness
-rw-r--r--sound/pci/intel8x0.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 173bebf9f51d..8aa5687f392a 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -356,8 +356,6 @@ struct ichdev {
356 unsigned int position; 356 unsigned int position;
357 unsigned int pos_shift; 357 unsigned int pos_shift;
358 unsigned int last_pos; 358 unsigned int last_pos;
359 unsigned long last_pos_jiffies;
360 unsigned int jiffy_to_bytes;
361 int frags; 359 int frags;
362 int lvi; 360 int lvi;
363 int lvi_frag; 361 int lvi_frag;
@@ -844,7 +842,6 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
844 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 842 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
845 val = ICH_IOCE | ICH_STARTBM; 843 val = ICH_IOCE | ICH_STARTBM;
846 ichdev->last_pos = ichdev->position; 844 ichdev->last_pos = ichdev->position;
847 ichdev->last_pos_jiffies = jiffies;
848 break; 845 break;
849 case SNDRV_PCM_TRIGGER_SUSPEND: 846 case SNDRV_PCM_TRIGGER_SUSPEND:
850 ichdev->suspended = 1; 847 ichdev->suspended = 1;
@@ -1048,7 +1045,6 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
1048 ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1; 1045 ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
1049 } 1046 }
1050 snd_intel8x0_setup_periods(chip, ichdev); 1047 snd_intel8x0_setup_periods(chip, ichdev);
1051 ichdev->jiffy_to_bytes = (runtime->rate * 4 * ichdev->pos_shift) / HZ;
1052 return 0; 1048 return 0;
1053} 1049}
1054 1050
@@ -1073,19 +1069,23 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
1073 ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) 1069 ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
1074 break; 1070 break;
1075 } while (timeout--); 1071 } while (timeout--);
1072 ptr = ichdev->last_pos;
1076 if (ptr1 != 0) { 1073 if (ptr1 != 0) {
1077 ptr1 <<= ichdev->pos_shift; 1074 ptr1 <<= ichdev->pos_shift;
1078 ptr = ichdev->fragsize1 - ptr1; 1075 ptr = ichdev->fragsize1 - ptr1;
1079 ptr += position; 1076 ptr += position;
1080 ichdev->last_pos = ptr; 1077 if (ptr < ichdev->last_pos) {
1081 ichdev->last_pos_jiffies = jiffies; 1078 unsigned int pos_base, last_base;
1082 } else { 1079 pos_base = position / ichdev->fragsize1;
1083 ptr1 = jiffies - ichdev->last_pos_jiffies; 1080 last_base = ichdev->last_pos / ichdev->fragsize1;
1084 if (ptr1) 1081 /* another sanity check; ptr1 can go back to full
1085 ptr1 -= 1; 1082 * before the base position is updated
1086 ptr = ichdev->last_pos + ptr1 * ichdev->jiffy_to_bytes; 1083 */
1087 ptr %= ichdev->size; 1084 if (pos_base == last_base)
1085 ptr = ichdev->last_pos;
1086 }
1088 } 1087 }
1088 ichdev->last_pos = ptr;
1089 spin_unlock(&chip->reg_lock); 1089 spin_unlock(&chip->reg_lock);
1090 if (ptr >= ichdev->size) 1090 if (ptr >= ichdev->size)
1091 return 0; 1091 return 0;