ChangeSet 1.2181.25.48, 2005/03/24 11:57:09+01:00, [EMAIL PROTECTED]
[ALSA] Fix EFX voice allocation/preparation
EMU10K1/EMU10K2 driver
Fixed a bug (possibly Oops) in allocation/preparation of EFX voices
The invalid voice pointer was accessed when voices are allocated over
the voice table boundary.
The patch includes a small clean-up & optimization.
Signed-off-by: Takashi Iwai <[EMAIL PROTECTED]>
emupcm.c | 66 +++++++++++++++++++++++++++++++--------------------------------
voice.c | 8 ++-----
2 files changed, 36 insertions(+), 38 deletions(-)
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c 2005-03-30 16:20:27 -08:00
+++ b/sound/pci/emu10k1/emupcm.c 2005-03-30 16:20:27 -08:00
@@ -275,11 +275,11 @@
int master, int extra,
emu10k1_voice_t *evoice,
unsigned int start_addr,
- unsigned int end_addr)
+ unsigned int end_addr,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream = evoice->epcm->substream;
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_mixer_t *mix;
unsigned int silent_page, tmp;
int voice, stereo, w_16;
unsigned char attn, send_amount[8];
@@ -289,11 +289,6 @@
unsigned int ccis;
voice = evoice->number;
- if (evoice->epcm->type == PLAYBACK_EFX)
- mix = &emu->efx_pcm_mixer[voice -
evoice->epcm->voices[0]->number];
- else
- mix = &emu->pcm_mixer[substream->number];
-
stereo = runtime->channels == 2;
w_16 = snd_pcm_format_width(runtime->format) == 16;
@@ -497,14 +492,16 @@
}
end_addr += start_addr;
snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
- start_addr, end_addr);
+ start_addr, end_addr, NULL);
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);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
if (epcm->voices[1])
snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1],
- start_addr, end_addr);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
return 0;
}
@@ -526,16 +523,18 @@
channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK;
snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
- start_addr, start_addr + (channel_size / 2));
+ start_addr, start_addr + (channel_size / 2),
NULL);
/* only difference with the master voice is we use it for the pointer */
snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
- start_addr, start_addr + channel_size);
+ start_addr, start_addr + channel_size,
+ &emu->efx_pcm_mixer[0]);
start_addr += channel_size;
for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i],
- start_addr, start_addr+channel_size);
+ start_addr, start_addr +
channel_size,
+ &emu->efx_pcm_mixer[i]);
start_addr += channel_size;
}
@@ -654,12 +653,13 @@
}
}
-static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t
*evoice, int master, int extra)
+static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t
*evoice,
+ int master, int extra,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- emu10k1_pcm_mixer_t *mix;
- unsigned int attn;
+ unsigned int attn, vattn;
unsigned int voice, tmp;
if (evoice == NULL) /* skip second voice for mono */
@@ -668,15 +668,12 @@
runtime = substream->runtime;
voice = evoice->number;
- mix = evoice->epcm->type == PLAYBACK_EFX
- ? &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number]
- : &emu->pcm_mixer[substream->number];
-
attn = extra ? 0 : 0x00ff;
tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
+ vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0;
snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
- snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) |
0xffff);
- snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) |
0xffff);
+ snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff);
+ snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff);
snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
snd_emu10k1_voice_clear_loop_stop(emu, voice);
}
@@ -725,7 +722,9 @@
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm = runtime->private_data;
+ emu10k1_pcm_mixer_t *mix;
int result = 0;
+
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n",
(int)emu, cmd, substream->ops->pointer(substream));
spin_lock(&emu->reg_lock);
switch (cmd) {
@@ -734,9 +733,10 @@
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);
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0);
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
+ mix = &emu->pcm_mixer[substream->number];
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0,
mix);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0,
mix);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1,
NULL);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
@@ -851,7 +851,7 @@
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm = runtime->private_data;
- int i = 0;
+ int i;
int result = 0;
spin_lock(&emu->reg_lock);
@@ -865,16 +865,16 @@
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0);
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
- for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
- snd_emu10k1_playback_prepare_voice(emu,
epcm->voices[i], 0, 0);
- }
+ snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1,
NULL);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 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, 0,
+
&emu->efx_pcm_mixer[i]);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
- for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_trigger_voice(emu,
epcm->voices[i], 0, 0);
- }
epcm->running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
diff -Nru a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
--- a/sound/pci/emu10k1/voice.c 2005-03-30 16:20:27 -08:00
+++ b/sound/pci/emu10k1/voice.c 2005-03-30 16:20:27 -08:00
@@ -62,15 +62,13 @@
continue;
}
- /* make sure the block of voices does not cross the 32 voice
boundary */
- //if (((i % 32) + number) > 32)
- // continue;
-
skip = 0;
for (k = 0; k < number; k++) {
voice = &emu->voices[(i+k) % NUM_G];
- if (voice->use)
+ if (voice->use) {
skip = 1;
+ break;
+ }
}
if (!skip) {
// printk("allocated voice %d\n", i);
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html