ALSA: emu10k1: fix snd_emu1010_fpga_read() input masking for rev2 cards
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Sat, 22 Apr 2023 13:24:30 +0000 (15:24 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sat, 22 Apr 2023 15:34:28 +0000 (17:34 +0200)
Unlike the Alice2 chips used on 1st generation E-MU cards, the
Tina/Tina2 chips used on the 2nd gen cards have only six GPIN pins,
which means that we need to use a smaller mask. Failure to do so would
falsify the read data if the FPGA tried to raise an IRQ right at that
moment. This wasn't a problem so far, as we didn't actually enable FPGA
IRQs, but that's going to change soon.

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

index f21441c..790dedd 100644 (file)
 #define MUSTAT_ORDYN           0x40            /* 0 = MUDATA can accept a command or data      */
 
 #define A_GPIO                 0x18            /* GPIO on Audigy card (16bits)                 */
-#define A_GPINPUT_MASK         0xff00
+#define A_GPINPUT_MASK         0xff00          /* Alice/2 has 8 input pins                     */
+#define A3_GPINPUT_MASK                0x3f00          /* ... while Tina/2 has only 6                  */
 #define A_GPOUTPUT_MASK                0x00ff
 
 // The GPIO port is used for I/O config on Sound Blasters;
index f013468..42b06f2 100644 (file)
@@ -255,6 +255,9 @@ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
 
 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
 {
+       // The higest input pin is used as the designated interrupt trigger,
+       // so it needs to be masked out.
+       u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
        unsigned long flags;
        if (snd_BUG_ON(reg > 0x3f))
                return;
@@ -264,7 +267,7 @@ void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
        udelay(10);
        outw(reg | 0x80, emu->port + A_GPIO);  /* High bit clocks the value into the fpga. */
        udelay(10);
-       *value = ((inw(emu->port + A_GPIO) >> 8) & 0x7f);
+       *value = ((inw(emu->port + A_GPIO) >> 8) & mask);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }