ALSA: emu10k1: move snd_emu1010_load_firmware_entry() to io.c
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Sun, 28 Apr 2024 09:37:16 +0000 (11:37 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 28 Apr 2024 10:00:36 +0000 (12:00 +0200)
It is a low-level I/O access function, so io.c is the natural place for
it.

While we're moving the code, reduce the scope of some variables, use
compound assignment operators, and add/adjust some comments.

Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Message-ID: <20240428093717.3198716-4-oswald.buddenhagen@gmx.de>

include/sound/emu10k1.h
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/io.c

index 234b5baea69c8e6154c3c048fe002bf99337e245..2856f4717c93eb5148a2e1e45a4dafd2ed80c39d 100644 (file)
@@ -1843,6 +1843,7 @@ void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 s
 u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst);
 int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src);
 void snd_emu1010_update_clock(struct snd_emu10k1 *emu);
+void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, const struct firmware *fw_entry);
 unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
index ec010971a2207ca658481ed25d11d281dcee718c..c8aa4143ac4fee67987b3bcbb101e377b9eb2c3a 100644 (file)
@@ -652,47 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
        return 0;
 }
 
-static void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu,
-                                    const struct firmware *fw_entry)
-{
-       int n, i;
-       u16 reg;
-       u8 value;
-       __always_unused u16 write_post;
-
-       /* The FPGA is a Xilinx Spartan IIE XC2S50E */
-       /* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */
-       /* GPIO7 -> FPGA PGMN
-        * GPIO6 -> FPGA CCLK
-        * GPIO5 -> FPGA DIN
-        * FPGA CONFIG OFF -> FPGA PGMN
-        */
-       spin_lock_irq(&emu->emu_lock);
-       outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */
-       write_post = inw(emu->port + A_GPIO);
-       udelay(100);
-       outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */
-       write_post = inw(emu->port + A_GPIO);
-       udelay(100); /* Allow FPGA memory to clean */
-       for (n = 0; n < fw_entry->size; n++) {
-               value = fw_entry->data[n];
-               for (i = 0; i < 8; i++) {
-                       reg = 0x80;
-                       if (value & 0x1)
-                               reg = reg | 0x20;
-                       value = value >> 1;
-                       outw(reg, emu->port + A_GPIO);
-                       write_post = inw(emu->port + A_GPIO);
-                       outw(reg | 0x40, emu->port + A_GPIO);
-                       write_post = inw(emu->port + A_GPIO);
-               }
-       }
-       /* After programming, set GPIO bit 4 high again. */
-       outw(0x10, emu->port + A_GPIO);
-       write_post = inw(emu->port + A_GPIO);
-       spin_unlock_irq(&emu->emu_lock);
-}
-
 /* firmware file names, per model, init-fw and dock-fw (optional) */
 static const char * const firmware_names[5][2] = {
        [EMU_MODEL_EMU1010] = {
index f4a1c2d4b0787518634dac52ebae9c41a01f05dc..fafa299efa5c586fb46bccc2ea496938de2e3e18 100644 (file)
@@ -422,6 +422,54 @@ void snd_emu1010_update_clock(struct snd_emu10k1 *emu)
        snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, leds);
 }
 
+void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu,
+                                    const struct firmware *fw_entry)
+{
+       __always_unused u16 write_post;
+
+       // On E-MU 1010 rev1 the FPGA is a Xilinx Spartan IIE XC2S50E.
+       // On E-MU 0404b it is a Xilinx Spartan III XC3S50.
+       // The wiring is as follows:
+       // GPO7 -> FPGA input & 1K resistor -> FPGA /PGMN <- FPGA output
+       //   In normal operation, the active low reset line is held up by
+       //   an FPGA output, while the GPO pin performs its duty as control
+       //   register access strobe signal. Writing the respective bit to
+       //   EMU_HANA_FPGA_CONFIG puts the FPGA output into high-Z mode, at
+       //   which point the GPO pin can control the reset line through the
+       //   resistor.
+       // GPO6 -> FPGA CCLK & FPGA input
+       // GPO5 -> FPGA DIN (dual function)
+
+       // Assert reset line for 100uS
+       outw(0x00, emu->port + A_GPIO);
+       write_post = inw(emu->port + A_GPIO);
+       udelay(100);
+       outw(0x80, emu->port + A_GPIO);
+       write_post = inw(emu->port + A_GPIO);
+       udelay(100);  // Allow FPGA memory to clean
+
+       // Upload the netlist. Keep reset line high!
+       for (int n = 0; n < fw_entry->size; n++) {
+               u8 value = fw_entry->data[n];
+               for (int i = 0; i < 8; i++) {
+                       u16 reg = 0x80;
+                       if (value & 1)
+                               reg |= 0x20;
+                       value >>= 1;
+                       outw(reg, emu->port + A_GPIO);
+                       write_post = inw(emu->port + A_GPIO);
+                       outw(reg | 0x40, emu->port + A_GPIO);
+                       write_post = inw(emu->port + A_GPIO);
+               }
+       }
+
+       // After programming, set GPIO bit 4 high again.
+       // This appears to be a config word that the rev1 Hana
+       // firmware reads; weird things happen without this.
+       outw(0x10, emu->port + A_GPIO);
+       write_post = inw(emu->port + A_GPIO);
+}
+
 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
 {
        unsigned long flags;