summaryrefslogtreecommitdiff
path: root/sound/pci/emu10k1/emu10k1_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/emu10k1/emu10k1_main.c')
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c957
1 files changed, 326 insertions, 631 deletions
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 3880f359e688..b2fe2d164ba8 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1,19 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ * James Courtier-Dutton <James@superbug.co.uk>
+ * Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
* Creative Labs, Inc.
- * Routines for control of EMU10K1 chips
- *
- * 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:
- * --
- *
- * TODO:
- * --
+ * Routines for control of EMU10K1 chips
*/
#include <linux/sched.h>
@@ -57,46 +49,49 @@ MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME);
void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch)
{
- snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
- snd_emu10k1_ptr_write(emu, IP, ch, 0);
- snd_emu10k1_ptr_write(emu, VTFT, ch, 0xffff);
- snd_emu10k1_ptr_write(emu, CVCF, ch, 0xffff);
- snd_emu10k1_ptr_write(emu, PTRX, ch, 0);
- snd_emu10k1_ptr_write(emu, CPF, ch, 0);
- snd_emu10k1_ptr_write(emu, CCR, ch, 0);
-
- snd_emu10k1_ptr_write(emu, PSST, ch, 0);
- snd_emu10k1_ptr_write(emu, DSL, ch, 0x10);
- snd_emu10k1_ptr_write(emu, CCCA, ch, 0);
- snd_emu10k1_ptr_write(emu, Z1, ch, 0);
- snd_emu10k1_ptr_write(emu, Z2, ch, 0);
- snd_emu10k1_ptr_write(emu, FXRT, ch, 0x32100000);
-
- snd_emu10k1_ptr_write(emu, ATKHLDM, ch, 0);
- snd_emu10k1_ptr_write(emu, DCYSUSM, ch, 0);
- snd_emu10k1_ptr_write(emu, IFATN, ch, 0xffff);
- snd_emu10k1_ptr_write(emu, PEFE, ch, 0);
- snd_emu10k1_ptr_write(emu, FMMOD, ch, 0);
- snd_emu10k1_ptr_write(emu, TREMFRQ, ch, 24); /* 1 Hz */
- snd_emu10k1_ptr_write(emu, FM2FRQ2, ch, 24); /* 1 Hz */
- snd_emu10k1_ptr_write(emu, TEMPENV, ch, 0);
-
- /*** these are last so OFF prevents writing ***/
- snd_emu10k1_ptr_write(emu, LFOVAL2, ch, 0);
- snd_emu10k1_ptr_write(emu, LFOVAL1, ch, 0);
- snd_emu10k1_ptr_write(emu, ATKHLDV, ch, 0);
- snd_emu10k1_ptr_write(emu, ENVVOL, ch, 0);
- snd_emu10k1_ptr_write(emu, ENVVAL, ch, 0);
+ snd_emu10k1_ptr_write_multiple(emu, ch,
+ DCYSUSV, 0,
+ VTFT, VTFT_FILTERTARGET_MASK,
+ CVCF, CVCF_CURRENTFILTER_MASK,
+ PTRX, 0,
+ CPF, 0,
+ CCR, 0,
+
+ PSST, 0,
+ DSL, 0x10,
+ CCCA, 0,
+ Z1, 0,
+ Z2, 0,
+ FXRT, 0x32100000,
+
+ // The rest is meaningless as long as DCYSUSV_CHANNELENABLE_MASK is zero
+ DCYSUSM, 0,
+ ATKHLDV, 0,
+ ATKHLDM, 0,
+ IP, 0,
+ IFATN, IFATN_FILTERCUTOFF_MASK | IFATN_ATTENUATION_MASK,
+ PEFE, 0,
+ FMMOD, 0,
+ TREMFRQ, 24, /* 1 Hz */
+ FM2FRQ2, 24, /* 1 Hz */
+ LFOVAL2, 0,
+ LFOVAL1, 0,
+ ENVVOL, 0,
+ ENVVAL, 0,
+
+ REGLIST_END);
/* Audigy extra stuffs */
if (emu->audigy) {
- snd_emu10k1_ptr_write(emu, 0x4c, ch, 0); /* ?? */
- snd_emu10k1_ptr_write(emu, 0x4d, ch, 0); /* ?? */
- snd_emu10k1_ptr_write(emu, 0x4e, ch, 0); /* ?? */
- snd_emu10k1_ptr_write(emu, 0x4f, ch, 0); /* ?? */
- snd_emu10k1_ptr_write(emu, A_FXRT1, ch, 0x03020100);
- snd_emu10k1_ptr_write(emu, A_FXRT2, ch, 0x3f3f3f3f);
- snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, ch, 0);
+ snd_emu10k1_ptr_write_multiple(emu, ch,
+ A_CSBA, 0,
+ A_CSDC, 0,
+ A_CSFE, 0,
+ A_CSHG, 0,
+ A_FXRT1, 0x03020100,
+ A_FXRT2, 0x07060504,
+ A_SENDAMOUNTS, 0,
+ REGLIST_END);
}
}
@@ -140,7 +135,7 @@ static const unsigned int i2c_adc_init[][2] = {
{ 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */
};
-static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
+static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir)
{
unsigned int silent_page;
int ch;
@@ -150,20 +145,26 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK |
HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
- /* reset recording buffers */
- snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE);
- snd_emu10k1_ptr_write(emu, MICBA, 0, 0);
- snd_emu10k1_ptr_write(emu, FXBS, 0, ADCBS_BUFSIZE_NONE);
- snd_emu10k1_ptr_write(emu, FXBA, 0, 0);
- snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE);
- snd_emu10k1_ptr_write(emu, ADCBA, 0, 0);
-
- /* disable channel interrupt */
outl(0, emu->port + INTE);
- snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
- snd_emu10k1_ptr_write(emu, CLIEH, 0, 0);
- snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
- snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
+
+ snd_emu10k1_ptr_write_multiple(emu, 0,
+ /* reset recording buffers */
+ MICBS, ADCBS_BUFSIZE_NONE,
+ MICBA, 0,
+ FXBS, ADCBS_BUFSIZE_NONE,
+ FXBA, 0,
+ ADCBS, ADCBS_BUFSIZE_NONE,
+ ADCBA, 0,
+
+ /* disable channel interrupt */
+ CLIEL, 0,
+ CLIEH, 0,
+
+ /* disable stop on loop end */
+ SOLEL, 0,
+ SOLEH, 0,
+
+ REGLIST_END);
if (emu->audigy) {
/* set SPDIF bypass mode */
@@ -177,17 +178,17 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
for (ch = 0; ch < NUM_G; ch++)
snd_emu10k1_voice_init(emu, ch);
- snd_emu10k1_ptr_write(emu, SPCS0, 0, emu->spdif_bits[0]);
- snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]);
- snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]);
+ snd_emu10k1_ptr_write_multiple(emu, 0,
+ SPCS0, emu->spdif_bits[0],
+ SPCS1, emu->spdif_bits[1],
+ SPCS2, emu->spdif_bits[2],
+ REGLIST_END);
- if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
+ if (emu->card_capabilities->emu_model) {
+ } else if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
/* Setup SRCMulti_I2S SamplingRate */
- tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
- tmp &= 0xfffff1ff;
- tmp |= (0x2<<9);
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
+ snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000);
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
@@ -199,32 +200,26 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
outl(0x0201, emu->port + HCFG2);
/* Set playback routing. */
snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
- }
- if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
+ } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
dev_info(emu->card->dev, "Audigy2 value: Special config.\n");
/* Setup SRCMulti_I2S SamplingRate */
- tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
- tmp &= 0xfffff1ff;
- tmp |= (0x2<<9);
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
+ snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000);
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
- outl(0x600000, emu->port + 0x20);
- outl(0x14, emu->port + 0x24);
+ snd_emu10k1_ptr20_write(emu, P17V_SRCSel, 0, 0x14);
/* Setup SRCMulti Input Audio Enable */
- outl(0x7b0000, emu->port + 0x20);
- outl(0xFF000000, emu->port + 0x24);
+ snd_emu10k1_ptr20_write(emu, P17V_MIXER_I2S_ENABLE, 0, 0xFF000000);
/* Setup SPDIF Out Audio Enable */
/* The Audigy 2 Value has a separate SPDIF out,
* so no need for a mixer switch
*/
- outl(0x7a0000, emu->port + 0x20);
- outl(0xFF000000, emu->port + 0x24);
- tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
- outl(tmp, emu->port + A_IOCFG);
+ snd_emu10k1_ptr20_write(emu, P17V_MIXER_SPDIF_ENABLE, 0, 0xFF000000);
+
+ tmp = inw(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
+ outw(tmp, emu->port + A_IOCFG);
}
if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */
int size, n;
@@ -244,15 +239,15 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
* GPIO6: Unknown
* GPIO7: Unknown
*/
- outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
+ outw(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
}
if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
int size, n;
snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f);
- tmp = inl(emu->port + A_IOCFG);
- outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */
- tmp = inl(emu->port + A_IOCFG);
+ tmp = inw(emu->port + A_IOCFG);
+ outw(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */
+ tmp = inw(emu->port + A_IOCFG);
size = ARRAY_SIZE(i2c_adc_init);
for (n = 0; n < size; n++)
snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
@@ -265,7 +260,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
- snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
+ snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_256K); /* taken from original driver */
silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
for (ch = 0; ch < NUM_G; ch++) {
@@ -308,12 +303,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
} else if (emu->card_capabilities->i2c_adc) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
} else if (emu->audigy) {
- unsigned int reg = inl(emu->port + A_IOCFG);
- outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
+ u16 reg = inw(emu->port + A_IOCFG);
+ outw(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
udelay(500);
- outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
+ outw(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
udelay(100);
- outl(reg, emu->port + A_IOCFG);
+ outw(reg, emu->port + A_IOCFG);
} else {
unsigned int reg = inl(emu->port + HCFG);
outl(reg | HCFG_GPOUT2, emu->port + HCFG);
@@ -329,8 +324,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
} else if (emu->card_capabilities->i2c_adc) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
} else if (emu->audigy) { /* enable analog output */
- unsigned int reg = inl(emu->port + A_IOCFG);
- outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
+ u16 reg = inw(emu->port + A_IOCFG);
+ outw(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
}
if (emu->address_mode == 0) {
@@ -354,19 +349,19 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
} else if (emu->card_capabilities->i2c_adc) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
} else if (emu->audigy) {
- outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
+ outw(inw(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Unmute Analog now. Set GPO6 to 1 for Apollo.
* This has to be done after init ALice3 I2SOut beyond 48KHz.
* So, sequence is important. */
- outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG);
+ outw(inw(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG);
} else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */
/* Unmute Analog now. */
- outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG);
+ outw(inw(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG);
} else {
/* Disable routing from AC97 line out to Front speakers */
- outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG);
+ outw(inw(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG);
}
}
@@ -388,7 +383,10 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
}
#endif
- snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
+ if (emu->card_capabilities->emu_model)
+ snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE | INTE_A_GPIOENABLE);
+ else
+ snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
}
int snd_emu10k1_done(struct snd_emu10k1 *emu)
@@ -398,41 +396,48 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
outl(0, emu->port + INTE);
/*
- * Shutdown the chip
+ * Shutdown the voices
*/
- for (ch = 0; ch < NUM_G; ch++)
- snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
for (ch = 0; ch < NUM_G; ch++) {
- snd_emu10k1_ptr_write(emu, VTFT, ch, 0);
- snd_emu10k1_ptr_write(emu, CVCF, ch, 0);
- snd_emu10k1_ptr_write(emu, PTRX, ch, 0);
- snd_emu10k1_ptr_write(emu, CPF, ch, 0);
+ snd_emu10k1_ptr_write_multiple(emu, ch,
+ DCYSUSV, 0,
+ VTFT, 0,
+ CVCF, 0,
+ PTRX, 0,
+ CPF, 0,
+ REGLIST_END);
}
- /* reset recording buffers */
- snd_emu10k1_ptr_write(emu, MICBS, 0, 0);
- snd_emu10k1_ptr_write(emu, MICBA, 0, 0);
- snd_emu10k1_ptr_write(emu, FXBS, 0, 0);
- snd_emu10k1_ptr_write(emu, FXBA, 0, 0);
- snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
- snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE);
- snd_emu10k1_ptr_write(emu, ADCBA, 0, 0);
- snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K);
- snd_emu10k1_ptr_write(emu, TCB, 0, 0);
+ // stop the DSP
if (emu->audigy)
snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP);
else
snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP);
- /* disable channel interrupt */
- snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
- snd_emu10k1_ptr_write(emu, CLIEH, 0, 0);
- snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
- snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
+ snd_emu10k1_ptr_write_multiple(emu, 0,
+ /* reset recording buffers */
+ MICBS, 0,
+ MICBA, 0,
+ FXBS, 0,
+ FXBA, 0,
+ FXWC, 0,
+ ADCBS, ADCBS_BUFSIZE_NONE,
+ ADCBA, 0,
+ TCBS, TCBS_BUFFSIZE_16K,
+ TCB, 0,
+
+ /* disable channel interrupt */
+ CLIEL, 0,
+ CLIEH, 0,
+ SOLEL, 0,
+ SOLEH, 0,
+
+ PTB, 0,
+
+ REGLIST_END);
/* disable audio and lock cache */
outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
- snd_emu10k1_ptr_write(emu, PTB, 0, 0);
return 0;
}
@@ -647,52 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
return 0;
}
-static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu,
- const struct firmware *fw_entry)
-{
- int n, i;
- int reg;
- int value;
- __always_unused unsigned int write_post;
- unsigned long flags;
-
- if (!fw_entry)
- return -EIO;
-
- /* The FPGA is a Xilinx Spartan IIE XC2S50E */
- /* GPIO7 -> FPGA PGMN
- * GPIO6 -> FPGA CCLK
- * GPIO5 -> FPGA DIN
- * FPGA CONFIG OFF -> FPGA PGMN
- */
- spin_lock_irqsave(&emu->emu_lock, flags);
- outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */
- write_post = inl(emu->port + A_IOCFG);
- udelay(100);
- outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
- write_post = inl(emu->port + A_IOCFG);
- 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);
- write_post = inl(emu->port + A_IOCFG);
- outl(reg | 0x40, emu->port + A_IOCFG);
- write_post = inl(emu->port + A_IOCFG);
- }
- }
- /* After programming, set GPIO bit 4 high again. */
- outl(0x10, emu->port + A_IOCFG);
- write_post = inl(emu->port + A_IOCFG);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
-
- return 0;
-}
-
/* firmware file names, per model, init-fw and dock-fw (optional) */
static const char * const firmware_names[5][2] = {
[EMU_MODEL_EMU1010] = {
@@ -724,99 +683,117 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
return err;
}
- return snd_emu1010_load_firmware_entry(emu, *fw);
+ snd_emu1010_load_firmware_entry(emu, dock, *fw);
+ return 0;
}
-static void emu1010_firmware_work(struct work_struct *work)
+static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu)
{
- struct snd_emu10k1 *emu;
- u32 tmp, tmp2, reg;
+ u32 tmp, tmp2;
int err;
- emu = container_of(work, struct snd_emu10k1,
- emu1010.firmware_work.work);
- if (emu->card->shutdown)
+ // The docking events clearly arrive prematurely - while the
+ // Dock's FPGA seems to be successfully programmed, the Dock
+ // fails to initialize subsequently if we don't give it some
+ // time to "warm up" here.
+ msleep(200);
+
+ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
+ err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
+ if (err < 0)
return;
-#ifdef CONFIG_PM_SLEEP
- if (emu->suspend)
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
+
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
+ dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
+ if ((tmp & 0x1f) != 0x15) {
+ /* FPGA failed to be programmed */
+ dev_err(emu->card->dev,
+ "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
+ tmp);
return;
-#endif
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
+ }
+ dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
+
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
+ dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
+
+ /* Allow DLL to settle, to sync clocking between 1010 and Dock */
+ msleep(10);
+}
+
+static void emu1010_dock_event(struct snd_emu10k1 *emu)
+{
+ u32 reg;
+
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
- /* Return to Audio Dock programming mode */
- dev_info(emu->card->dev,
- "emu1010: Loading Audio Dock Firmware\n");
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
- EMU_HANA_FPGA_CONFIG_AUDIODOCK);
- err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
- if (err < 0)
- goto next;
-
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp);
- dev_info(emu->card->dev,
- "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp);
- /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
- dev_info(emu->card->dev,
- "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
- if ((tmp & 0x1f) != 0x15) {
- /* FPGA failed to be programmed */
- dev_info(emu->card->dev,
- "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
- tmp);
- goto next;
- }
- dev_info(emu->card->dev,
- "emu1010: Audio Dock Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
- dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
- /* Sync clocking between 1010 and Dock */
- /* Allow DLL to settle */
- msleep(10);
+ snd_emu1010_load_dock_firmware(emu);
/* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
- } else if (!reg && emu->emu1010.last_reg) {
+ } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
/* Audio Dock removed */
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
- /* Unmute all */
+ /* The hardware auto-mutes all, so we unmute again */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
}
+}
+
+static void emu1010_clock_event(struct snd_emu10k1 *emu)
+{
+ struct snd_ctl_elem_id id;
+
+ scoped_guard(spinlock_irq, &emu->reg_lock) {
+ // This is the only thing that can actually happen.
+ emu->emu1010.clock_source = emu->emu1010.clock_fallback;
+ emu->emu1010.wclock = 1 - emu->emu1010.clock_source;
+ snd_emu1010_update_clock(emu);
+ }
+ snd_ctl_build_ioff(&id, emu->ctl_clock_source, 0);
+ snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+}
+
+static void emu1010_work(struct work_struct *work)
+{
+ struct snd_emu10k1 *emu;
+ u32 sts;
+
+ emu = container_of(work, struct snd_emu10k1, emu1010.work);
+ if (emu->card->shutdown)
+ return;
+#ifdef CONFIG_PM_SLEEP
+ if (emu->suspend)
+ return;
+#endif
+
+ guard(snd_emu1010_fpga_lock)(emu);
+
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
+
+ // The distinction of the IRQ status bits is unreliable,
+ // so we dispatch later based on option card status.
+ if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
+ emu1010_dock_event(emu);
+
+ if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
+ emu1010_clock_event(emu);
+}
- next:
- emu->emu1010.last_reg = reg;
- if (!emu->card->shutdown)
- schedule_delayed_work(&emu->emu1010.firmware_work,
- msecs_to_jiffies(1000));
+static void emu1010_interrupt(struct snd_emu10k1 *emu)
+{
+ // We get an interrupt on each GPIO input pin change, but we
+ // care only about the ones triggered by the dedicated pin.
+ u16 sts = inw(emu->port + A_GPIO);
+ u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000;
+ if (!(sts & bit))
+ return;
+
+ schedule_work(&emu->emu1010.work);
}
/*
- * EMU-1010 - details found out from this driver, official MS Win drivers,
- * testing the card:
- *
- * Audigy2 (aka Alice2):
- * ---------------------
- * * communication over PCI
- * * conversion of 32-bit data coming over EMU32 links from HANA FPGA
- * to 2 x 16-bit, using internal DSP instructions
- * * slave mode, clock supplied by HANA
- * * linked to HANA using:
- * 32 x 32-bit serial EMU32 output channels
- * 16 x EMU32 input channels
- * (?) x I2S I/O channels (?)
- *
- * FPGA (aka HANA):
- * ---------------
- * * provides all (?) physical inputs and outputs of the card
- * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.)
- * * provides clock signal for the card and Alice2
- * * two crystals - for 44.1kHz and 48kHz multiples
- * * provides internal routing of signal sources to signal destinations
- * * inputs/outputs to Alice2 - see above
- *
* Current status of the driver:
* ----------------------------
* * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz)
@@ -826,52 +803,18 @@ static void emu1010_firmware_work(struct work_struct *work)
*/
static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
{
- unsigned int i;
u32 tmp, tmp2, reg;
int err;
dev_info(emu->card->dev, "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);
- /* 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);
- /* 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);
- dev_dbg(emu->card->dev, "reg1 = 0x%x\n", reg);
- if ((reg & 0x3f) == 0x15) {
- /* FPGA netlist already present so clear it */
- /* Return to programming mode */
+ /* Mute, and disable audio and lock cache, just in case.
+ * Proper init follows in snd_emu10k1_init(). */
+ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02);
- }
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
- dev_dbg(emu->card->dev, "reg2 = 0x%x\n", reg);
- if ((reg & 0x3f) == 0x15) {
- /* FPGA failed to return to programming mode */
- dev_info(emu->card->dev,
- "emu1010: FPGA failed to return to programming mode\n");
- return -ENODEV;
- }
- dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg);
+ guard(snd_emu1010_fpga_lock)(emu);
+ dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n");
err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
if (err < 0) {
dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
@@ -897,339 +840,53 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp);
- /* Optical -> ADAT I/O */
- /* 0 : SPDIF
- * 1 : ADAT
- */
- emu->emu1010.optical_in = 1; /* IN_ADAT */
- emu->emu1010.optical_out = 1; /* IN_ADAT */
- tmp = 0;
- tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
- (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
+ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
+ snd_emu1010_load_dock_firmware(emu);
+ if (emu->card_capabilities->no_adat) {
+ emu->emu1010.optical_in = 0; /* IN_SPDIF */
+ emu->emu1010.optical_out = 0; /* OUT_SPDIF */
+ } else {
+ /* Optical -> ADAT I/O */
+ emu->emu1010.optical_in = 1; /* IN_ADAT */
+ emu->emu1010.optical_out = 1; /* OUT_ADAT */
+ }
+ tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
+ (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
- snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp);
/* Set no attenuation on Audio Dock pads. */
- snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00);
emu->emu1010.adc_pads = 0x00;
- snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, emu->emu1010.adc_pads);
/* 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_DAC_PADS, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, EMU_HANA_DOCK_PHONES_192_DAC4);
/* DAC PADs. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f);
- emu->emu1010.dac_pads = 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);
+ emu->emu1010.dac_pads = EMU_HANA_DOCK_DAC_PAD1 | EMU_HANA_DOCK_DAC_PAD2 |
+ EMU_HANA_DOCK_DAC_PAD3 | EMU_HANA_DOCK_DAC_PAD4;
+ snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, emu->emu1010.dac_pads);
/* SPDIF Format. Set Consumer mode, 24bit, copy enable */
- snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10);
+ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, EMU_HANA_SPDIF_MODE_RX_INVALID);
/* MIDI routing */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
- /* Unknown. */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
- /* IRQ Enable: All on */
- /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
- /* IRQ Enable: All off */
- snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, EMU_HANA_MIDI_INA_FROM_HAMOA | EMU_HANA_MIDI_INB_FROM_DOCK2);
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, EMU_HANA_MIDI_OUT_DOCK2 | EMU_HANA_MIDI_OUT_SYNC2);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- dev_info(emu->card->dev, "emu1010: Card options3 = 0x%x\n", reg);
+ emu->gpio_interrupt = emu1010_interrupt;
+ // Note: The Audigy INTE is set later
+ snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE,
+ EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST | EMU_HANA_IRQ_WCLK_CHANGED);
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg); // Clear pending IRQs
+
+ emu->emu1010.clock_source = 1; /* 48000 */
+ emu->emu1010.clock_fallback = 1; /* 48000 */
/* Default WCLK set to 48kHz. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K);
/* Word Clock source, Internal 48kHz x1 */
+ emu->emu1010.wclock = EMU_HANA_WCLOCK_INT_48K;
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);
+ snd_emu1010_update_clock(emu);
-#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);
- /* Pavel Hofman - setting defaults for 8 more capture channels
- * Defaults only, users will set their own values anyways, let's
- * just copy/paste.
- */
-
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1);
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_ALICE2_EMU32_F, 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_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp);
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 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) */
-
-#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 */
- if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
- /* 1616(M) cardbus default outputs */
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- emu->emu1010.output_source[0] = 17;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
- emu->emu1010.output_source[1] = 18;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2);
- emu->emu1010.output_source[2] = 19;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3);
- emu->emu1010.output_source[3] = 20;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4);
- emu->emu1010.output_source[4] = 21;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5);
- emu->emu1010.output_source[5] = 22;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_MANA_DAC_LEFT, EMU_SRC_ALICE_EMU32A + 0);
- emu->emu1010.output_source[16] = 17;
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_MANA_DAC_RIGHT, EMU_SRC_ALICE_EMU32A + 1);
- emu->emu1010.output_source[17] = 18;
- } else {
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- 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;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- 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;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- 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;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- 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;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0);
- 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;
- /* ALICE2 bus 0xa0 */
- snd_emu1010_fpga_link_dst_src_write(emu,
- EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0);
- 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); */
- emu->emu1010.internal_clock = 1; /* 48000 */
- 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 */
+ // The routes are all set to EMU_SRC_SILENCE due to the reset,
+ // so it is safe to simply enable the outputs.
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
return 0;
}
@@ -1253,9 +910,10 @@ static void snd_emu10k1_free(struct snd_card *card)
}
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
/* Disable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+ snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0);
}
- cancel_delayed_work_sync(&emu->emu1010.firmware_work);
+ cancel_work_sync(&emu->emu1010.work);
+ mutex_destroy(&emu->emu1010.lock);
release_firmware(emu->firmware);
release_firmware(emu->dock_fw);
snd_util_memhdr_free(emu->memhdr);
@@ -1343,6 +1001,15 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
* AC97: STAC9750
* CA0151: None
*/
+ /*
+ * A_IOCFG Input (GPIO)
+ * 0x400 = Front analog jack plugged in. (Green socket)
+ * 0x1000 = Rear analog jack plugged in. (Black socket)
+ * 0x2000 = Center/LFE analog jack plugged in. (Orange socket)
+ * A_IOCFG Output (GPIO)
+ * 0x60 = Sound out of front Left.
+ * Win sets it to 0xXX61
+ */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
.driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]",
.id = "Audigy2",
@@ -1391,9 +1058,12 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.spi_dac = 1,
.i2c_adc = 1,
.spk71 = 1} ,
+ /* This is MAEM8950 "Mana" */
+ /* Attach MicroDock[M] to make it an E-MU 1616[m]. */
+ /* Does NOT support sync daughter card (obviously). */
/* Tested by James@superbug.co.uk 4th Nov 2007. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102,
- .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]",
+ .driver = "Audigy2", .name = "E-MU 02 CardBus [MAEM8950]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1401,9 +1071,12 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.spk71 = 1 ,
.emu_model = EMU_MODEL_EMU1616},
/* Tested by James@superbug.co.uk 4th Nov 2007. */
- /* This is MAEM8960, 0202 is MAEM 8980 */
+ /* This is MAEM8960 "Hana3", 0202 is MAEM8980 */
+ /* Attach 0202 daughter card to make it an E-MU 1212m, OR a
+ * MicroDock[M] to make it an E-MU 1616[m]. */
+ /* Does NOT support sync daughter card. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102,
- .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]",
+ .driver = "Audigy2", .name = "E-MU 1010b PCI [MAEM8960]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1411,47 +1084,62 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
/* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
/* This is MAEM8986, 0202 is MAEM8980 */
+ /* Attach 0202 daughter card to make it an E-MU 1212m, OR a
+ * MicroDockM to make it an E-MU 1616m. The non-m
+ * version was never sold with this card, but should
+ * still work. */
+ /* Does NOT support sync daughter card. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102,
- .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]",
+ .driver = "Audigy2", .name = "E-MU 1010 PCIe [MAEM8986]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
.emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */
/* Tested by James@superbug.co.uk 8th July 2005. */
- /* This is MAEM8810, 0202 is MAEM8820 */
+ /* This is MAEM8810 "Hana", 0202 is MAEM8820 "Hamoa" */
+ /* Attach 0202 daughter card to make it an E-MU 1212m, OR an
+ * AudioDock[M] to make it an E-MU 1820[m]. */
+ /* Supports sync daughter card. */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
- .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]",
+ .driver = "Audigy2", .name = "E-MU 1010 [MAEM8810]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spk71 = 1,
.emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */
- /* EMU0404b */
+ /* This is MAEM8852 "HanaLiteLite" */
+ /* Supports sync daughter card. */
+ /* Tested by oswald.buddenhagen@gmx.de Mar 2023. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]",
+ .driver = "Audigy2", .name = "E-MU 0404b PCI [MAEM8852]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0108_chip = 1,
- .spk71 = 1,
+ .spk20 = 1,
+ .no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */
+ /* This is MAEM8850 "HanaLite" */
+ /* Supports sync daughter card. */
/* Tested by James@superbug.co.uk 20-3-2007. */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]",
+ .driver = "Audigy2", .name = "E-MU 0404 [MAEM8850]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0102_chip = 1,
- .spk71 = 1,
+ .spk20 = 1,
+ .no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
/* EMU0404 PCIe */
+ /* Does NOT support sync daughter card. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102,
- .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]",
+ .driver = "Audigy2", .name = "E-MU 0404 PCIe [MAEM8984]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0108_chip = 1,
- .spk71 = 1,
+ .spk20 = 1,
+ .no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */
- /* Note that all E-mu cards require kernel 2.6 or newer. */
{.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
.id = "Audigy2",
@@ -1532,6 +1220,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.adc_1361t = 1, /* 24 bit capture instead of 16bit */
.ac97_chip = 1} ,
+ /* Audigy 2 Platinum EX */
+ /* Win driver sets A_IOCFG output to 0x1c00 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
.driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]",
.id = "Audigy2",
@@ -1552,6 +1242,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
+ /* Audigy 2 Platinum */
+ /* Win driver sets A_IOCFG output to 0xa00 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
.driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]",
.id = "Audigy2",
@@ -1657,6 +1349,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
+ /* SB Live! Platinum */
+ /* Win driver sets A_IOCFG output to 0 */
+ /* Tested by Jonathan Dowland <jon@dow.land> Apr 2023. */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
.driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]",
.id = "Live",
@@ -1706,7 +1401,7 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
- .driver = "EMU10K1", .name = "E-mu APS [PC545]",
+ .driver = "EMU10K1", .name = "E-MU APS [PC545]",
.id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
@@ -1797,7 +1492,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->irq = -1;
emu->synth = NULL;
emu->get_synth_voice = NULL;
- INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
+ INIT_WORK(&emu->emu1010.work, emu1010_work);
+ mutex_init(&emu->emu1010.lock);
/* read revision & serial */
emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
@@ -1862,7 +1558,7 @@ int snd_emu10k1_create(struct snd_card *card,
else
emu->gpr_base = FXGPREGBASE;
- err = pci_request_regions(pci, "EMU10K1");
+ err = pcim_request_all_regions(pci, "EMU10K1");
if (err < 0)
return err;
emu->port = pci_resource_start(pci, 0);
@@ -1901,11 +1597,12 @@ int snd_emu10k1_create(struct snd_card *card,
pci_set_master(pci);
- emu->fx8010.fxbus_mask = 0x303f;
+ // The masks are not used for Audigy.
+ // FIXME: these should come from the card_capabilites table.
if (extin_mask == 0)
- extin_mask = 0x3fcf;
+ extin_mask = 0x3fcf; // EXTIN_*
if (extout_mask == 0)
- extout_mask = 0x7fff;
+ extout_mask = 0x7fff; // EXTOUT_*
emu->fx8010.extin_mask = extin_mask;
emu->fx8010.extout_mask = extout_mask;
emu->enable_ir = enable_ir;
@@ -1970,12 +1667,10 @@ int snd_emu10k1_create(struct snd_card *card,
pgtbl[idx] = cpu_to_le32(silent_page | idx);
/* set up voice indices */
- for (idx = 0; idx < NUM_G; idx++) {
- emu->voices[idx].emu = emu;
+ for (idx = 0; idx < NUM_G; idx++)
emu->voices[idx].number = idx;
- }
- err = snd_emu10k1_init(emu, enable_ir, 0);
+ err = snd_emu10k1_init(emu, enable_ir);
if (err < 0)
return err;
#ifdef CONFIG_PM_SLEEP
@@ -2007,7 +1702,7 @@ static const unsigned char saved_regs[] = {
0xff /* end */
};
static const unsigned char saved_regs_audigy[] = {
- A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE,
+ A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_EHC,
A_FXRT2, A_SENDAMOUNTS, A_FXRT1,
0xff /* end */
};
@@ -2054,7 +1749,7 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu)
*val = snd_emu10k1_ptr_read(emu, *reg, i);
}
if (emu->audigy)
- emu->saved_a_iocfg = inl(emu->port + A_IOCFG);
+ emu->saved_a_iocfg = inw(emu->port + A_IOCFG);
emu->saved_hcfg = inl(emu->port + HCFG);
}
@@ -2068,7 +1763,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
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);
+ snd_emu10k1_init(emu, emu->enable_ir);
}
void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
@@ -2081,7 +1776,7 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
/* resore for spdif */
if (emu->audigy)
- outl(emu->saved_a_iocfg, emu->port + A_IOCFG);
+ outw(emu->saved_a_iocfg, emu->port + A_IOCFG);
outl(emu->saved_hcfg, emu->port + HCFG);
val = emu->saved_ptr;