From 1298bc978afba0a507cedd0a91e53267ca152804 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sun, 14 May 2023 19:03:22 +0200 Subject: [PATCH] ALSA: emu10k1: enable bit-exact playback, part 1: DSP attenuation Fractional multiplication with the maximal value 2^31-1 causes some tiny distortion. Instead, we want to multiply with the full 2^31. The catch is of course that this cannot be represented in the DSP's signed 32 bit registers. One way to deal with this is to encode 1.0 as a negative number and special-case it. As a matter of fact, the SbLive! code path already contained such code, though the controls never actually exercised it. A more efficient approach is to use negative values, which actually extend to -2^31. Accordingly, for all the volume adjustments we now use the MAC1 instruction which negates the X operand. The range of the controls in highres mode is extended downwards, so -1 is the new zero/mute. At maximal excursion, real zero is not mute any more, but I don't think anyone will notice this behavior change. ;-) That also required making the min/max/values in the control structs signed. This technically changes the user space interface, but it seems implausible that someone would notice - the numbers were actually treated as if they were signed anyway (and in the actual mixer iface they _are_). And without this change, the min value didn't even make sense in the first place (and no-one noticed, because it was always 0). Tested-by: Jonathan Dowland Signed-off-by: Oswald Buddenhagen Link: https://lore.kernel.org/r/20230514170323.3408834-7-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai --- include/sound/emu10k1.h | 6 +- include/uapi/sound/emu10k1.h | 8 ++- sound/pci/emu10k1/emufx.c | 119 +++++++++++++++++------------------ 3 files changed, 64 insertions(+), 69 deletions(-) diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index e9b1729ade60..8e27f7074230 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1508,9 +1508,9 @@ struct snd_emu10k1_fx8010_ctl { unsigned int vcount; unsigned int count; /* count of GPR (1..16) */ unsigned short gpr[32]; /* GPR number(s) */ - unsigned int value[32]; - unsigned int min; /* minimum range */ - unsigned int max; /* maximum range */ + int value[32]; + int min; /* minimum range */ + int max; /* maximum range */ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ struct snd_kcontrol *kcontrol; }; diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h index c8e131d6da00..4c32a116e7ad 100644 --- a/include/uapi/sound/emu10k1.h +++ b/include/uapi/sound/emu10k1.h @@ -308,6 +308,8 @@ struct snd_emu10k1_fx8010_info { #define EMU10K1_GPR_TRANSLATION_BASS 2 #define EMU10K1_GPR_TRANSLATION_TREBLE 3 #define EMU10K1_GPR_TRANSLATION_ONOFF 4 +#define EMU10K1_GPR_TRANSLATION_NEGATE 5 +#define EMU10K1_GPR_TRANSLATION_NEG_TABLE100 6 enum emu10k1_ctl_elem_iface { EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */ @@ -328,9 +330,9 @@ struct snd_emu10k1_fx8010_control_gpr { unsigned int vcount; /* visible count */ unsigned int count; /* count of GPR (1..16) */ unsigned short gpr[32]; /* GPR number(s) */ - unsigned int value[32]; /* initial values */ - unsigned int min; /* minimum range */ - unsigned int max; /* maximum range */ + int value[32]; /* initial values */ + int min; /* minimum range */ + int max; /* maximum range */ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ const unsigned int *tlv; }; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 9c9ffba7e591..4c9d67e72ae5 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -332,7 +332,7 @@ static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_fx8010_ctl *ctl = (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - unsigned int nval, val; + int nval, val; unsigned int i, j; int change = 0; @@ -349,9 +349,16 @@ static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl case EMU10K1_GPR_TRANSLATION_NONE: snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val); break; + case EMU10K1_GPR_TRANSLATION_NEGATE: + snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, ~val); + break; case EMU10K1_GPR_TRANSLATION_TABLE100: snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]); break; + case EMU10K1_GPR_TRANSLATION_NEG_TABLE100: + snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, + val == 100 ? 0x80000000 : -(int)db_table[val]); + break; case EMU10K1_GPR_TRANSLATION_BASS: if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { change = -EIO; @@ -771,8 +778,10 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, } switch (gctl->translation) { case EMU10K1_GPR_TRANSLATION_NONE: + case EMU10K1_GPR_TRANSLATION_NEGATE: break; case EMU10K1_GPR_TRANSLATION_TABLE100: + case EMU10K1_GPR_TRANSLATION_NEG_TABLE100: if (gctl->min != 0 || gctl->max != 100) { err = -EINVAL; goto __error; @@ -1137,44 +1146,44 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, static void snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) + const char *name, int gpr, int defval) { ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER; strcpy(ctl->id.name, name); ctl->vcount = ctl->count = 1; if (high_res_gpr_volume) { - ctl->min = 0; + ctl->min = -1; ctl->max = 0x7fffffff; ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - defval = defval * 0x7fffffffLL / 100; + ctl->translation = EMU10K1_GPR_TRANSLATION_NEGATE; + defval = defval * 0x80000000LL / 100 - 1; } else { ctl->min = 0; ctl->max = 100; ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; + ctl->translation = EMU10K1_GPR_TRANSLATION_NEG_TABLE100; } ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; } static void snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) + const char *name, int gpr, int defval) { ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER; strcpy(ctl->id.name, name); ctl->vcount = ctl->count = 2; if (high_res_gpr_volume) { - ctl->min = 0; + ctl->min = -1; ctl->max = 0x7fffffff; ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - defval = defval * 0x7fffffffLL / 100; + ctl->translation = EMU10K1_GPR_TRANSLATION_NEGATE; + defval = defval * 0x80000000LL / 100 - 1; } else { ctl->min = 0; ctl->max = 100; ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; + ctl->translation = EMU10K1_GPR_TRANSLATION_NEG_TABLE100; } ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; @@ -1293,36 +1302,36 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) #if 1 /* PCM front Playback Volume (independent from stereo mix) - * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) - * where gpr contains attenuation from corresponding mixer control + * playback = -gpr * FXBUS_PCM_LEFT_FRONT >> 31 + * where gpr contains negated attenuation from corresponding mixer control * (snd_emu10k1_init_stereo_control) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); gpr += 2; /* PCM Surround Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100); gpr += 2; /* PCM Side Playback (independent from stereo mix) */ if (emu->card_capabilities->spk71) { - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); gpr += 2; } /* PCM Center Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER)); snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100); gpr++; /* PCM LFE Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE)); snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100); gpr++; @@ -1330,26 +1339,26 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) * Stereo Mix */ /* Wave (PCM) Playback Volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); + A_OP(icode, &ptr, iMAC1, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); + A_OP(icode, &ptr, iMAC1, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100); gpr += 2; /* Synth Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); + A_OP(icode, &ptr, iMAC1, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); + A_OP(icode, &ptr, iMAC1, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100); gpr += 2; /* Wave (PCM) Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0); gpr += 2; /* Synth Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); gpr += 2; @@ -1357,23 +1366,23 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) * inputs */ #define A_ADD_VOLUME_IN(var,vol,input) \ -A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) + A_OP(icode, &ptr, iMAC1, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) if (emu->card_capabilities->emu_model) { /* EMU1010 DSP 0 and DSP 1 Capture */ // The 24 MSB hold the actual value. We implicitly discard the 16 LSB. if (emu->card_capabilities->ca0108_chip) { // For unclear reasons, the EMU32IN cannot be the Y operand! - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A3_EMU32IN(0x0), A_GPR(gpr)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+0), A_GPR(capture+0), A3_EMU32IN(0x0), A_GPR(gpr)); // A3_EMU32IN(0) is delayed by one sample, so all other A3_EMU32IN channels // need to be delayed as well; we use an auxiliary register for that. - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+2), A_GPR(gpr+1)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+2), A_GPR(gpr+1)); A_OP(icode, &ptr, iACC3, A_GPR(gpr+2), A3_EMU32IN(0x1), A_C_00000000, A_C_00000000); } else { - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+0), A_GPR(capture+0), A_P16VIN(0x0), A_GPR(gpr)); // A_P16VIN(0) is delayed by one sample, so all other A_P16VIN channels // need to be delayed as well; we use an auxiliary register for that. - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_GPR(gpr+2)); + A_OP(icode, &ptr, iMAC1, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+2), A_GPR(gpr+1)); A_OP(icode, &ptr, iACC3, A_GPR(gpr+2), A_P16VIN(0x1), A_C_00000000, A_C_00000000); } snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); @@ -1465,33 +1474,33 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) } /* Stereo Mix Front Playback Volume */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100); gpr += 2; /* Stereo Mix Surround Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0); gpr += 2; /* Stereo Mix Center Playback */ /* Center = sub = Left/2 + Right/2 */ A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), A_C_40000000, A_GPR(stereo_mix+1)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp)); snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0); gpr++; /* Stereo Mix LFE Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp)); snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); gpr++; if (emu->card_capabilities->spk71) { /* Stereo Mix Side Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0); gpr += 2; } @@ -1579,7 +1588,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* Master volume (will be renamed later) */ for (z = 0; z < 8; z++) - A_OP(icode, &ptr, iMAC0, A_GPR(playback+z), A_C_00000000, A_GPR(gpr), A_GPR(playback+z)); + A_OP(icode, &ptr, iMAC1, A_GPR(playback+z), A_C_00000000, A_GPR(gpr), A_GPR(playback+z)); snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0); gpr++; @@ -1731,30 +1740,14 @@ __err_gpr: * initial DSP configuration for Emu10k1 */ -/* when volume = max, then copy only to avoid volume modification */ -/* with iMAC0 (negative values) */ +/* Volumes are in the [-2^31, 0] range, zero being mute. */ static void _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) { - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); + OP(icode, ptr, iMAC1, dst, C_00000000, src, vol); } static void _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) { - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, dst, src, vol); -} -static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); + OP(icode, ptr, iMAC1, dst, dst, src, vol); } #define VOLUME(icode, ptr, dst, src, vol) \ @@ -1766,7 +1759,7 @@ static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst #define VOLUME_ADDIN(icode, ptr, dst, src, vol) \ _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol)) #define VOLUME_OUT(icode, ptr, dst, src, vol) \ - _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol)) + _volume(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol)) #define _SWITCH(icode, ptr, dst, src, sw) \ OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw); #define SWITCH(icode, ptr, dst, src, sw) \