From: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
To: alsa-devel@alsa-project.org
Cc: Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>
Subject: [PATCH 5/6] ALSA: emu10k1: skip needless setting of some voice registers
Date: Tue, 16 May 2023 11:36:11 +0200 [thread overview]
Message-ID: <20230516093612.3536451-6-oswald.buddenhagen@gmx.de> (raw)
In-Reply-To: <20230516093612.3536451-1-oswald.buddenhagen@gmx.de>
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: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
---
include/sound/emu10k1.h | 8 ++++
sound/pci/emu10k1/emupcm.c | 89 ++++++++++++++++++++------------------
2 files changed, 56 insertions(+), 41 deletions(-)
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index a5e935e16651..5c1e5b123362 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -404,6 +404,14 @@ SUB_REG(HCFG, LOCKTANKCACHE, 0x00000004) /* 1 = Cancel bustmaster accesses to ta
// distortion), the modulation engine sets the target registers, towards
// 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 */
SUB_REG(CPF, CURRENTPITCH, 0xffff0000) /* Current pitch (linear, 0x4000 == unity pitch shift) */
#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 7b0ab4e02cfd..4ade0ef2cd1b 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -301,12 +301,12 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
start_addr += ccis;
end_addr += ccis + emu->delay_pcm_irq;
}
- if (stereo && !extra) {
- snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
- snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK);
- } else {
- snd_emu10k1_ptr_write(emu, CPF, voice, 0);
- }
+ }
+ if (stereo && !extra) {
+ // Not really necessary for the slave, but it doesn't hurt
+ snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
+ } else {
+ snd_emu10k1_ptr_write(emu, CPF, voice, 0);
}
/* setup routing */
@@ -325,6 +325,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
snd_emu10k1_compose_send_routing(send_routing));
/* Assumption that PT is already 0 so no harm overwriting */
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, PSST, voice,
(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
struct snd_pcm_runtime *runtime;
unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
- if (evoice == NULL)
- return;
runtime = evoice->epcm->substream->runtime;
voice = evoice->number;
stereo = (!extra && runtime->channels == 2);
@@ -575,71 +574,79 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
if (stereo) {
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);
}
/* fill cache */
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
if (stereo) {
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
}
}
-static void snd_emu10k1_playback_prepare_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice,
- int master,
- struct snd_emu10k1_pcm_mixer *mix)
+static void snd_emu10k1_playback_commit_volume(struct snd_emu10k1 *emu,
+ 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_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
unsigned int vattn;
- unsigned int voice, tmp;
+ unsigned int tmp;
if (evoice == NULL) /* skip second voice for mono */
return;
substream = evoice->epcm->substream;
runtime = substream->runtime;
- voice = evoice->number;
tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
- vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0;
- snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | VTFT_FILTERTARGET_MASK);
- snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | CVCF_CURRENTFILTER_MASK);
+ vattn = mix->attn[tmp] << 16;
+ snd_emu10k1_playback_commit_volume(emu, evoice, vattn);
}
+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,
- struct snd_emu10k1_voice *evoice,
- int master)
+ struct snd_emu10k1_voice *evoice)
{
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
unsigned int voice, pitch_target;
- if (evoice == NULL) /* skip second voice for mono */
- return;
substream = evoice->epcm->substream;
runtime = substream->runtime;
voice = evoice->number;
if (emu->card_capabilities->emu_model)
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);
- 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);
}
static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu,
struct snd_emu10k1_voice *evoice)
{
unsigned int voice;
- if (evoice == NULL)
- return;
voice = evoice->number;
snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, 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,
@@ -698,21 +705,20 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE)
snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime);
mix = &emu->pcm_mixer[substream->number];
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, mix);
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, mix);
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, NULL);
+ snd_emu10k1_playback_unmute_voice(emu, epcm->voices[0], true, mix);
+ snd_emu10k1_playback_unmute_voice(emu, epcm->voices[1], false, mix);
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[1], 0);
- snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0]);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
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_set_stopped(emu, epcm);
+ snd_emu10k1_playback_mute_voice(emu, epcm->voices[0]);
+ snd_emu10k1_playback_mute_voice(emu, epcm->voices[1]);
break;
default:
result = -EINVAL;
@@ -844,25 +850,26 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, NULL);
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0,
- &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]);
+ for (i = 0; i < NUM_EFX_PLAYBACK; i++)
+ snd_emu10k1_playback_unmute_voice(emu, epcm->voices[i], false,
+ &emu->efx_pcm_mixer[i]);
+
snd_emu10k1_playback_set_running(emu, epcm);
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->extra, 1);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i]);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]);
}
snd_emu10k1_playback_stop_voice(emu, epcm->extra);
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;
default:
result = -EINVAL;
--
2.40.0.152.g15d061e6df
next prev parent reply other threads:[~2023-05-16 9:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-16 9:36 [PATCH 0/6] ALSA: emu10k1: assorted playback-related cleanups Oswald Buddenhagen
2023-05-16 9:36 ` [PATCH 1/6] ALSA: emu10k1: straighten out FX send init Oswald Buddenhagen
2023-05-16 9:36 ` [PATCH 2/6] ALSA: emu10k1: cleanup envelope register init Oswald Buddenhagen
2023-05-16 9:36 ` [PATCH 3/6] ALSA: emu10k1: remove useless resets of stop-on-loop-end bits Oswald Buddenhagen
2023-05-16 9:36 ` [PATCH 4/6] ALSA: emu10k1: rewire {en,dis}abling interrupts for PCM playback Oswald Buddenhagen
2023-05-16 9:36 ` Oswald Buddenhagen [this message]
2023-05-16 9:36 ` [PATCH 6/6] ALSA: emu10k1: factor out snd_emu10k1_compose_audigy_sendamounts() Oswald Buddenhagen
2023-05-17 15:08 ` [PATCH 0/6] ALSA: emu10k1: assorted playback-related cleanups Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230516093612.3536451-6-oswald.buddenhagen@gmx.de \
--to=oswald.buddenhagen@gmx.de \
--cc=alsa-devel@alsa-project.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox