Commit f549466b authored by Oswald Buddenhagen's avatar Oswald Buddenhagen Committed by Takashi Iwai
Browse files

ALSA: emu10k1: apply channel delay hack to all E-MU cards



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: default avatarOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230510173917.3073107-6-oswald.buddenhagen@gmx.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4c7bfbcf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1192,6 +1192,7 @@
 * 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 */
+18 −5
Original line number Diff line number Diff line
@@ -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");