aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/emu10k1/emupcm.c
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2010-08-18 08:08:17 -0400
committerTakashi Iwai <tiwai@suse.de>2010-08-18 09:10:59 -0400
commit56385a12d9bb9e173751f74b6c430742018cafc0 (patch)
treea0ccadcd4ab6fe2fa7b7dbde1a8b542b7b105c15 /sound/pci/emu10k1/emupcm.c
parenta5ba6beb839cfa288960c92cd2668a2601c24dda (diff)
ALSA: emu10k1 - delay the PCM interrupts (add pcm_irq_delay parameter)
With some hardware combinations, the PCM interrupts are acknowledged before the period boundary from the emu10k1 chip. The midlevel PCM code gets confused and the playback stream is interrupted. It seems that the interrupt processing shift by 2 samples is enough to fix this issue. This default value does not harm other, non-affected hardware. More information: Kernel bugzilla bug#16300 [A copmile warning fixed by tiwai] Signed-off-by: Jaroslav Kysela <perex@perex.cz> Cc: <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/emu10k1/emupcm.c')
-rw-r--r--sound/pci/emu10k1/emupcm.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 55b83ef73c63..622bace148e3 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -332,7 +332,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
332 evoice->epcm->ccca_start_addr = start_addr + ccis; 332 evoice->epcm->ccca_start_addr = start_addr + ccis;
333 if (extra) { 333 if (extra) {
334 start_addr += ccis; 334 start_addr += ccis;
335 end_addr += ccis; 335 end_addr += ccis + emu->delay_pcm_irq;
336 } 336 }
337 if (stereo && !extra) { 337 if (stereo && !extra) {
338 snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); 338 snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
@@ -360,7 +360,9 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
360 /* Assumption that PT is already 0 so no harm overwriting */ 360 /* Assumption that PT is already 0 so no harm overwriting */
361 snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); 361 snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
362 snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); 362 snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
363 snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); 363 snd_emu10k1_ptr_write(emu, PSST, voice,
364 (start_addr + (extra ? emu->delay_pcm_irq : 0)) |
365 (send_amount[2] << 24));
364 if (emu->card_capabilities->emu_model) 366 if (emu->card_capabilities->emu_model)
365 pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ 367 pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
366 else 368 else
@@ -732,6 +734,23 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_
732 snd_emu10k1_ptr_write(emu, IP, voice, 0); 734 snd_emu10k1_ptr_write(emu, IP, voice, 0);
733} 735}
734 736
737static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu,
738 struct snd_emu10k1_pcm *epcm,
739 struct snd_pcm_substream *substream,
740 struct snd_pcm_runtime *runtime)
741{
742 unsigned int ptr, period_pos;
743
744 /* try to sychronize the current position for the interrupt
745 source voice */
746 period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt;
747 period_pos %= runtime->period_size;
748 ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number);
749 ptr &= ~0x00ffffff;
750 ptr |= epcm->ccca_start_addr + period_pos;
751 snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr);
752}
753
735static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, 754static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
736 int cmd) 755 int cmd)
737{ 756{
@@ -753,6 +772,8 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
753 /* follow thru */ 772 /* follow thru */
754 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 773 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
755 case SNDRV_PCM_TRIGGER_RESUME: 774 case SNDRV_PCM_TRIGGER_RESUME:
775 if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE)
776 snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime);
756 mix = &emu->pcm_mixer[substream->number]; 777 mix = &emu->pcm_mixer[substream->number];
757 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); 778 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
758 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); 779 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
@@ -869,8 +890,9 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *
869#endif 890#endif
870 /* 891 /*
871 printk(KERN_DEBUG 892 printk(KERN_DEBUG
872 "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", 893 "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n",
873 ptr, runtime->buffer_size, runtime->period_size); 894 (long)ptr, (long)runtime->buffer_size,
895 (long)runtime->period_size);
874 */ 896 */
875 return ptr; 897 return ptr;
876} 898}