ALSA: emu10k1: apply channel delay hack to all E-MU cards
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Wed, 10 May 2023 17:39:08 +0000 (19:39 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 12 May 2023 07:17:18 +0000 (09:17 +0200)
Evidently, the channel delay bug exists in all E-MU cards; it's in the
Hana FPGA program, and was never fixed.

Note that the implementation is somewhat lazy - to localize the code
paths, we actually waste a GPR and a DSP instruction by keeping two
delay registers for the same physical source.

Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230510173917.3073107-6-oswald.buddenhagen@gmx.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/emu10k1.h
sound/pci/emu10k1/emufx.c

index 8fe80dc..7129b92 100644 (file)
  * emumixer.c - snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[]
  */
 #define EMU_DST_ALICE2_EMU32_0 0x000f  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+                                       /* This channel is delayed by one sample. */
 #define EMU_DST_ALICE2_EMU32_1 0x0000  /* 16 EMU32 channels to Alice2 +0 to +0xf */
 #define EMU_DST_ALICE2_EMU32_2 0x0001  /* 16 EMU32 channels to Alice2 +0 to +0xf */
 #define EMU_DST_ALICE2_EMU32_3 0x0002  /* 16 EMU32 channels to Alice2 +0 to +0xf */
index 8ba2941..2e139ae 100644 (file)
@@ -1326,13 +1326,20 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
                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, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A3_EMU32IN(0x1), A_GPR(gpr+1));
+                       // 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, 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, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
+                       // 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, 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);
-               gpr += 2;
+               gpr_map[gpr + 2] = 0x00000000;
+               gpr += 3;
        }
        /* AC'97 Playback Volume - used only for mic (renamed later) */
        A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
@@ -1624,11 +1631,17 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
                        dev_info(emu->card->dev, "EMU2 inputs on\n");
                        /* Note that the Tina[2] DSPs have 16 more EMU32 inputs which we don't use. */
 
-                       for (z = 0; z < 0x10; z++) {
+                       snd_emu10k1_audigy_dsp_convert_32_to_2x16(
+                               icode, &ptr, tmp, bit_shifter16, A3_EMU32IN(0), A_FXBUS2(0));
+                       // 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.
+                       for (z = 1; z < 0x10; z++) {
                                snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, 
                                                                        bit_shifter16,
-                                                                       A3_EMU32IN(z),
+                                                                       A_GPR(gpr),
                                                                        A_FXBUS2(z*2) );
+                               A_OP(icode, &ptr, iACC3, A_GPR(gpr), A3_EMU32IN(z), A_C_00000000, A_C_00000000);
+                               gpr_map[gpr++] = 0x00000000;
                        }
                } else {
                        dev_info(emu->card->dev, "EMU inputs on\n");