--- emupcm.c.orig 2005-03-02 09:40:37.000000000 +0100 +++ emupcm.c 2005-03-05 09:13:09.074485436 +0100 @@ -250,6 +250,22 @@ return CCCA_INTERPROM_2; } +/* + * calculate cache invalidate size + * + * stereo: channel is stereo + * w_16: using 16bit samples + * + * returns: cache invalidate size in samples + */ +static int inline emu10k1_ccis(int stereo, int w_16) +{ + if (w_16) { + return stereo ? 24 : 26; + } else { + return stereo ? 24*2 : 26*2; + } +} static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu, int master, int extra, @@ -304,9 +320,7 @@ memcpy(send_amount, &mix->send_volume[tmp][0], 8); } - ccis = stereo ? 28 : 30; - if (w_16) - ccis *= 2; + ccis = emu10k1_ccis(stereo, w_16); if (master) { evoice->epcm->ccca_start_addr = start_addr + ccis; @@ -473,11 +487,14 @@ start_addr = epcm->start_addr; end_addr = snd_pcm_lib_period_bytes(substream); - if (runtime->channels == 2) + if (runtime->channels == 2) { + start_addr >>= 1; end_addr >>= 1; + } end_addr += start_addr; snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, start_addr, end_addr); + start_addr = epcm->start_addr; end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], start_addr, end_addr); @@ -598,7 +615,7 @@ return 0; } -static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, emu10k1_voice_t *evoice) +static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu10k1_voice_t *evoice) { snd_pcm_runtime_t *runtime; unsigned int voice, i, ccis, cra = 64, cs, sample; @@ -608,27 +625,26 @@ runtime = evoice->epcm->substream->runtime; voice = evoice->number; sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080; - if (runtime->channels == 2) { - ccis = 28; - cs = 4; - } else { - ccis = 30; - cs = 2; - } - if (sample == 0) /* 16-bit */ - ccis *= 2; - for (i = 0; i < cs; i++) + cs = 16; + ccis = emu10k1_ccis(!extra && runtime->channels == 2, sample == 0); + for (i = 0; i < cs; i++) { snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample); - + if (!extra && runtime->channels == 2) { + snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample); + } + } // reset cache snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); - if (runtime->channels == 2) { + if (!extra && runtime->channels == 2) { snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); } // fill cache snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis); + if (!extra && runtime->channels == 2) { + snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis); + } } static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra) @@ -707,8 +723,8 @@ spin_lock(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_emu10k1_playback_invalidate_cache(emu, epcm->extra); /* do we need this? */ - snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]); + snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */ + snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]); /* follow thru */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0); @@ -836,9 +852,9 @@ case SNDRV_PCM_TRIGGER_START: // prepare voices for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[i]); + snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]); } - snd_emu10k1_playback_invalidate_cache(emu, epcm->extra); + snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* follow thru */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: