From 08e55ae996cbdbd76c3eb12fcad6cc79cba7ddbc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 18 May 2023 16:03:38 +0200 Subject: [PATCH] ALSA: emu10k1: enable bit-exact playback, part 3: pitch CPF_CURRENTPITCH starts swerving towards PTRX_PITCHTARGET as soon as that is set. In practice this means that CPF_FRACADDRESS may acquire a non-zero value before we manage to force CPF_CURRENTPITCH to the final value, which would prevent bit-for-bit reproduction. To avoid that this state persists, we now reset CPF_FRACADDRESS when setting CPF_CURRENTPITCH, and to (mostly) avoid that it progresses too far in the first place (possibly even reaching CCCA_CURRADDR), we write PTRX and CPF in one critical section (though NMIs, etc. still make this unreliable). Signed-off-by: Oswald Buddenhagen Link: https://lore.kernel.org/r/20230518140339.3722279-2-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emupcm.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 1ca16f0..0b23ff8 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -601,6 +601,17 @@ static void snd_emu10k1_playback_mute_voice(struct snd_emu10k1 *emu, snd_emu10k1_playback_commit_volume(emu, evoice, 0); } +static void snd_emu10k1_playback_commit_pitch(struct snd_emu10k1 *emu, + u32 voice, u32 pitch_target) +{ + u32 ptrx = snd_emu10k1_ptr_read(emu, PTRX, voice); + u32 cpf = snd_emu10k1_ptr_read(emu, CPF, voice); + snd_emu10k1_ptr_write_multiple(emu, voice, + PTRX, (ptrx & ~PTRX_PITCHTARGET_MASK) | pitch_target, + CPF, (cpf & ~(CPF_CURRENTPITCH_MASK | CPF_FRACADDRESS_MASK)) | pitch_target, + REGLIST_END); +} + static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice) { @@ -616,8 +627,7 @@ static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ else pitch_target = emu10k1_calc_pitch_target(runtime->rate); - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); + snd_emu10k1_playback_commit_pitch(emu, voice, pitch_target << 16); } static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, @@ -626,8 +636,7 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, unsigned int voice; voice = evoice->number; - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0); - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0); + snd_emu10k1_playback_commit_pitch(emu, voice, 0); } static void snd_emu10k1_playback_set_running(struct snd_emu10k1 *emu, -- 2.7.4