[ALSA] snd-emu10k1: Added support for emu1010, including E-Mu 1212m and E-Mu 1820m
authorJames Courtier-Dutton <James@superbug.co.uk>
Sun, 1 Oct 2006 09:48:04 +0000 (10:48 +0100)
committerJaroslav Kysela <perex@suse.cz>
Fri, 9 Feb 2007 07:59:59 +0000 (08:59 +0100)
Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
include/sound/emu10k1.h
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/pci/emu10k1/p16v.c
sound/pci/emu10k1/voice.c

index 3d3c151..396812e 100644 (file)
 #define HCFG_LEGACYINT         0x00200000      /* 1 = legacy event captured. Write 1 to clear. */
                                                /* NOTE: The rest of the bits in this register  */
                                                /* _are_ relevant under Linux.                  */
-#define HCFG_CODECFORMAT_MASK  0x00070000      /* CODEC format                                 */
+#define HCFG_PUSH_BUTTON_ENABLE 0x00100000     /* Enables Volume Inc/Dec and Mute functions    */
+#define HCFG_BAUD_RATE         0x00080000      /* 0 = 48kHz, 1 = 44.1kHz                       */
+#define HCFG_EXPANDED_MEM      0x00040000      /* 1 = any 16M of 4G addr, 0 = 32M of 2G addr   */
+#define HCFG_CODECFORMAT_MASK  0x00030000      /* CODEC format                                 */
+
+/* Specific to Alice2, CA0102 */
+#define HCFG_CODECFORMAT_AC97_1        0x00000000      /* AC97 CODEC format -- Ver 1.03                */
+#define HCFG_CODECFORMAT_AC97_2        0x00010000      /* AC97 CODEC format -- Ver 2.1                 */
+#define HCFG_AUTOMUTE_ASYNC    0x00008000      /* When set, the async sample rate convertors   */
+                                               /* will automatically mute their output when    */
+                                               /* they are not rate-locked to the external     */
+                                               /* async audio source                           */
+#define HCFG_AUTOMUTE_SPDIF    0x00004000      /* When set, the async sample rate convertors   */
+                                               /* will automatically mute their output when    */
+                                               /* the SPDIF V-bit indicates invalid audio      */
+#define HCFG_EMU32_SLAVE       0x00002000      /* 0 = Master, 1 = Slave. Slave for EMU1010     */
+#define HCFG_SLOW_RAMP         0x00001000      /* Increases Send Smoothing time constant       */
+/* 0x00000800 not used on Alice2 */
+#define HCFG_PHASE_TRACK_MASK  0x00000700      /* When set, forces corresponding input to      */
+                                               /* phase track the previous input.              */
+                                               /* I2S0 can phase track the last S/PDIF input   */
+#define HCFG_I2S_ASRC_ENABLE   0x00000070      /* When set, enables asynchronous sample rate   */
+                                               /* conversion for the corresponding             */
+                                               /* I2S format input                             */
+/* Rest of HCFG 0x0000000f same as below. LOCKSOUNDCACHE etc.  */
+
+
+
+/* Older chips */
 #define HCFG_CODECFORMAT_AC97  0x00000000      /* AC97 CODEC format -- Primary Output          */
 #define HCFG_CODECFORMAT_I2S   0x00010000      /* I2S CODEC format -- Secondary (Rear) Output  */
 #define HCFG_GPINPUT0          0x00004000      /* External pin112                              */
 #define A_HIWORD_RESULT_MASK   0x007ff000
 #define A_HIWORD_OPA_MASK      0x000007ff
 
+/************************************************************************************************/
+/* EMU1010m HANA FPGA registers                                                                        */
+/************************************************************************************************/
+#define EMU_HANA_DESTHI                0x00    /* 0000xxx  3 bits Link Destination */
+#define EMU_HANA_DESTLO                0x01    /* 00xxxxx  5 bits */
+#define EMU_HANA_SRCHI         0x02    /* 0000xxx  3 bits Link Source */
+#define EMU_HANA_SRCLO         0x03    /* 00xxxxx  5 bits */
+#define EMU_HANA_DOCK_PWR      0x04    /* 000000x  1 bits Audio Dock power */
+#define EMU_HANA_DOCK_PWR_ON           0x01 /* Audio Dock power on */
+#define EMU_HANA_WCLOCK                0x05    /* 0000xxx  3 bits Word Clock source select  */
+                                       /* Must be written after power on to reset DLL */
+                                       /* One is unable to detect the Audio dock without this */
+#define EMU_HANA_WCLOCK_SRC_MASK       0x07
+#define EMU_HANA_WCLOCK_INT_48K                0x00
+#define EMU_HANA_WCLOCK_INT_44_1K      0x01
+#define EMU_HANA_WCLOCK_HANA_SPDIF_IN  0x02
+#define EMU_HANA_WCLOCK_HANA_ADAT_IN   0x03
+#define EMU_HANA_WCLOCK_SYNC_BNCN      0x04
+#define EMU_HANA_WCLOCK_2ND_HANA       0x05
+#define EMU_HANA_WCLOCK_SRC_RESERVED   0x06
+#define EMU_HANA_WCLOCK_OFF            0x07 /* For testing, forces fallback to DEFCLOCK */
+#define EMU_HANA_WCLOCK_MULT_MASK      0x18
+#define EMU_HANA_WCLOCK_1X             0x00
+#define EMU_HANA_WCLOCK_2X             0x08
+#define EMU_HANA_WCLOCK_4X             0x10
+#define EMU_HANA_WCLOCK_MULT_RESERVED  0x18
+
+#define EMU_HANA_DEFCLOCK      0x06    /* 000000x  1 bits Default Word Clock  */
+#define EMU_HANA_DEFCLOCK_48K          0x00
+#define EMU_HANA_DEFCLOCK_44_1K                0x01
+
+#define EMU_HANA_UNMUTE                0x07    /* 000000x  1 bits Mute all audio outputs  */
+#define EMU_MUTE                       0x00
+#define EMU_UNMUTE                     0x01
+
+#define EMU_HANA_FPGA_CONFIG   0x08    /* 00000xx  2 bits Config control of FPGAs  */
+#define EMU_HANA_FPGA_CONFIG_AUDIODOCK 0x01 /* Set in order to program FPGA on Audio Dock */
+#define EMU_HANA_FPGA_CONFIG_HANA      0x02 /* Set in order to program FPGA on Hana */
+
+#define EMU_HANA_IRQ_ENABLE    0x09    /* 000xxxx  4 bits IRQ Enable  */
+#define EMU_HANA_IRQ_WCLK_CHANGED      0x01
+#define EMU_HANA_IRQ_ADAT              0x02
+#define EMU_HANA_IRQ_DOCK              0x04
+#define EMU_HANA_IRQ_DOCK_LOST         0x08
+
+#define EMU_HANA_SPDIF_MODE    0x0a    /* 00xxxxx  5 bits SPDIF MODE  */
+#define EMU_HANA_SPDIF_MODE_TX_COMSUMER        0x00
+#define EMU_HANA_SPDIF_MODE_TX_PRO     0x01
+#define EMU_HANA_SPDIF_MODE_TX_NOCOPY  0x02
+#define EMU_HANA_SPDIF_MODE_RX_COMSUMER        0x00
+#define EMU_HANA_SPDIF_MODE_RX_PRO     0x04
+#define EMU_HANA_SPDIF_MODE_RX_NOCOPY  0x08
+#define EMU_HANA_SPDIF_MODE_RX_INVALID 0x10
+
+#define EMU_HANA_OPTICAL_TYPE  0x0b    /* 00000xx  2 bits ADAT or SPDIF in/out  */
+#define EMU_HANA_OPTICAL_IN_SPDIF      0x00
+#define EMU_HANA_OPTICAL_IN_ADAT       0x01
+#define EMU_HANA_OPTICAL_OUT_SPDIF     0x00
+#define EMU_HANA_OPTICAL_OUT_ADAT      0x02
+
+#define EMU_HANA_MIDI          0x0c    /* 000000x  1 bit  Control MIDI  */
+#define EMU_HANA_MIDI_IN_FROM_HAMOA    0x00 /* HAMOA MIDI in to Alice 2 MIDI B */
+#define EMU_HANA_MIDI_IN_FROM_DOCK     0x01 /* Audio Dock MIDI in to Alice 2 MIDI B */
+
+#define EMU_HANA_DOCK_LEDS_1   0x0d    /* 000xxxx  4 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_1_MIDI1     0x01    /* MIDI 1 LED on */
+#define EMU_HANA_DOCK_LEDS_1_MIDI2     0x02    /* MIDI 2 LED on */
+#define EMU_HANA_DOCK_LEDS_1_SMPTE_IN  0x04    /* SMPTE IN LED on */
+#define EMU_HANA_DOCK_LEDS_1_SMPTE_OUT 0x08    /* SMPTE OUT LED on */
+
+#define EMU_HANA_DOCK_LEDS_2   0x0e    /* 0xxxxxx  6 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_2_44K       0x01    /* 44.1 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_48K       0x02    /* 48 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_96K       0x04    /* 96 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_192K      0x08    /* 192 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_LOCK      0x10    /* LOCK LED on */
+#define EMU_HANA_DOCK_LEDS_2_EXT       0x20    /* EXT LED on */
+
+#define EMU_HANA_DOCK_LEDS_3   0x0f    /* 0xxxxxx  6 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_3_CLIP_A    0x01    /* Mic A Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_CLIP_B    0x02    /* Mic B Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_SIGNAL_A  0x04    /* Signal A Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_SIGNAL_B  0x08    /* Signal B Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_MANUAL_CLIP       0x10    /* Manual Clip detection */
+#define EMU_HANA_DOCK_LEDS_3_MANUAL_SIGNAL     0x20    /* Manual Signal detection */
+
+#define EMU_HANA_DOCK_PADS     0x10    /* 0000xxx  3 bit  Audio Dock ADC 14dB pads */
+#define EMU_HANA_DOCK_PAD1     0x01    /* 14dB Attenuation on ADC 1 */
+#define EMU_HANA_DOCK_PAD2     0x02    /* 14dB Attenuation on ADC 2 */
+#define EMU_HANA_DOCK_PAD3     0x04    /* 14dB Attenuation on ADC 3 */
+
+#define EMU_HANA_DOCK_MISC     0x11    /* 0xxxxxx  6 bit  Audio Dock misc bits */
+#define EMU_HANA_DOCK_DAC1_MUTE        0x01    /* DAC 1 Mute */
+#define EMU_HANA_DOCK_DAC2_MUTE        0x02    /* DAC 2 Mute */
+#define EMU_HANA_DOCK_DAC3_MUTE        0x04    /* DAC 3 Mute */
+#define EMU_HANA_DOCK_DAC4_MUTE        0x08    /* DAC 4 Mute */
+#define EMU_HANA_DOCK_PHONES_192_DAC1  0x00    /* DAC 1 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC2  0x10    /* DAC 2 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC3  0x20    /* DAC 3 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC4  0x30    /* DAC 4 Headphones source at 192kHz */
+
+#define EMU_HANA_UNKNOWN12     0x12    /* 0xxxxxx  6 bit  Unknown12 */
+#define EMU_HANA_UNKNOWN13     0x13    /* 0xxxxxx  6 bit  Unknown13 */
+/* 0x14 - 0x1f Unused R/W registers */
+#define EMU_HANA_IRQ_STATUS    0x20    /* 000xxxx  4 bits IRQ Status  */
+#if 0  /* Already defined for reg 0x09 IRQ_ENABLE */
+#define EMU_HANA_IRQ_WCLK_CHANGED      0x01
+#define EMU_HANA_IRQ_ADAT              0x02
+#define EMU_HANA_IRQ_DOCK              0x04
+#define EMU_HANA_IRQ_DOCK_LOST         0x08
+#endif
+
+#define EMU_HANA_OPTION_CARDS  0x21    /* 000xxxx  4 bits Presence of option cards */
+#define EMU_HANA_OPTION_HAMOA  0x01    /* HAMOA card present */
+#define EMU_HANA_OPTION_SYNC   0x02    /* Sync card present */
+#define EMU_HANA_OPTION_DOCK_ONLINE    0x04    /* Audio Dock online and FPGA configured */
+#define EMU_HANA_OPTION_DOCK_OFFLINE   0x08    /* Audio Dock online and FPGA not configured */
+
+#define EMU_HANA_ID            0x22    /* 1010101  7 bits ID byte & 0x7f = 0x55 */
+
+#define EMU_HANA_MAJOR_REV     0x23    /* 0000xxx  3 bit  Hana FPGA Major rev */
+#define EMU_HANA_MINOR_REV     0x24    /* 0000xxx  3 bit  Hana FPGA Minor rev */
+
+#define EMU_DOCK_MAJOR_REV     0x25    /* 0000xxx  3 bit  Audio Dock FPGA Major rev */
+#define EMU_DOCK_MINOR_REV     0x26    /* 0000xxx  3 bit  Audio Dock FPGA Minor rev */
+
+#define EMU_DOCK_BOARD_ID      0x27    /* 00000xx  2 bits Audio Dock ID pins */
+#define EMU_DOCK_BOARD_ID0     0x00    /* ID bit 0 */
+#define EMU_DOCK_BOARD_ID1     0x03    /* ID bit 1 */
+
+#define EMU_HANA_WC_SPDIF_HI   0x28    /* 0xxxxxx  6 bit  SPDIF IN Word clock, upper 6 bits */
+#define EMU_HANA_WC_SPDIF_LO   0x29    /* 0xxxxxx  6 bit  SPDIF IN Word clock, lower 6 bits */
+
+#define EMU_HANA_WC_ADAT_HI    0x2a    /* 0xxxxxx  6 bit  ADAT IN Word clock, upper 6 bits */
+#define EMU_HANA_WC_ADAT_LO    0x2b    /* 0xxxxxx  6 bit  ADAT IN Word clock, lower 6 bits */
+
+#define EMU_HANA_WC_BNC_LO     0x2c    /* 0xxxxxx  6 bit  BNC IN Word clock, lower 6 bits */
+#define EMU_HANA_WC_BNC_HI     0x2d    /* 0xxxxxx  6 bit  BNC IN Word clock, upper 6 bits */
+
+#define EMU_HANA2_WC_SPDIF_HI  0x2e    /* 0xxxxxx  6 bit  HANA2 SPDIF IN Word clock, upper 6 bits */
+#define EMU_HANA2_WC_SPDIF_LO  0x2f    /* 0xxxxxx  6 bit  HANA2 SPDIF IN Word clock, lower 6 bits */
+/* 0x30 - 0x3f Unused Read only registers */
+
+/************************************************************************************************/
+/* EMU1010m HANA Destinations                                                                  */
+/************************************************************************************************/
+#define EMU_DST_ALICE2_EMU32_0 0x000f  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#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 */
+#define EMU_DST_ALICE2_EMU32_4 0x0003  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_5 0x0004  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_6 0x0005  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_7 0x0006  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_8 0x0007  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_9 0x0008  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_A 0x0009  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_B 0x000a  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_C 0x000b  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_D 0x000c  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_E 0x000d  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_F 0x000e  /* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_DOCK_DAC1_LEFT1        0x0100  /* Audio Dock DAC1 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC1_LEFT2        0x0101  /* Audio Dock DAC1 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC1_LEFT3        0x0102  /* Audio Dock DAC1 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC1_LEFT4        0x0103  /* Audio Dock DAC1 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT1       0x0104  /* Audio Dock DAC1 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC1_RIGHT2       0x0105  /* Audio Dock DAC1 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT3       0x0106  /* Audio Dock DAC1 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT4       0x0107  /* Audio Dock DAC1 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC2_LEFT1        0x0108  /* Audio Dock DAC2 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC2_LEFT2        0x0109  /* Audio Dock DAC2 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC2_LEFT3        0x010a  /* Audio Dock DAC2 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC2_LEFT4        0x010b  /* Audio Dock DAC2 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT1       0x010c  /* Audio Dock DAC2 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC2_RIGHT2       0x010d  /* Audio Dock DAC2 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT3       0x010e  /* Audio Dock DAC2 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT4       0x010f  /* Audio Dock DAC2 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC3_LEFT1        0x0110  /* Audio Dock DAC1 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC3_LEFT2        0x0111  /* Audio Dock DAC1 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_LEFT3        0x0112  /* Audio Dock DAC1 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC3_LEFT4        0x0113  /* Audio Dock DAC1 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_PHONES_LEFT1      0x0112  /* Audio Dock PHONES Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_PHONES_LEFT2      0x0113  /* Audio Dock PHONES Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT1       0x0114  /* Audio Dock DAC1 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC3_RIGHT2       0x0115  /* Audio Dock DAC1 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT3       0x0116  /* Audio Dock DAC1 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT4       0x0117  /* Audio Dock DAC1 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_PHONES_RIGHT1     0x0116  /* Audio Dock PHONES Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_PHONES_RIGHT2     0x0117  /* Audio Dock PHONES Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_LEFT1        0x0118  /* Audio Dock DAC2 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC4_LEFT2        0x0119  /* Audio Dock DAC2 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_LEFT3        0x011a  /* Audio Dock DAC2 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC4_LEFT4        0x011b  /* Audio Dock DAC2 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_SPDIF_LEFT1       0x011a  /* Audio Dock SPDIF Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_SPDIF_LEFT2       0x011b  /* Audio Dock SPDIF Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT1       0x011c  /* Audio Dock DAC2 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC4_RIGHT2       0x011d  /* Audio Dock DAC2 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT3       0x011e  /* Audio Dock DAC2 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT4       0x011f  /* Audio Dock DAC2 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_SPDIF_RIGHT1      0x011e  /* Audio Dock SPDIF Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_SPDIF_RIGHT2      0x011f  /* Audio Dock SPDIF Right, 2nd or 96kHz */
+#define EMU_DST_HANA_SPDIF_LEFT1       0x0200  /* Hana SPDIF Left, 1st or 48kHz only */
+#define EMU_DST_HANA_SPDIF_LEFT2       0x0202  /* Hana SPDIF Left, 2nd or 96kHz */
+#define EMU_DST_HANA_SPDIF_RIGHT1      0x0201  /* Hana SPDIF Right, 1st or 48kHz only */
+#define EMU_DST_HANA_SPDIF_RIGHT2      0x0203  /* Hana SPDIF Right, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_LEFT1        0x0300  /* Hamoa DAC Left, 1st or 48kHz only */
+#define EMU_DST_HAMOA_DAC_LEFT2        0x0302  /* Hamoa DAC Left, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_LEFT3        0x0304  /* Hamoa DAC Left, 3rd or 192kHz */
+#define EMU_DST_HAMOA_DAC_LEFT4        0x0306  /* Hamoa DAC Left, 4th or 192kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT1       0x0301  /* Hamoa DAC Right, 1st or 48kHz only */
+#define EMU_DST_HAMOA_DAC_RIGHT2       0x0303  /* Hamoa DAC Right, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT3       0x0305  /* Hamoa DAC Right, 3rd or 192kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT4       0x0307  /* Hamoa DAC Right, 4th or 192kHz */
+#define EMU_DST_HANA_ADAT      0x0400  /* Hana ADAT 8 channel out +0 to +7 */
+#define EMU_DST_ALICE_I2S0_LEFT                0x0500  /* Alice2 I2S0 Left */
+#define EMU_DST_ALICE_I2S0_RIGHT       0x0501  /* Alice2 I2S0 Right */
+#define EMU_DST_ALICE_I2S1_LEFT                0x0600  /* Alice2 I2S1 Left */
+#define EMU_DST_ALICE_I2S1_RIGHT       0x0601  /* Alice2 I2S1 Right */
+#define EMU_DST_ALICE_I2S2_LEFT                0x0700  /* Alice2 I2S2 Left */
+#define EMU_DST_ALICE_I2S2_RIGHT       0x0701  /* Alice2 I2S2 Right */
+
+/************************************************************************************************/
+/* EMU1010m HANA Sources                                                                       */
+/************************************************************************************************/
+#define EMU_SRC_SILENCE                0x0000  /* Silence */
+#define EMU_SRC_DOCK_MIC_A1    0x0100  /* Audio Dock Mic A, 1st or 48kHz only */
+#define EMU_SRC_DOCK_MIC_A2    0x0101  /* Audio Dock Mic A, 2nd or 96kHz */
+#define EMU_SRC_DOCK_MIC_A3    0x0102  /* Audio Dock Mic A, 3rd or 192kHz */
+#define EMU_SRC_DOCK_MIC_A4    0x0103  /* Audio Dock Mic A, 4th or 192kHz */
+#define EMU_SRC_DOCK_MIC_B1    0x0104  /* Audio Dock Mic B, 1st or 48kHz only */
+#define EMU_SRC_DOCK_MIC_B2    0x0105  /* Audio Dock Mic B, 2nd or 96kHz */
+#define EMU_SRC_DOCK_MIC_B3    0x0106  /* Audio Dock Mic B, 3rd or 192kHz */
+#define EMU_SRC_DOCK_MIC_B4    0x0107  /* Audio Dock Mic B, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT1        0x0108  /* Audio Dock ADC1 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC1_LEFT2        0x0109  /* Audio Dock ADC1 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT3        0x010a  /* Audio Dock ADC1 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT4        0x010b  /* Audio Dock ADC1 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT1       0x010c  /* Audio Dock ADC1 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC1_RIGHT2       0x010d  /* Audio Dock ADC1 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT3       0x010e  /* Audio Dock ADC1 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT4       0x010f  /* Audio Dock ADC1 Right, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT1        0x0110  /* Audio Dock ADC2 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC2_LEFT2        0x0111  /* Audio Dock ADC2 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT3        0x0112  /* Audio Dock ADC2 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT4        0x0113  /* Audio Dock ADC2 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT1       0x0114  /* Audio Dock ADC2 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC2_RIGHT2       0x0115  /* Audio Dock ADC2 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT3       0x0116  /* Audio Dock ADC2 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT4       0x0117  /* Audio Dock ADC2 Right, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT1        0x0118  /* Audio Dock ADC3 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC3_LEFT2        0x0119  /* Audio Dock ADC3 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT3        0x011a  /* Audio Dock ADC3 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT4        0x011b  /* Audio Dock ADC3 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT1       0x011c  /* Audio Dock ADC3 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC3_RIGHT2       0x011d  /* Audio Dock ADC3 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT3       0x011e  /* Audio Dock ADC3 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT4       0x011f  /* Audio Dock ADC3 Right, 4th or 192kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT1        0x0200  /* Hamoa ADC Left, 1st or 48kHz only */
+#define EMU_SRC_HAMOA_ADC_LEFT2        0x0202  /* Hamoa ADC Left, 2nd or 96kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT3        0x0204  /* Hamoa ADC Left, 3rd or 192kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT4        0x0206  /* Hamoa ADC Left, 4th or 192kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT1       0x0201  /* Hamoa ADC Right, 1st or 48kHz only */
+#define EMU_SRC_HAMOA_ADC_RIGHT2       0x0203  /* Hamoa ADC Right, 2nd or 96kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT3       0x0205  /* Hamoa ADC Right, 3rd or 192kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT4       0x0207  /* Hamoa ADC Right, 4th or 192kHz */
+#define EMU_SRC_ALICE_EMU32A           0x0300  /* Alice2 EMU32a 16 outputs. +0 to +0xf */
+#define EMU_SRC_ALICE_EMU32B           0x0310  /* Alice2 EMU32b 16 outputs. +0 to +0xf */
+#define EMU_SRC_HANA_ADAT      0x0400  /* Hana ADAT 8 channel in +0 to +7 */
+#define EMU_SRC_HANA_SPDIF_LEFT1       0x0500  /* Hana SPDIF Left, 1st or 48kHz only */
+#define EMU_SRC_HANA_SPDIF_LEFT2       0x0502  /* Hana SPDIF Left, 2nd or 96kHz */
+#define EMU_SRC_HANA_SPDIF_RIGHT1      0x0501  /* Hana SPDIF Right, 1st or 48kHz only */
+#define EMU_SRC_HANA_SPDIF_RIGHT2      0x0503  /* Hana SPDIF Right, 2nd or 96kHz */
+/* 0x600 and 0x700 no used */
 
 /* ------------------- STRUCTURES -------------------- */
 
@@ -1063,7 +1365,7 @@ struct snd_emu_chip_details {
        unsigned char spdif_bug;    /* Has Spdif phasing bug */
        unsigned char ac97_chip;    /* Has an AC97 chip: 1 = mandatory, 2 = optional */
        unsigned char ecard;        /* APS EEPROM */
-       unsigned char emu1212m;     /* EMU 1212m card */
+       unsigned char emu1010;     /* EMU 1010m card */
        unsigned char spi_dac;      /* SPI interface for DAC */
        unsigned char i2c_adc;      /* I2C interface for ADC */
        unsigned char adc_1361t;    /* Use Philips 1361T ADC */
@@ -1072,6 +1374,11 @@ struct snd_emu_chip_details {
        const char *id;         /* for backward compatibility - can be NULL if not needed */
 };
 
+struct snd_emu1010 {
+       unsigned int output_source[64];
+       unsigned int input_source[64];
+};
+
 struct snd_emu10k1 {
        int irq;
 
@@ -1132,6 +1439,7 @@ struct snd_emu10k1 {
        int p16v_device_offset;
        u32 p16v_capture_source;
        u32 p16v_capture_channel;
+        struct snd_emu1010 emu1010;
        struct snd_emu10k1_pcm_mixer pcm_mixer[32];
        struct snd_emu10k1_pcm_mixer efx_pcm_mixer[NUM_EFX_PLAYBACK];
        struct snd_kcontrol *ctl_send_routing;
@@ -1208,6 +1516,9 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i
 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value);
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value);
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src);
 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 972ec40..891172f 100644 (file)
@@ -3,8 +3,10 @@
  *                   Creative Labs, Inc.
  *  Routines for control of EMU10K1 chips
  *
- *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
  *      Added support for Audigy 2 Value.
+ *     Added EMU 1010 support.
+ *     General bug fixes and enhancements.
  *
  *
  *  BUGS:
@@ -41,6 +43,7 @@
 
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include <linux/firmware.h>
 #include "p16v.h"
 #include "tina2.h"
 
@@ -211,7 +214,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                int size, n;
 
                size = ARRAY_SIZE(spi_dac_init);
-               for (n=0; n < size; n++)
+               for (n = 0; n < size; n++)
                        snd_emu10k1_spi_write(emu, spi_dac_init[n]);
 
                snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10);
@@ -239,6 +242,10 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
        }
 
+       if (emu->card_capabilities->emu1010) {
+               outl(HCFG_AUTOMUTE_ASYNC |
+                       HCFG_EMU32_SLAVE |
+                       HCFG_AUDIOENABLE, emu->port + HCFG);
        /*
         *  Hokay, setup HCFG
         *   Mute Disable Audio = 0
@@ -246,7 +253,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
         *   Lock Sound Memory = 0
         *   Auto Mute = 1
         */
-       if (emu->audigy) {
+       } else if (emu->audigy) {
                if (emu->revision == 4) /* audigy2 */
                        outl(HCFG_AUDIOENABLE |
                             HCFG_AC3ENABLE_CDSPDIF |
@@ -265,8 +272,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
 
        if (enable_ir) {        /* enable IR for SB Live */
-               if ( emu->card_capabilities->emu1212m) {
-                       ;  /* Disable all access to A_IOCFG for the emu1212m */
+               if (emu->card_capabilities->emu1010) {
+                       ;  /* Disable all access to A_IOCFG for the emu1010 */
                } else if (emu->audigy) {
                        unsigned int reg = inl(emu->port + A_IOCFG);
                        outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
@@ -284,8 +291,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                }
        }
        
-       if ( emu->card_capabilities->emu1212m) {
-               ;  /* Disable all access to A_IOCFG for the emu1212m */
+       if (emu->card_capabilities->emu1010) {
+               ;  /* Disable all access to A_IOCFG for the emu1010 */
        } else if (emu->audigy) {       /* enable analog output */
                unsigned int reg = inl(emu->port + A_IOCFG);
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
@@ -302,8 +309,8 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
        outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
 
        /* Enable analog/digital outs on audigy */
-       if ( emu->card_capabilities->emu1212m) {
-               ;  /* Disable all access to A_IOCFG for the emu1212m */
+       if (emu->card_capabilities->emu1010) {
+               ;  /* Disable all access to A_IOCFG for the emu1010 */
        } else if (emu->audigy) {
                outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
  
@@ -596,133 +603,417 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
        return 0;
 }
 
-static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
-{
-       if (reg<0 || reg>0x3f)
-               return 1;
-       reg+=0x40; /* 0x40 upwards are registers. */
-       if (value<0 || value>0x3f) /* 0 to 0x3f are values */
-               return 1;
-       outl(reg, emu->port + A_IOCFG);
-       outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
-       outl(value, emu->port + A_IOCFG);
-       outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
-
-       return 0;
-}
-
-static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename)
 {
-       if (reg<0 || reg>0x3f)
-               return 1;
-       reg+=0x40; /* 0x40 upwards are registers. */
-       outl(reg, emu->port + A_IOCFG);
-       outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
-       *value = inl(emu->port + A_IOCFG);
-
-       return 0;
-}
+       int err;
+       int n, i;
+       int reg;
+       int value;
+       const struct firmware *fw_entry;
+
+       if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) {
+               snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err);
+               return err;
+       }
+       snd_printk(KERN_INFO "firmware size=0x%x\n",fw_entry->size);
+       if (fw_entry->size != 0x133a4) {
+               snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename);
+               return -EINVAL;
+       }
 
-static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value)
-{
-       snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) );
-       snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) );
-       snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) );
-       snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) );
+       /* The FPGA is a Xilinx Spartan IIE XC2S50E */
+       /* GPIO7 -> FPGA PGMN
+        * GPIO6 -> FPGA CCLK
+        * GPIO5 -> FPGA DIN
+        * FPGA CONFIG OFF -> FPGA PGMN
+        */
+       outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */
+       udelay(1);
+       outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
+       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;   
+                       outl(reg, emu->port + A_IOCFG);
+                       outl(reg | 0x40, emu->port + A_IOCFG);
+               }
+       }
+       /* After programming, set GPIO bit 4 high again. */
+       outl(0x10, emu->port + A_IOCFG);
+       
 
+        release_firmware(fw_entry);
        return 0;
 }
 
-static int snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu)
+static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
 {
        unsigned int i;
-       int tmp;
-
-       snd_printk(KERN_ERR "emu1212m: Special config.\n");
+       int tmp,tmp2;
+       int reg;
+       int err;
+       const char *hana_filename = "emu/hana.fw";
+       const char *dock_filename = "emu/audio_dock.fw";
+
+       snd_printk(KERN_INFO "emu1010: Special config.\n");
+       /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+        * Lock Sound Memory Cache, Lock Tank Memory Cache,
+        * Mute all codecs.
+        */
        outl(0x0005a00c, emu->port + HCFG);
-       outl(0x0005a004, emu->port + HCFG);
+       /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+        * Lock Tank Memory Cache,
+        * Mute all codecs.
+        */
+       outl(0x0005a004, emu->port + HCFG); 
+       /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+        * Mute all codecs.
+        */
        outl(0x0005a000, emu->port + HCFG);
+       /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+        * Mute all codecs.
+        */
        outl(0x0005a000, emu->port + HCFG);
 
-       snd_emu1212m_fpga_read(emu, 0x22, &tmp );
-       snd_emu1212m_fpga_read(emu, 0x23, &tmp );
-       snd_emu1212m_fpga_read(emu, 0x24, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x04, 0x01 );
-       snd_emu1212m_fpga_read(emu, 0x0b, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x0b, 0x01 );
-       snd_emu1212m_fpga_read(emu, 0x10, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x10, 0x00 );
-       snd_emu1212m_fpga_read(emu, 0x11, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
-       snd_emu1212m_fpga_read(emu, 0x13, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x13, 0x0f );
-       snd_emu1212m_fpga_read(emu, 0x11, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
-       snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
-       snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-       snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-       snd_emu1212m_fpga_write(emu, 0x09, 0x0f );
-       snd_emu1212m_fpga_write(emu, 0x06, 0x00 );
-       snd_emu1212m_fpga_write(emu, 0x05, 0x00 );
-       snd_emu1212m_fpga_write(emu, 0x0e, 0x12 );
-       snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200);
-       snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201);
-       for (i=0;i < 0x20;i++) {
-               snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000);
+       /* Disable 48Volt power to Audio Dock */
+       snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  0 );
+
+       /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
+       snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+       snd_printdd("reg1=0x%x\n",reg);
+       if (reg == 0x55) {
+               /* FPGA netlist already present so clear it */
+               /* Return to programming mode */
+
+               snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0x02 );
        }
-       for (i=0;i < 4;i++) {
-               snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000);
+       snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+       snd_printdd("reg2=0x%x\n",reg);
+       if (reg == 0x55) {
+               /* FPGA failed to return to programming mode */
+               return -ENODEV;
        }
-       for (i=0;i < 7;i++) {
-               snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000);
+       snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
+       if ((err = snd_emu1010_load_firmware(emu, hana_filename)) != 0) {
+               snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", hana_filename);
+               return err;
        }
-       for (i=0;i < 7;i++) {
-               snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000);
+
+       /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+       snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+       if (reg != 0x55) {
+               /* FPGA failed to be programmed */
+               snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
+               return -ENODEV;
        }
-       snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c);
-       snd_emu1212m_fpga_write(emu, 0x07, 0x01 );
 
-       snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+       snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
+       snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp );
+       snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 );
+       snd_printk("Hana ver:%d.%d\n",tmp ,tmp2);
+       /* Enable 48Volt power to Audio Dock */
+       snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  EMU_HANA_DOCK_PWR_ON );
+
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+       snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+       snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); 
+       /* ADAT input. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 );
+       snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_PADS, &tmp );
+       /* Set no attenuation on Audio Dock pads. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PADS, 0x00 );
+       snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+       /* Unmute Audio dock DACs, Headphone source DAC-4. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
+       snd_emu1010_fpga_read(emu, EMU_HANA_UNKNOWN13, &tmp );
+       /* Unknown. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNKNOWN13, 0x0f );
+       snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+       snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
+       /* SPDIF Format. Set Consumer mode, 24bit, copy enable */
+       snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 );
+       /* MIDI routing */
+       snd_emu1010_fpga_write(emu, EMU_HANA_MIDI, 0x19 );
+       /* Unknown. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNKNOWN12, 0x0c );
+       /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */
+       /* IRQ Enable: All off */
+       snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 );
+
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+       snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg);
+       /* Default WCLK set to 48kHz. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 );
+       /* Word Clock source, Internal 48kHz x1 */
+       snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+       //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+       /* Audio Dock LEDs. */
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
 
-       outl(0x0000a000, emu->port + HCFG);
+#if 0
+       /* For 96kHz */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT2);
+#endif
+#if 0
+       /* For 192kHz */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_RIGHT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT3);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT3);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_6, EMU_SRC_HAMOA_ADC_LEFT4);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_7, EMU_SRC_HAMOA_ADC_RIGHT4);
+#endif
+#if 1
+       /* For 48kHz */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_0, EMU_SRC_DOCK_MIC_A1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_1, EMU_SRC_DOCK_MIC_B1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_LEFT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_4, EMU_SRC_DOCK_ADC1_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_5, EMU_SRC_DOCK_ADC1_RIGHT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1);
+#endif
+#if 0
+       /* Original */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_4, EMU_SRC_HANA_ADAT);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_5, EMU_SRC_HANA_ADAT + 1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_6, EMU_SRC_HANA_ADAT + 2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_7, EMU_SRC_HANA_ADAT + 3);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_8, EMU_SRC_HANA_ADAT + 4);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_9, EMU_SRC_HANA_ADAT + 5);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_A, EMU_SRC_HANA_ADAT + 6);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_B, EMU_SRC_HANA_ADAT + 7);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_MIC_A1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_MIC_B1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_E, EMU_SRC_HAMOA_ADC_LEFT2);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2);
+#endif
+       for (i = 0;i < 0x20; i++ ) {
+               /* AudioDock Elink <-  Silence */
+               snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE);
+       }
+       for (i = 0;i < 4; i++) {
+               /* Hana SPDIF Out <- Silence */
+               snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE);
+       }
+       for (i = 0;i < 7; i++) {
+               /* Hamoa DAC <- Silence */
+               snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE);
+       }
+       for (i = 0;i < 7; i++) {
+               /* Hana ADAT Out <- Silence */
+               snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE);
+       }
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S0_LEFT, EMU_SRC_DOCK_ADC1_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S0_RIGHT, EMU_SRC_DOCK_ADC1_RIGHT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S1_LEFT, EMU_SRC_DOCK_ADC2_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S1_RIGHT, EMU_SRC_DOCK_ADC2_RIGHT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1);
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1);
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all
+
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+       
+       /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
+        * Lock Sound Memory Cache, Lock Tank Memory Cache,
+        * Mute all codecs.
+        */
+       outl(0x0000a000, emu->port + HCFG); 
+       /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
+        * Lock Sound Memory Cache, Lock Tank Memory Cache,
+        * Un-Mute all codecs.
+        */
        outl(0x0000a001, emu->port + HCFG);
        /* Initial boot complete. Now patches */
 
-       snd_emu1212m_fpga_read(emu, 0x21, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-       snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-       snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-       snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-       snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
-       snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
-
-       snd_emu1212m_fpga_read(emu, 0x20, &tmp );
-       snd_emu1212m_fpga_read(emu, 0x21, &tmp );
-
-       snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302);
-       snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303);
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+       snd_emu1010_fpga_write(emu, EMU_HANA_MIDI, 0x19 ); /* MIDI Route */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNKNOWN12, 0x0c ); /* Unknown */
+       snd_emu1010_fpga_write(emu, EMU_HANA_MIDI, 0x19 ); /* MIDI Route */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNKNOWN12, 0x0c ); /* Unknown */
+       snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); 
+       snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif  (or 0x11 for aes/ebu) */
+
+       /* Delay to allow Audio Dock to settle */
+       msleep(100);
+       snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
+       snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
+       /* FIXME: The loading of this should be able to happen any time,
+        * as the user can plug/unplug it at any time
+        */
+       if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) {
+               /* Audio Dock attached */
+               /* Return to Audio Dock programming mode */
+               snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
+               snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
+               if ((err = snd_emu1010_load_firmware(emu, dock_filename)) != 0) {
+                       return err;
+               }
+               snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
+               snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0 );
+               snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
+               snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
+               /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+               snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+               snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
+               if (reg != 0x55) {
+                       /* FPGA failed to be programmed */
+                       snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
+                       return 0;
+                       return -ENODEV;
+               }
+       }
+#if 0
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32B + 3); /* ALICE2 bus 0xa3 */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 2); /* ALICE2 bus 0xb2 */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */
+#endif
+       /* Default outputs */
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[0] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[1] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2);
+       emu->emu1010.output_source[2] = 23;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3);
+       emu->emu1010.output_source[3] = 24;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4);
+       emu->emu1010.output_source[4] = 25;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5);
+       emu->emu1010.output_source[5] = 26;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6);
+       emu->emu1010.output_source[6] = 27;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7);
+       emu->emu1010.output_source[7] = 28;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[8] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[9] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[10] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[11] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[12] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[13] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[14] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[15] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+       emu->emu1010.output_source[16] = 21;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1);
+       emu->emu1010.output_source[17] = 22;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2);
+       emu->emu1010.output_source[18] = 23;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3);
+       emu->emu1010.output_source[19] = 24;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4);
+       emu->emu1010.output_source[20] = 25;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5);
+       emu->emu1010.output_source[21] = 26;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6);
+       emu->emu1010.output_source[22] = 27;
+       snd_emu1010_fpga_link_dst_src_write(emu,
+               EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7);
+       emu->emu1010.output_source[23] = 28;
+
+       /* TEMP: Select SPDIF in/out */
+       snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
+
+       /* TEMP: Select 48kHz SPDIF out */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
+       snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */
+       /* Word Clock source, Internal 48kHz x1 */
+       snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+       //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+       snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */
+       snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */
+       //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */
+       //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */
+       //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */
 
        return 0;
 }
@@ -747,6 +1038,10 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
                }
                snd_emu10k1_free_efx(emu);
                }
+       if (emu->card_capabilities->emu1010) {
+               /* Disable 48Volt power to Audio Dock */
+               snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  0 );
+       }
        if (emu->memhdr)
                snd_util_memhdr_free(emu->memhdr);
        if (emu->silent_page.area)
@@ -865,11 +1160,12 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ac97_chip = 1} ,
        /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
-        .driver = "Audigy2", .name = "E-mu 1212m [4001]", 
-        .id = "EMU1212m",
+        .driver = "Audigy2", .name = "E-mu 1010 [4001]", 
+        .id = "EMU1010",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
-        .emu1212m = 1} ,
+        .spk71 = 1,
+        .emu1010 = 1} ,
        /* Tested by James@superbug.co.uk 3rd July 2005 */
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
         .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
@@ -1297,8 +1593,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
        } else if (emu->card_capabilities->ca_cardbus_chip) {
                if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
                        goto error;
-       } else if (emu->card_capabilities->emu1212m) {
-               if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) {
+       } else if (emu->card_capabilities->emu1010) {
+               if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
                        snd_emu10k1_free(emu);
                        return err;
                }
@@ -1446,8 +1742,8 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
                snd_emu10k1_ecard_init(emu);
        else if (emu->card_capabilities->ca_cardbus_chip)
                snd_emu10k1_cardbus_init(emu);
-       else if (emu->card_capabilities->emu1212m)
-               snd_emu10k1_emu1212m_init(emu);
+       else if (emu->card_capabilities->emu1010)
+               snd_emu10k1_emu1010_init(emu);
        else
                snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
        snd_emu10k1_init(emu, emu->enable_ir, 1);
index 2199b42..bb0fec7 100644 (file)
@@ -460,7 +460,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        int i;
        
-       for(i=0; i < runtime->periods; i++) {
+       for(i = 0; i < runtime->periods; i++) {
                *table_base++=runtime->dma_addr+(i*period_size_bytes);
                *table_base++=period_size_bytes<<16;
        }
@@ -1042,8 +1042,8 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
                if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
                        continue;
 
-               if ((reg < 0x49) && (reg >=0) && (val <= 0xffffffff) 
-                   && (channel_id >=0) && (channel_id <= 2) )
+               if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff) 
+                   && (channel_id >= 0) && (channel_id <= 2) )
                        snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
        }
 }
index 13cd6ce..d8e8db8 100644 (file)
@@ -3,6 +3,9 @@
  *                   Creative Labs, Inc.
  *  Routines for effect processor FX8010
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *     Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -1069,6 +1072,21 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
        ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
 }
 
+static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
+                               struct snd_emu10k1_fx8010_code *icode,
+                               u32 *ptr, int tmp, int bit_shifter16,
+                               int reg_in, int reg_out)
+{
+       A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
+       A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
+       A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
+       A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
+       A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
+       A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
+       A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
+       A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
+       return 1;
+}
 
 /*
  * initial DSP configuration for Audigy
@@ -1077,6 +1095,7 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
 static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
 {
        int err, i, z, gpr, nctl;
+       int bit_shifter16;
        const int playback = 10;
        const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
        const int stereo_mix = capture + 2;
@@ -1114,17 +1133,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
        ptr = 0;
        nctl = 0;
        gpr = stereo_mix + 10;
+       gpr_map[gpr++] = 0x00007fff;
+       gpr_map[gpr++] = 0x00008000;
+       gpr_map[gpr++] = 0x0000ffff;
+       bit_shifter16 = gpr;
 
        /* stop FX processor */
        snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
 
-#if 0
-       /* FIX: jcd test */
-       for (z = 0; z < 80; z=z+2) {
-               A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
-               A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
-       }
-#endif /* jcd test */
 #if 1
        /* PCM front Playback Volume (independent from stereo mix) */
        A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
@@ -1182,13 +1198,20 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
        A_OP(icode, &ptr, iMAC0, 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;
-
+      
        /*
         * 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))
 
+       /* emu1212 DSP 0 and DSP 1 Capture */
+       if (emu->card_capabilities->emu1010) {
+               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));
+               snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
+               gpr += 2;
+       }
        /* AC'97 Playback Volume - used only for mic (renamed later) */
        A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
        A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
@@ -1429,6 +1452,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 
        /* digital outputs */
        /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
+       if (emu->card_capabilities->emu1010) {
+               /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
+               snd_printk("EMU outputs on\n");
+               for (z = 0; z < 8; z++) {
+                       A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
+               }
+       }
 
        /* IEC958 Optical Raw Playback Switch */ 
        gpr_map[gpr++] = 0;
@@ -1466,9 +1496,57 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
 #endif
 
-       /* EFX capture - capture the 16 EXTINs */
-       for (z = 0; z < 16; z++) {
-               A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+       if (emu->card_capabilities->emu1010) {
+               snd_printk("EMU inputs on\n");
+               /* Capture 8 channels of S32_LE sound */
+               
+               /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
+               /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
+               /* A_P16VIN(0) is delayed by one sample,
+                * so all other A_P16VIN channels will need to also be delayed
+                */
+               /* Left ADC in. 1 of 2 */
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
+               /* Right ADC in 1 of 2 */
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
+               /* For 96kHz mode */
+               /* Left ADC in. 2 of 2 */
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
+               /* Right ADC in 2 of 2 */
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
+               gpr_map[gpr++] = 0x00000000;
+               snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
+               A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
+
+#if 0
+               for (z = 4; z < 8; z++) {
+                       A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
+               }
+               for (z = 0xc; z < 0x10; z++) {
+                       A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
+               }
+#endif
+       } else {
+               /* EFX capture - capture the 16 EXTINs */
+               /* Capture 16 channels of S16_LE sound */
+               for (z = 0; z < 16; z++) {
+                       A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+               }
        }
        
 #endif /* JCD test */
@@ -2138,7 +2216,7 @@ void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
                snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
 }
 
-#if 0 // FIXME: who use them?
+#if 0 /* FIXME: who use them? */
 int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
 {
        if (output < 0 || output >= 6)
index c31f3d0..c8176dc 100644 (file)
@@ -5,6 +5,9 @@
  *  Routines for control of EMU10K1 chips / mixer routines
  *  Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *     Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -68,6 +71,311 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static char *emu1010_src_texts[] = { 
+       "Silence",
+       "Dock Mic A",
+       "Dock Mic B",
+       "Dock ADC1 Left",
+       "Dock ADC1 Right",
+       "Dock ADC2 Left",
+       "Dock ADC2 Right",
+       "Dock ADC3 Left",
+       "Dock ADC3 Right",
+       "0202 ADC Left",
+       "0202 ADC Right",
+       "0202 SPDIF Left",
+       "0202 SPDIF Right",
+       "ADAT 0",
+       "ADAT 1",
+       "ADAT 2",
+       "ADAT 3",
+       "ADAT 4",
+       "ADAT 5",
+       "ADAT 6",
+       "ADAT 7",
+       "DSP 0",
+       "DSP 1",
+       "DSP 2",
+       "DSP 3",
+       "DSP 4",
+       "DSP 5",
+       "DSP 6",
+       "DSP 7",
+       "DSP 8",
+       "DSP 9",
+       "DSP 10",
+       "DSP 11",
+       "DSP 12",
+       "DSP 13",
+       "DSP 14",
+       "DSP 15",
+       "DSP 16",
+       "DSP 17",
+       "DSP 18",
+       "DSP 19",
+       "DSP 20",
+       "DSP 21",
+       "DSP 22",
+       "DSP 23",
+       "DSP 24",
+       "DSP 25",
+       "DSP 26",
+       "DSP 27",
+       "DSP 28",
+       "DSP 29",
+       "DSP 30",
+       "DSP 31",
+};
+
+static unsigned int emu1010_src_regs[] = {
+       EMU_SRC_SILENCE,/* 0 */
+       EMU_SRC_DOCK_MIC_A1, /* 1 */
+       EMU_SRC_DOCK_MIC_B1, /* 2 */
+       EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
+       EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
+       EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
+       EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
+       EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
+       EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
+       EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
+       EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
+       EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
+       EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
+       EMU_SRC_HANA_ADAT, /* 13 */
+       EMU_SRC_HANA_ADAT+1, /* 14 */
+       EMU_SRC_HANA_ADAT+2, /* 15 */
+       EMU_SRC_HANA_ADAT+3, /* 16 */
+       EMU_SRC_HANA_ADAT+4, /* 17 */
+       EMU_SRC_HANA_ADAT+5, /* 18 */
+       EMU_SRC_HANA_ADAT+6, /* 19 */
+       EMU_SRC_HANA_ADAT+7, /* 20 */
+       EMU_SRC_ALICE_EMU32A, /* 21 */
+       EMU_SRC_ALICE_EMU32A+1, /* 22 */
+       EMU_SRC_ALICE_EMU32A+2, /* 23 */
+       EMU_SRC_ALICE_EMU32A+3, /* 24 */
+       EMU_SRC_ALICE_EMU32A+4, /* 25 */
+       EMU_SRC_ALICE_EMU32A+5, /* 26 */
+       EMU_SRC_ALICE_EMU32A+6, /* 27 */
+       EMU_SRC_ALICE_EMU32A+7, /* 28 */
+       EMU_SRC_ALICE_EMU32A+8, /* 29 */
+       EMU_SRC_ALICE_EMU32A+9, /* 30 */
+       EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
+       EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
+       EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
+       EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
+       EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
+       EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
+       EMU_SRC_ALICE_EMU32B, /* 37 */
+       EMU_SRC_ALICE_EMU32B+1, /* 38 */
+       EMU_SRC_ALICE_EMU32B+2, /* 39 */
+       EMU_SRC_ALICE_EMU32B+3, /* 40 */
+       EMU_SRC_ALICE_EMU32B+4, /* 41 */
+       EMU_SRC_ALICE_EMU32B+5, /* 42 */
+       EMU_SRC_ALICE_EMU32B+6, /* 43 */
+       EMU_SRC_ALICE_EMU32B+7, /* 44 */
+       EMU_SRC_ALICE_EMU32B+8, /* 45 */
+       EMU_SRC_ALICE_EMU32B+9, /* 46 */
+       EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
+       EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
+       EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
+       EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
+       EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
+       EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
+};
+
+static unsigned int emu1010_output_dst[] = {
+       EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
+       EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
+       EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
+       EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
+       EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
+       EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
+       EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
+       EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
+       EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
+       EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
+       EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
+       EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
+       EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
+       EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
+       EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
+       EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
+       EMU_DST_HANA_ADAT, /* 16 */
+       EMU_DST_HANA_ADAT+1, /* 17 */
+       EMU_DST_HANA_ADAT+2, /* 18 */
+       EMU_DST_HANA_ADAT+3, /* 19 */
+       EMU_DST_HANA_ADAT+4, /* 20 */
+       EMU_DST_HANA_ADAT+5, /* 21 */
+       EMU_DST_HANA_ADAT+6, /* 22 */
+       EMU_DST_HANA_ADAT+7, /* 23 */
+};
+
+static unsigned int emu1010_input_dst[] = {
+       EMU_DST_ALICE2_EMU32_0,
+       EMU_DST_ALICE2_EMU32_1,
+       EMU_DST_ALICE2_EMU32_2,
+       EMU_DST_ALICE2_EMU32_3,
+       EMU_DST_ALICE2_EMU32_4,
+       EMU_DST_ALICE2_EMU32_5,
+       EMU_DST_ALICE2_EMU32_6,
+       EMU_DST_ALICE2_EMU32_7,
+       EMU_DST_ALICE2_EMU32_8,
+       EMU_DST_ALICE2_EMU32_9,
+       EMU_DST_ALICE2_EMU32_A,
+       EMU_DST_ALICE2_EMU32_B,
+       EMU_DST_ALICE2_EMU32_C,
+       EMU_DST_ALICE2_EMU32_D,
+       EMU_DST_ALICE2_EMU32_E,
+       EMU_DST_ALICE2_EMU32_F,
+       EMU_DST_ALICE_I2S0_LEFT,
+       EMU_DST_ALICE_I2S0_RIGHT,
+       EMU_DST_ALICE_I2S1_LEFT,
+       EMU_DST_ALICE_I2S1_RIGHT,
+       EMU_DST_ALICE_I2S2_LEFT,
+       EMU_DST_ALICE_I2S2_RIGHT,
+};
+
+static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 53;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       int channel;
+
+       channel = (kcontrol->private_value) & 0xff;
+       ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
+       return 0;
+}
+
+static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       int change = 0;
+       unsigned int val;
+       int channel;
+
+       channel = (kcontrol->private_value) & 0xff;
+       if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
+               val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
+               change = 1;
+               snd_emu1010_fpga_link_dst_src_write(emu,
+                       emu1010_output_dst[channel], emu1010_src_regs[val]);
+       }
+       return change;
+}
+
+static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       int channel;
+
+       channel = (kcontrol->private_value) & 0xff;
+       ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
+       return 0;
+}
+
+static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       int change = 0;
+       unsigned int val;
+       int channel;
+
+       channel = (kcontrol->private_value) & 0xff;
+       if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
+               val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
+               change = 1;
+               snd_emu1010_fpga_link_dst_src_write(emu,
+                       emu1010_input_dst[channel], emu1010_src_regs[val]);
+       }
+       return change;
+}
+
+#define EMU1010_SOURCE_OUTPUT(xname,chid) \
+{                                                              \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
+       .info =  snd_emu1010_input_output_source_info,          \
+       .get =   snd_emu1010_output_source_get,                 \
+       .put =   snd_emu1010_output_source_put,                 \
+       .private_value = chid                                   \
+}
+
+static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Left", 0),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Right", 1),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Left", 2),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Right", 3),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Left", 4),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Right", 5),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Left", 6),
+       EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Right", 7),
+       EMU1010_SOURCE_OUTPUT("Playback Dock Phones Left", 8),
+       EMU1010_SOURCE_OUTPUT("Playback Dock Phones Right", 9),
+       EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Left", 0xa),
+       EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Right", 0xb),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Left", 0xc),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Right", 0xd),
+       EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Left", 0xe),
+       EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Right", 0xf),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 0", 0x10),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 1", 0x11),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 2", 0x12),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 3", 0x13),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 4", 0x14),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 5", 0x15),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 6", 0x16),
+       EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 7", 0x17),
+};
+
+#define EMU1010_SOURCE_INPUT(xname,chid) \
+{                                                              \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
+       .info =  snd_emu1010_input_output_source_info,          \
+       .get =   snd_emu1010_input_source_get,                  \
+       .put =   snd_emu1010_input_source_put,                  \
+       .private_value = chid                                   \
+}
+
+static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
+       EMU1010_SOURCE_INPUT("DSP 0 CAPTURE ENUM", 0),
+       EMU1010_SOURCE_INPUT("DSP 1 CAPTURE ENUM", 1),
+       EMU1010_SOURCE_INPUT("DSP 2 CAPTURE ENUM", 2),
+       EMU1010_SOURCE_INPUT("DSP 3 CAPTURE ENUM", 3),
+       EMU1010_SOURCE_INPUT("DSP 4 CAPTURE ENUM", 4),
+       EMU1010_SOURCE_INPUT("DSP 5 CAPTURE ENUM", 5),
+       EMU1010_SOURCE_INPUT("DSP 6 CAPTURE ENUM", 6),
+       EMU1010_SOURCE_INPUT("DSP 7 CAPTURE ENUM", 7),
+       EMU1010_SOURCE_INPUT("DSP 8 CAPTURE ENUM", 8),
+       EMU1010_SOURCE_INPUT("DSP 9 CAPTURE ENUM", 9),
+       EMU1010_SOURCE_INPUT("DSP A CAPTURE ENUM", 0xa),
+       EMU1010_SOURCE_INPUT("DSP B CAPTURE ENUM", 0xb),
+       EMU1010_SOURCE_INPUT("DSP C CAPTURE ENUM", 0xc),
+       EMU1010_SOURCE_INPUT("DSP D CAPTURE ENUM", 0xd),
+       EMU1010_SOURCE_INPUT("DSP E CAPTURE ENUM", 0xe),
+       EMU1010_SOURCE_INPUT("DSP F CAPTURE ENUM", 0xf),
+       EMU1010_SOURCE_INPUT("DSP 10 CAPTURE ENUM", 0x10),
+       EMU1010_SOURCE_INPUT("DSP 11 CAPTURE ENUM", 0x11),
+       EMU1010_SOURCE_INPUT("DSP 12 CAPTURE ENUM", 0x12),
+       EMU1010_SOURCE_INPUT("DSP 13 CAPTURE ENUM", 0x13),
+       EMU1010_SOURCE_INPUT("DSP 14 CAPTURE ENUM", 0x14),
+       EMU1010_SOURCE_INPUT("DSP 15 CAPTURE ENUM", 0x15),
+};
+
 #if 0
 static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
@@ -1021,7 +1329,7 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                        return err;
        }
 
-       if ( emu->card_capabilities->emu1212m) {
+       if ( emu->card_capabilities->emu1010) {
                ;  /* Disable the snd_audigy_spdif_shared_spdif */
        } else if (emu->audigy) {
                if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
@@ -1045,6 +1353,21 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                if ((err = snd_p16v_mixer(emu)))
                        return err;
        }
+
+       if ( emu->card_capabilities->emu1010) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
+                       err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
+                       if (err < 0)
+                               return err;
+               }
+               for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
+                       err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
+                       if (err < 0)
+                               return err;
+               }
+       }
                
        return 0;
 }
index 717e92e..44d098a 100644 (file)
@@ -147,7 +147,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
                                              1,
                                              &epcm->extra);
                if (err < 0) {
-                       // printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
+                       /* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
                        for (i = 0; i < voices; i++) {
                                snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
                                epcm->voices[i] = NULL;
@@ -339,7 +339,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
                }
        }
 
-       // setup routing
+       /* setup routing */
        if (emu->audigy) {
                snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
                                      snd_emu10k1_compose_audigy_fxrt1(send_routing));
@@ -353,8 +353,8 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        } else
                snd_emu10k1_ptr_write(emu, FXRT, voice,
                                      snd_emu10k1_compose_send_routing(send_routing));
-       // Stop CA
-       // Assumption that PT is already 0 so no harm overwriting
+       /* Stop CA */
+       /* Assumption that PT is already 0 so no harm overwriting */
        snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
        snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
        snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
@@ -367,14 +367,14 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
                snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
                              emu10k1_select_interprom(pitch_target) |
                              (w_16 ? 0 : CCCA_8BITSELECT));
-       // Clear filter delay memory
+       /* Clear filter delay memory */
        snd_emu10k1_ptr_write(emu, Z1, voice, 0);
        snd_emu10k1_ptr_write(emu, Z2, voice, 0);
-       // invalidate maps
+       /* invalidate maps */
        silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
        snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
        snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
-       // modulation envelope
+       /* modulation envelope */
        snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
        snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
        snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
@@ -385,12 +385,12 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
        snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
        snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
-       // volume envelope
+       /* volume envelope */
        snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
        snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
-       // filter envelope
+       /* filter envelope */
        snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
-       // pitch envelope
+       /* pitch envelope */
        snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
 
        spin_unlock_irqrestore(&emu->reg_lock, flags);
@@ -468,7 +468,7 @@ static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream)
                snd_emu10k1_voice_free(epcm->emu, epcm->extra);
                epcm->extra = NULL;
        }
-       for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+       for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
                if (epcm->voices[i]) {
                        snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
                        epcm->voices[i] = NULL;
@@ -637,7 +637,7 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
        stereo = (!extra && runtime->channels == 2);
        sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
        ccis = emu10k1_ccis(stereo, sample == 0);
-       // set cs to 2 * number of cache registers beside the invalidated
+       /* set cs to 2 * number of cache registers beside the invalidated */
        cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
        if (cs > 16) cs = 16;
        for (i = 0; i < cs; i++) {
@@ -646,14 +646,14 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
                        snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
                }
        }
-       // reset cache
+       /* reset cache */
        snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
        snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
        if (stereo) {
                snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
                snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
        }
-       // fill cache
+       /* fill cache */
        snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
        if (stereo) {
                snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
@@ -732,7 +732,7 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
        struct snd_emu10k1_pcm_mixer *mix;
        int result = 0;
 
-       // printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
+       /* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
        spin_lock(&emu->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -778,10 +778,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
-               // hmm this should cause full and half full interrupt to be raised?  
+               /* hmm this should cause full and half full interrupt to be raised? */
                outl(epcm->capture_ipr, emu->port + IPR);
                snd_emu10k1_intr_enable(emu, epcm->capture_inte);
-               // printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
+               /* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
                switch (epcm->type) {
                case CAPTURE_AC97ADC:
                        snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
@@ -790,6 +790,7 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
                        if (emu->audigy) {
                                snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
                                snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
+                               snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2);
                        } else
                                snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
                        break;
@@ -851,7 +852,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *
                        ptr -= runtime->buffer_size;
        }
 #endif
-       // printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
+       /* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
        return ptr;
 }
 
@@ -868,7 +869,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
        spin_lock(&emu->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               // prepare voices
+               /* prepare voices */
                for (i = 0; i < NUM_EFX_PLAYBACK; i++) {        
                        snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
                }
@@ -917,7 +918,7 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *s
        if (!epcm->running)
                return 0;
        if (epcm->first_ptr) {
-               udelay(50);     // hack, it takes awhile until capture is started
+               udelay(50);     /* hack, it takes awhile until capture is started */
                epcm->first_ptr = 0;
        }
        ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
@@ -972,6 +973,28 @@ static struct snd_pcm_hardware snd_emu10k1_capture =
        .fifo_size =            0,
 };
 
+static struct snd_pcm_hardware snd_emu10k1_capture_efx =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_RESUME |
+                                SNDRV_PCM_INFO_MMAP_VALID),
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE,
+       .rates =                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
+                                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 
+                                SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+       .rate_min =             44100,
+       .rate_max =             192000,
+       .channels_min =         8,
+       .channels_max =         8,
+       .buffer_bytes_max =     (64*1024),
+       .period_bytes_min =     384,
+       .period_bytes_max =     (64*1024),
+       .periods_min =          2,
+       .periods_max =          2,
+       .fifo_size =            0,
+};
+
 /*
  *
  */
@@ -1016,7 +1039,7 @@ static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream)
        struct snd_emu10k1_pcm_mixer *mix;
        int i;
 
-       for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+       for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
                mix = &emu->efx_pcm_mixer[i];
                mix->epcm = NULL;
                snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
@@ -1045,7 +1068,7 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
        runtime->private_free = snd_emu10k1_pcm_free_substream;
        runtime->hw = snd_emu10k1_efx_playback;
        
-       for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+       for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
                mix = &emu->efx_pcm_mixer[i];
                mix->send_routing[0][0] = i;
                memset(&mix->send_volume, 0, sizeof(mix->send_volume));
@@ -1199,15 +1222,59 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
        epcm->capture_idx_reg = FXIDX;
        substream->runtime->private_data = epcm;
        substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
-       runtime->hw = snd_emu10k1_capture;
+       runtime->hw = snd_emu10k1_capture_efx;
        runtime->hw.rates = SNDRV_PCM_RATE_48000;
        runtime->hw.rate_min = runtime->hw.rate_max = 48000;
        spin_lock_irq(&emu->reg_lock);
-       runtime->hw.channels_min = runtime->hw.channels_max = 0;
-       for (idx = 0; idx < nefx; idx++) {
-               if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
-                       runtime->hw.channels_min++;
-                       runtime->hw.channels_max++;
+       if (emu->card_capabilities->emu1010) {
+               /* TODO 
+                * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
+                * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+                * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+                * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
+                * rate_min = 44100,
+                * rate_max = 192000,
+                * channels_min = 8,
+                * channels_max = 8,
+                * Need to add mixer control to fix sample rate
+                *                 
+                * There are 16 mono channels of 16bits each.
+                * 24bit Audio uses 2x channels over 16bit
+                * 96kHz uses 2x channels over 48kHz
+                * 192kHz uses 4x channels over 48kHz
+                * So, for 48kHz 24bit, one has 8 channels
+                * for 96kHz 24bit, one has 4 channels
+                * for 192kHz 24bit, one has 2 channels
+                */
+#if 1
+               /* For 48kHz */
+               runtime->hw.rates = SNDRV_PCM_RATE_48000;
+               runtime->hw.rate_min = runtime->hw.rate_max = 48000;
+               runtime->hw.channels_min = runtime->hw.channels_max = 8;
+#endif
+#if 0
+               /* For 96kHz */
+               runtime->hw.rates = SNDRV_PCM_RATE_96000;
+               runtime->hw.rate_min = runtime->hw.rate_max = 96000;
+               runtime->hw.channels_min = runtime->hw.channels_max = 4;
+#endif
+#if 0
+               /* For 192kHz */
+               runtime->hw.rates = SNDRV_PCM_RATE_192000;
+               runtime->hw.rate_min = runtime->hw.rate_max = 192000;
+               runtime->hw.channels_min = runtime->hw.channels_max = 2;
+#endif
+               runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+               /* efx_voices_mask[0] is expected to be zero
+                * efx_voices_mask[1] is expected to have 16bits set
+                */
+       } else {
+               runtime->hw.channels_min = runtime->hw.channels_max = 0;
+               for (idx = 0; idx < nefx; idx++) {
+                       if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
+                               runtime->hw.channels_min++;
+                               runtime->hw.channels_max++;
+                       }
                }
        }
        epcm->capture_cr_val = emu->efx_voices_mask[0];
@@ -1460,7 +1527,7 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
                                                   unsigned int count,
                                                   unsigned int tram_shift)
 {
-       // printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+       /* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
        if ((tram_shift & 1) == 0) {
                while (count--) {
                        *dst_left-- = *src++;
@@ -1537,7 +1604,7 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre
        struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
        unsigned int i;
        
-       // printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+       /* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
        memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
        pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
        pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
index b939e03..2c15859 100644 (file)
@@ -3,6 +3,9 @@
  *                   Creative Labs, Inc.
  *  Routines for control of EMU10K1 chips / proc interface routines
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *     Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -255,7 +258,7 @@ static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry,
        unsigned int val, tmp, n;
        val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
        tmp = (val >> 16) & 0x8;
-       for (n=0;n<4;n++) {
+       for (n = 0; n < 4; n++) {
                tmp = val >> (16 + (n*4));
                if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
                else snd_iprintf(buffer, "Channel %d: No input\n", n);
@@ -372,6 +375,27 @@ static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
 }
 
 #ifdef CONFIG_SND_DEBUG
+static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
+                                    struct snd_info_buffer *buffer)
+{
+       struct snd_emu10k1 *emu = entry->private_data;
+       unsigned long value;
+       unsigned long flags;
+       unsigned long regs;
+       int i;
+       snd_iprintf(buffer, "EMU1010 Registers:\n\n");
+
+       for(i = 0; i < 0x30; i+=1) {
+               spin_lock_irqsave(&emu->emu_lock, flags);
+               regs=i+0x40; /* 0x40 upwards are registers. */
+               outl(regs, emu->port + A_IOCFG);
+               outl(regs | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+               value = inl(emu->port + A_IOCFG);
+               spin_unlock_irqrestore(&emu->emu_lock, flags);
+               snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f);
+       }
+}
+
 static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
                                     struct snd_info_buffer *buffer)
 {
@@ -398,7 +422,7 @@ static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
                if (sscanf(line, "%x %x", &reg, &val) != 2)
                        continue;
-               if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) {
+               if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) {
                        spin_lock_irqsave(&emu->emu_lock, flags);
                        outl(val, emu->port + (reg & 0xfffffffc));
                        spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -474,7 +498,7 @@ static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
                if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
                        continue;
-               if ((reg < 0xa0) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
+               if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) )
                        snd_ptr_write(emu, iobase, reg, channel_id, val);
        }
 }
@@ -531,6 +555,10 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
 {
        struct snd_info_entry *entry;
 #ifdef CONFIG_SND_DEBUG
+       if ((emu->card_capabilities->emu1010) &&
+            snd_card_proc_new(emu->card, "emu1010_regs", &entry)) {
+               snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
+       }
        if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
                snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
                entry->c.text.write = snd_emu_proc_io_reg_write;
index 029e785..27ab7d1 100644 (file)
@@ -167,6 +167,51 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
        return 0;
 }
 
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
+{
+       if (reg < 0 || reg > 0x3f)
+               return 1;
+       reg += 0x40; /* 0x40 upwards are registers. */
+       if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
+               return 1;
+       outl(reg, emu->port + A_IOCFG);
+       udelay(10);
+       outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+       udelay(10);
+       outl(value, emu->port + A_IOCFG);
+       udelay(10);
+       outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+
+       return 0;
+}
+
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
+{
+       if (reg < 0 || reg > 0x3f)
+               return 1;
+       reg += 0x40; /* 0x40 upwards are registers. */
+       outl(reg, emu->port + A_IOCFG);
+       udelay(10);
+       outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+       udelay(10);
+       *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
+
+       return 0;
+}
+
+/* Each Destination has one and only one Source,
+ * but one Source can feed any number of Destinations simultaneously.
+ */
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src)
+{
+       snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
+       snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
+       snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
+       snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
+
+       return 0;
+}
+
 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
 {
        unsigned long flags;
index 4e0f954..5da637c 100644 (file)
@@ -253,7 +253,7 @@ static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        //struct snd_pcm_runtime *runtime = substream->runtime;
        //struct snd_emu10k1_pcm *epcm = runtime->private_data;
-       emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+       emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
        /* FIXME: maybe zero others */
        return 0;
 }
@@ -264,7 +264,7 @@ static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        //struct snd_pcm_runtime *runtime = substream->runtime;
        //struct snd_emu10k1_pcm *epcm = runtime->private_data;
-       emu->p16v_capture_voice.use=0;
+       emu->p16v_capture_voice.use = 0;
        /* FIXME: maybe zero others */
        return 0;
 }
@@ -349,7 +349,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
          break;
        }
        /* FIXME: Check emu->buffer.size before actually writing to it. */
-       for(i=0; i < runtime->periods; i++) {
+       for(i = 0; i < runtime->periods; i++) {
                table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
                table_base[(i*2)+1]=period_size_bytes<<16;
        }
@@ -394,7 +394,7 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
        /* FIXME: Check emu->buffer.size before actually writing to it. */
        snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
        snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
-       snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
+       snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
        snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
        //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
        //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
@@ -437,7 +437,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
         struct snd_pcm_substream *s;
        u32 basic = 0;
        u32 inte = 0;
-       int running=0;
+       int running = 0;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -445,7 +445,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        default:
-               running=0;
+               running = 0;
                break;
        }
         snd_pcm_group_for_each(pos, substream) {
index 94eca82..1db50fe 100644 (file)
@@ -83,7 +83,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
        if (first_voice == last_voice)
                return -ENOMEM;
        
-       for (i=0; i < number; i++) {
+       for (i = 0; i < number; i++) {
                voice = &emu->voices[(first_voice + i) % NUM_G];
                // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
                voice->use = 1;