Commit 77e067d0 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen Committed by Takashi Iwai

ALSA: emu10k1: skip needless setting of some voice registers

Many registers are meaningless for stereo slaves and the extra voices.
This patch cleans up these unnecessary register writes.

snd_emu10k1_playback_{trigger,stop}_voice() is not called for stereo
slaves any more.

snd_emu10k1_playback_prepare_voice() is renamed to
snd_emu10k1_playback_unmute_voice(), as this better reflects its
remaining function. It's not called for the extra voices any more.

Accordingly, snd_emu10k1_playback_mute_voice() is factored out from
snd_emu10k1_playback_stop_voice(), and is called selectively as well.

This doesn't add conditionals which would avoid initializing
sub-registers, as that wouldn't pull its weight.
Signed-off-by: default avatarOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230516093612.3536451-6-oswald.buddenhagen@gmx.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 35a60d1e
...@@ -404,6 +404,14 @@ SUB_REG(HCFG, LOCKTANKCACHE, 0x00000004) /* 1 = Cancel bustmaster accesses to ta ...@@ -404,6 +404,14 @@ SUB_REG(HCFG, LOCKTANKCACHE, 0x00000004) /* 1 = Cancel bustmaster accesses to ta
// distortion), the modulation engine sets the target registers, towards // distortion), the modulation engine sets the target registers, towards
// which the current registers "swerve" gradually. // which the current registers "swerve" gradually.
// For the odd channel in a stereo pair, these registers are meaningless:
// CPF_STEREO, CPF_CURRENTPITCH, PTRX_PITCHTARGET, CCR_CACHEINVALIDSIZE,
// PSST_LOOPSTARTADDR, DSL_LOOPENDADDR, CCCA_CURRADDR
// The somewhat non-obviously still meaningful ones are:
// CPF_STOP, CPF_FRACADDRESS, CCR_READADDRESS (!),
// CCCA_INTERPROM, CCCA_8BITSELECT (!)
// (The envelope engine is ignored here, as stereo matters only for verbatim playback.)
#define CPF 0x00 /* Current pitch and fraction register */ #define CPF 0x00 /* Current pitch and fraction register */
SUB_REG(CPF, CURRENTPITCH, 0xffff0000) /* Current pitch (linear, 0x4000 == unity pitch shift) */ SUB_REG(CPF, CURRENTPITCH, 0xffff0000) /* Current pitch (linear, 0x4000 == unity pitch shift) */
#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */ #define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */
......
...@@ -301,13 +301,13 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, ...@@ -301,13 +301,13 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
start_addr += ccis; start_addr += ccis;
end_addr += ccis + emu->delay_pcm_irq; end_addr += ccis + emu->delay_pcm_irq;
} }
}
if (stereo && !extra) { if (stereo && !extra) {
// Not really necessary for the slave, but it doesn't hurt
snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK);
} else { } else {
snd_emu10k1_ptr_write(emu, CPF, voice, 0); snd_emu10k1_ptr_write(emu, CPF, voice, 0);
} }
}
/* setup routing */ /* setup routing */
if (emu->audigy) { if (emu->audigy) {
...@@ -325,6 +325,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, ...@@ -325,6 +325,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
snd_emu10k1_compose_send_routing(send_routing)); snd_emu10k1_compose_send_routing(send_routing));
/* Assumption that PT is already 0 so no harm overwriting */ /* Assumption that PT is already 0 so no harm overwriting */
snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
// Stereo slaves don't need to have the addresses set, but it doesn't hurt
snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
snd_emu10k1_ptr_write(emu, PSST, voice, snd_emu10k1_ptr_write(emu, PSST, voice,
(start_addr + (extra ? emu->delay_pcm_irq : 0)) | (start_addr + (extra ? emu->delay_pcm_irq : 0)) |
...@@ -554,8 +555,6 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e ...@@ -554,8 +555,6 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
unsigned int voice, stereo, i, ccis, cra = 64, cs, sample; unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
if (evoice == NULL)
return;
runtime = evoice->epcm->substream->runtime; runtime = evoice->epcm->substream->runtime;
voice = evoice->number; voice = evoice->number;
stereo = (!extra && runtime->channels == 2); stereo = (!extra && runtime->channels == 2);
...@@ -575,6 +574,7 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e ...@@ -575,6 +574,7 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
if (stereo) { if (stereo) {
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
// The engine goes haywire if this one is out of sync
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
} }
/* fill cache */ /* fill cache */
...@@ -584,37 +584,49 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e ...@@ -584,37 +584,49 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
} }
} }
static void snd_emu10k1_playback_prepare_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, static void snd_emu10k1_playback_commit_volume(struct snd_emu10k1 *emu,
int master, struct snd_emu10k1_voice *evoice,
unsigned int vattn)
{
snd_emu10k1_ptr_write(emu, VTFT, evoice->number, vattn | VTFT_FILTERTARGET_MASK);
snd_emu10k1_ptr_write(emu, CVCF, evoice->number, vattn | CVCF_CURRENTFILTER_MASK);
}
static void snd_emu10k1_playback_unmute_voice(struct snd_emu10k1 *emu,
struct snd_emu10k1_voice *evoice,
bool master,
struct snd_emu10k1_pcm_mixer *mix) struct snd_emu10k1_pcm_mixer *mix)
{ {
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
unsigned int vattn; unsigned int vattn;
unsigned int voice, tmp; unsigned int tmp;
if (evoice == NULL) /* skip second voice for mono */ if (evoice == NULL) /* skip second voice for mono */
return; return;
substream = evoice->epcm->substream; substream = evoice->epcm->substream;
runtime = substream->runtime; runtime = substream->runtime;
voice = evoice->number;
tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0; tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0; vattn = mix->attn[tmp] << 16;
snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | VTFT_FILTERTARGET_MASK); snd_emu10k1_playback_commit_volume(emu, evoice, vattn);
snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | CVCF_CURRENTFILTER_MASK); }
static void snd_emu10k1_playback_mute_voice(struct snd_emu10k1 *emu,
struct snd_emu10k1_voice *evoice)
{
if (evoice == NULL)
return;
snd_emu10k1_playback_commit_volume(emu, evoice, 0);
} }
static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
struct snd_emu10k1_voice *evoice, struct snd_emu10k1_voice *evoice)
int master)
{ {
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
unsigned int voice, pitch_target; unsigned int voice, pitch_target;
if (evoice == NULL) /* skip second voice for mono */
return;
substream = evoice->epcm->substream; substream = evoice->epcm->substream;
runtime = substream->runtime; runtime = substream->runtime;
voice = evoice->number; voice = evoice->number;
...@@ -624,7 +636,6 @@ static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, ...@@ -624,7 +636,6 @@ static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
else else
pitch_target = emu10k1_calc_pitch_target(runtime->rate); pitch_target = emu10k1_calc_pitch_target(runtime->rate);
snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
if (master || evoice->epcm->type == PLAYBACK_EFX)
snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
} }
...@@ -633,13 +644,9 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, ...@@ -633,13 +644,9 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu,
{ {
unsigned int voice; unsigned int voice;
if (evoice == NULL)
return;
voice = evoice->number; voice = evoice->number;
snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0); snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0);
snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0); snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0);
snd_emu10k1_ptr_write(emu, VTFT, voice, VTFT_FILTERTARGET_MASK);
snd_emu10k1_ptr_write(emu, CVCF, voice, CVCF_CURRENTFILTER_MASK);
} }
static void snd_emu10k1_playback_set_running(struct snd_emu10k1 *emu, static void snd_emu10k1_playback_set_running(struct snd_emu10k1 *emu,
...@@ -698,21 +705,20 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, ...@@ -698,21 +705,20 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE)
snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime);
mix = &emu->pcm_mixer[substream->number]; mix = &emu->pcm_mixer[substream->number];
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, mix); snd_emu10k1_playback_unmute_voice(emu, epcm->voices[0], true, mix);
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, mix); snd_emu10k1_playback_unmute_voice(emu, epcm->voices[1], false, mix);
snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, NULL);
snd_emu10k1_playback_set_running(emu, epcm); snd_emu10k1_playback_set_running(emu, epcm);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1); snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0]);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0); snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]); snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);
snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]);
snd_emu10k1_playback_stop_voice(emu, epcm->extra); snd_emu10k1_playback_stop_voice(emu, epcm->extra);
snd_emu10k1_playback_set_stopped(emu, epcm); snd_emu10k1_playback_set_stopped(emu, epcm);
snd_emu10k1_playback_mute_voice(emu, epcm->voices[0]);
snd_emu10k1_playback_mute_voice(emu, epcm->voices[1]);
break; break;
default: default:
result = -EINVAL; result = -EINVAL;
...@@ -844,16 +850,14 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, ...@@ -844,16 +850,14 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
fallthrough; fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, NULL); for (i = 0; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, snd_emu10k1_playback_unmute_voice(emu, epcm->voices[i], false,
&emu->efx_pcm_mixer[0]);
for (i = 1; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0,
&emu->efx_pcm_mixer[i]); &emu->efx_pcm_mixer[i]);
snd_emu10k1_playback_set_running(emu, epcm); snd_emu10k1_playback_set_running(emu, epcm);
for (i = 0; i < NUM_EFX_PLAYBACK; i++) for (i = 0; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0); snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i]);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1); snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
...@@ -863,6 +867,9 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, ...@@ -863,6 +867,9 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
} }
snd_emu10k1_playback_stop_voice(emu, epcm->extra); snd_emu10k1_playback_stop_voice(emu, epcm->extra);
snd_emu10k1_playback_set_stopped(emu, epcm); snd_emu10k1_playback_set_stopped(emu, epcm);
for (i = 0; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_mute_voice(emu, epcm->voices[i]);
break; break;
default: default:
result = -EINVAL; result = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment