Commit 6b844f06 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/emu10k1-fix' into for-next

Pull emu10k1 fixes from Oswald Buddenhagen
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parents 078c95fe 1aa41272
...@@ -1692,8 +1692,8 @@ struct snd_emu1010 { ...@@ -1692,8 +1692,8 @@ struct snd_emu1010 {
unsigned int clock_fallback; unsigned int clock_fallback;
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
struct work_struct firmware_work; struct work_struct work;
struct work_struct clock_work; struct mutex lock;
}; };
struct snd_emu10k1 { struct snd_emu10k1 {
...@@ -1842,12 +1842,16 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, ...@@ -1842,12 +1842,16 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); 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_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); };
static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); };
void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src); void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src);
u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst); u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst);
int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src); int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src);
void snd_emu1010_update_clock(struct snd_emu10k1 *emu); void snd_emu1010_update_clock(struct snd_emu10k1 *emu);
void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock, const struct firmware *fw_entry);
unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); 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_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
......
...@@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, ...@@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest,
midi1->note.group = midi2->note.group; midi1->note.group = midi2->note.group;
midi1->note.status = midi2->note.status; midi1->note.status = midi2->note.status;
midi1->note.channel = midi2->note.channel; midi1->note.channel = midi2->note.channel;
switch (midi2->note.status << 4) { switch (midi2->note.status) {
case UMP_MSG_STATUS_NOTE_ON: case UMP_MSG_STATUS_NOTE_ON:
case UMP_MSG_STATUS_NOTE_OFF: case UMP_MSG_STATUS_NOTE_OFF:
midi1->note.note = midi2->note.note; midi1->note.note = midi2->note.note;
......
...@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev) ...@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev)
emu->suspend = 1; emu->suspend = 1;
cancel_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.work);
cancel_work_sync(&emu->emu1010.clock_work);
snd_ac97_suspend(emu->ac97); snd_ac97_suspend(emu->ac97);
......
...@@ -652,52 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) ...@@ -652,52 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
return 0; return 0;
} }
static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu,
const struct firmware *fw_entry)
{
int n, i;
u16 reg;
u8 value;
__always_unused u16 write_post;
if (!fw_entry)
return -EIO;
/* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */
/* GPIO7 -> FPGA PGMN
* GPIO6 -> FPGA CCLK
* GPIO5 -> FPGA DIN
* FPGA CONFIG OFF -> FPGA PGMN
*/
spin_lock_irq(&emu->emu_lock);
outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */
write_post = inw(emu->port + A_GPIO);
udelay(100);
outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */
write_post = inw(emu->port + A_GPIO);
udelay(100); /* Allow FPGA memory to clean */
for (n = 0; n < fw_entry->size; n++) {
value = fw_entry->data[n];
for (i = 0; i < 8; i++) {
reg = 0x80;
if (value & 0x1)
reg = reg | 0x20;
value = value >> 1;
outw(reg, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
outw(reg | 0x40, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
}
}
/* After programming, set GPIO bit 4 high again. */
outw(0x10, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
spin_unlock_irq(&emu->emu_lock);
return 0;
}
/* firmware file names, per model, init-fw and dock-fw (optional) */ /* firmware file names, per model, init-fw and dock-fw (optional) */
static const char * const firmware_names[5][2] = { static const char * const firmware_names[5][2] = {
[EMU_MODEL_EMU1010] = { [EMU_MODEL_EMU1010] = {
...@@ -729,72 +683,68 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, ...@@ -729,72 +683,68 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
return err; 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;
u32 tmp, tmp2, reg;
int err; int err;
emu = container_of(work, struct snd_emu10k1, // The docking events clearly arrive prematurely - while the
emu1010.firmware_work); // Dock's FPGA seems to be successfully programmed, the Dock
if (emu->card->shutdown) // fails to initialize subsequently if we don't give it some
return; // time to "warm up" here.
#ifdef CONFIG_PM_SLEEP msleep(200);
if (emu->suspend)
return; dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
#endif
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); err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
if (err < 0) if (err < 0)
return; return;
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
dev_info(emu->card->dev, dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
"emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
if ((tmp & 0x1f) != 0x15) { if ((tmp & 0x1f) != 0x15) {
/* FPGA failed to be programmed */ /* FPGA failed to be programmed */
dev_info(emu->card->dev, dev_err(emu->card->dev,
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
tmp); tmp);
return; return;
} }
dev_info(emu->card->dev, dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
"emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */ /* Allow DLL to settle, to sync clocking between 1010 and Dock */
msleep(10); 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 */
snd_emu1010_load_dock_firmware(emu);
/* Unmute all. Default is muted after a firmware load */ /* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
/* Audio Dock removed */
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
/* The hardware auto-mutes all, so we unmute again */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} }
} }
static void emu1010_clock_work(struct work_struct *work) static void emu1010_clock_event(struct snd_emu10k1 *emu)
{ {
struct snd_emu10k1 *emu;
struct snd_ctl_elem_id id; struct snd_ctl_elem_id id;
emu = container_of(work, struct snd_emu10k1,
emu1010.clock_work);
if (emu->card->shutdown)
return;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
return;
#endif
spin_lock_irq(&emu->reg_lock); spin_lock_irq(&emu->reg_lock);
// This is the only thing that can actually happen. // This is the only thing that can actually happen.
emu->emu1010.clock_source = emu->emu1010.clock_fallback; emu->emu1010.clock_source = emu->emu1010.clock_fallback;
...@@ -805,21 +755,44 @@ static void emu1010_clock_work(struct work_struct *work) ...@@ -805,21 +755,44 @@ static void emu1010_clock_work(struct work_struct *work)
snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
} }
static void emu1010_interrupt(struct snd_emu10k1 *emu) static void emu1010_work(struct work_struct *work)
{ {
struct snd_emu10k1 *emu;
u32 sts; 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
snd_emu1010_fpga_lock(emu);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
if (sts & EMU_HANA_IRQ_DOCK_LOST) {
/* Audio Dock removed */ // The distinction of the IRQ status bits is unreliable,
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); // so we dispatch later based on option card status.
/* The hardware auto-mutes all, so we unmute again */ if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); emu1010_dock_event(emu);
} else if (sts & EMU_HANA_IRQ_DOCK) {
schedule_work(&emu->emu1010.firmware_work);
}
if (sts & EMU_HANA_IRQ_WCLK_CHANGED) if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
schedule_work(&emu->emu1010.clock_work); emu1010_clock_event(emu);
snd_emu1010_fpga_unlock(emu);
}
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);
} }
/* /*
...@@ -841,32 +814,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -841,32 +814,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
* Proper init follows in snd_emu10k1_init(). */ * Proper init follows in snd_emu10k1_init(). */
outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
/* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_lock(emu);
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 */
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_HANA);
}
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);
dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n");
err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
if (err < 0) { if (err < 0) {
dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
return err; goto fail;
} }
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
...@@ -876,7 +830,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -876,7 +830,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
dev_info(emu->card->dev, dev_info(emu->card->dev,
"emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n",
reg); reg);
return -ENODEV; err = -ENODEV;
goto fail;
} }
dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n");
...@@ -889,7 +844,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -889,7 +844,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
schedule_work(&emu->emu1010.firmware_work); snd_emu1010_load_dock_firmware(emu);
if (emu->card_capabilities->no_adat) { if (emu->card_capabilities->no_adat) {
emu->emu1010.optical_in = 0; /* IN_SPDIF */ emu->emu1010.optical_in = 0; /* IN_SPDIF */
emu->emu1010.optical_out = 0; /* OUT_SPDIF */ emu->emu1010.optical_out = 0; /* OUT_SPDIF */
...@@ -936,7 +891,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -936,7 +891,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
// so it is safe to simply enable the outputs. // so it is safe to simply enable the outputs.
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
return 0; fail:
snd_emu1010_fpga_unlock(emu);
return err;
} }
/* /*
* Create the EMU10K1 instance * Create the EMU10K1 instance
...@@ -958,10 +915,10 @@ static void snd_emu10k1_free(struct snd_card *card) ...@@ -958,10 +915,10 @@ static void snd_emu10k1_free(struct snd_card *card)
} }
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
/* Disable 48Volt power to Audio Dock */ /* 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_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.work);
cancel_work_sync(&emu->emu1010.clock_work); mutex_destroy(&emu->emu1010.lock);
release_firmware(emu->firmware); release_firmware(emu->firmware);
release_firmware(emu->dock_fw); release_firmware(emu->dock_fw);
snd_util_memhdr_free(emu->memhdr); snd_util_memhdr_free(emu->memhdr);
...@@ -1540,8 +1497,8 @@ int snd_emu10k1_create(struct snd_card *card, ...@@ -1540,8 +1497,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->irq = -1; emu->irq = -1;
emu->synth = NULL; emu->synth = NULL;
emu->get_synth_voice = NULL; emu->get_synth_voice = NULL;
INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); INIT_WORK(&emu->emu1010.work, emu1010_work);
INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work); mutex_init(&emu->emu1010.lock);
/* read revision & serial */ /* read revision & serial */
emu->revision = pci->revision; emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
......
...@@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, ...@@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.output_source[channel] != val); change = (emu->emu1010.output_source[channel] != val);
if (change) { if (change) {
emu->emu1010.output_source[channel] = val; emu->emu1010.output_source[channel] = val;
snd_emu1010_fpga_lock(emu);
snd_emu1010_output_source_apply(emu, channel, val); snd_emu1010_output_source_apply(emu, channel, val);
snd_emu1010_fpga_unlock(emu);
} }
return change; return change;
} }
...@@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, ...@@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.input_source[channel] != val); change = (emu->emu1010.input_source[channel] != val);
if (change) { if (change) {
emu->emu1010.input_source[channel] = val; emu->emu1010.input_source[channel] = val;
snd_emu1010_fpga_lock(emu);
snd_emu1010_input_source_apply(emu, channel, val); snd_emu1010_input_source_apply(emu, channel, val);
snd_emu1010_fpga_unlock(emu);
} }
return change; return change;
} }
...@@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct ...@@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
cache = cache & ~mask; cache = cache & ~mask;
change = (cache != emu->emu1010.adc_pads); change = (cache != emu->emu1010.adc_pads);
if (change) { if (change) {
snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache );
emu->emu1010.adc_pads = cache; emu->emu1010.adc_pads = cache;
} }
...@@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct ...@@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
cache = cache & ~mask; cache = cache & ~mask;
change = (cache != emu->emu1010.dac_pads); change = (cache != emu->emu1010.dac_pads);
if (change) { if (change) {
snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache );
emu->emu1010.dac_pads = cache; emu->emu1010.dac_pads = cache;
} }
...@@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, ...@@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
if (val >= emu_ci->num) if (val >= emu_ci->num)
return -EINVAL; return -EINVAL;
snd_emu1010_fpga_lock(emu);
spin_lock_irq(&emu->reg_lock); spin_lock_irq(&emu->reg_lock);
change = (emu->emu1010.clock_source != val); change = (emu->emu1010.clock_source != val);
if (change) { if (change) {
...@@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, ...@@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
} else { } else {
spin_unlock_irq(&emu->reg_lock); spin_unlock_irq(&emu->reg_lock);
} }
snd_emu1010_fpga_unlock(emu);
return change; return change;
} }
...@@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol, ...@@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.clock_fallback != val); change = (emu->emu1010.clock_fallback != val);
if (change) { if (change) {
emu->emu1010.clock_fallback = val; emu->emu1010.clock_fallback = val;
snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val);
} }
return change; return change;
} }
...@@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol, ...@@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
emu->emu1010.optical_out = val; emu->emu1010.optical_out = val;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | 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); (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_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
} }
return change; return change;
} }
...@@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol, ...@@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
emu->emu1010.optical_in = val; emu->emu1010.optical_in = val;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | 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); (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_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
} }
return change; return change;
} }
...@@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, ...@@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
for (i = 0; i < emu_ri->n_outs; i++) for (i = 0; i < emu_ri->n_outs; i++)
emu->emu1010.output_source[i] = emu->emu1010.output_source[i] =
emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
snd_emu1010_fpga_lock(emu);
snd_emu1010_apply_sources(emu); snd_emu1010_apply_sources(emu);
snd_emu1010_fpga_unlock(emu);
kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu);
err = snd_ctl_add(card, kctl); err = snd_ctl_add(card, kctl);
......
...@@ -165,6 +165,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, ...@@ -165,6 +165,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
u32 value2; u32 value2;
if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->emu_model) {
snd_emu1010_fpga_lock(emu);
// This represents the S/PDIF lock status on 0404b, which is // This represents the S/PDIF lock status on 0404b, which is
// kinda weird and unhelpful, because monitoring it via IRQ is // kinda weird and unhelpful, because monitoring it via IRQ is
// impractical (one gets an IRQ flood as long as it is desynced). // impractical (one gets an IRQ flood as long as it is desynced).
...@@ -197,6 +199,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, ...@@ -197,6 +199,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n", snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n",
value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer", value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer",
value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : ""); value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : "");
snd_emu1010_fpga_unlock(emu);
} else { } else {
snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
...@@ -458,6 +462,9 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, ...@@ -458,6 +462,9 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
struct snd_emu10k1 *emu = entry->private_data; struct snd_emu10k1 *emu = entry->private_data;
u32 value; u32 value;
int i; int i;
snd_emu1010_fpga_lock(emu);
snd_iprintf(buffer, "EMU1010 Registers:\n\n"); snd_iprintf(buffer, "EMU1010 Registers:\n\n");
for(i = 0; i < 0x40; i+=1) { for(i = 0; i < 0x40; i+=1) {
...@@ -496,6 +503,8 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, ...@@ -496,6 +503,8 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
snd_emu_proc_emu1010_link_read(emu, buffer, 0x701); snd_emu_proc_emu1010_link_read(emu, buffer, 0x701);
} }
} }
snd_emu1010_fpga_unlock(emu);
} }
static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
......
...@@ -285,24 +285,33 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 ...@@ -285,24 +285,33 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32
outw(value, emu->port + A_GPIO); outw(value, emu->port + A_GPIO);
udelay(10); udelay(10);
outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
udelay(10);
} }
void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
{ {
unsigned long flags; if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
return;
snd_emu1010_fpga_write_locked(emu, reg, value);
}
spin_lock_irqsave(&emu->emu_lock, flags); void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value)
{
snd_emu1010_fpga_lock(emu);
snd_emu1010_fpga_write_locked(emu, reg, value); snd_emu1010_fpga_write_locked(emu, reg, value);
spin_unlock_irqrestore(&emu->emu_lock, flags); snd_emu1010_fpga_unlock(emu);
} }
static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *value) void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
{ {
// The higest input pin is used as the designated interrupt trigger, // The higest input pin is used as the designated interrupt trigger,
// so it needs to be masked out. // so it needs to be masked out.
// But note that any other input pin change will also cause an IRQ, // But note that any other input pin change will also cause an IRQ,
// so using this function often causes an IRQ as a side effect. // so using this function often causes an IRQ as a side effect.
u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f; u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
return;
if (snd_BUG_ON(reg > 0x3f)) if (snd_BUG_ON(reg > 0x3f))
return; return;
reg += 0x40; /* 0x40 upwards are registers. */ reg += 0x40; /* 0x40 upwards are registers. */
...@@ -313,47 +322,31 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 * ...@@ -313,47 +322,31 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *
*value = ((inw(emu->port + A_GPIO) >> 8) & mask); *value = ((inw(emu->port + A_GPIO) >> 8) & mask);
} }
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
{
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read_locked(emu, reg, value);
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
/* Each Destination has one and only one Source, /* Each Destination has one and only one Source,
* but one Source can feed any number of Destinations simultaneously. * but one Source can feed any number of Destinations simultaneously.
*/ */
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src) void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
{ {
unsigned long flags;
if (snd_BUG_ON(dst & ~0x71f)) if (snd_BUG_ON(dst & ~0x71f))
return; return;
if (snd_BUG_ON(src & ~0x71f)) if (snd_BUG_ON(src & ~0x71f))
return; return;
spin_lock_irqsave(&emu->emu_lock, flags); snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8); snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f); snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8); snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f);
spin_unlock_irqrestore(&emu->emu_lock, flags);
} }
u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst) u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
{ {
unsigned long flags;
u32 hi, lo; u32 hi, lo;
if (snd_BUG_ON(dst & ~0x71f)) if (snd_BUG_ON(dst & ~0x71f))
return 0; return 0;
spin_lock_irqsave(&emu->emu_lock, flags); snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8); snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f); snd_emu1010_fpga_read(emu, EMU_HANA_SRCHI, &hi);
snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCHI, &hi); snd_emu1010_fpga_read(emu, EMU_HANA_SRCLO, &lo);
snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCLO, &lo);
spin_unlock_irqrestore(&emu->emu_lock, flags);
return (hi << 8) | lo; return (hi << 8) | lo;
} }
...@@ -429,6 +422,59 @@ void snd_emu1010_update_clock(struct snd_emu10k1 *emu) ...@@ -429,6 +422,59 @@ void snd_emu1010_update_clock(struct snd_emu10k1 *emu)
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, leds); snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, leds);
} }
void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock,
const struct firmware *fw_entry)
{
__always_unused u16 write_post;
// On E-MU 1010 rev1 the FPGA is a Xilinx Spartan IIE XC2S50E.
// On E-MU 0404b it is a Xilinx Spartan III XC3S50.
// The wiring is as follows:
// GPO7 -> FPGA input & 1K resistor -> FPGA /PGMN <- FPGA output
// In normal operation, the active low reset line is held up by
// an FPGA output, while the GPO pin performs its duty as control
// register access strobe signal. Writing the respective bit to
// EMU_HANA_FPGA_CONFIG puts the FPGA output into high-Z mode, at
// which point the GPO pin can control the reset line through the
// resistor.
// GPO6 -> FPGA CCLK & FPGA input
// GPO5 -> FPGA DIN (dual function)
// If the FPGA is already programmed, return it to programming mode
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
dock ? EMU_HANA_FPGA_CONFIG_AUDIODOCK :
EMU_HANA_FPGA_CONFIG_HANA);
// Assert reset line for 100uS
outw(0x00, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
udelay(100);
outw(0x80, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
udelay(100); // Allow FPGA memory to clean
// Upload the netlist. Keep reset line high!
for (int n = 0; n < fw_entry->size; n++) {
u8 value = fw_entry->data[n];
for (int i = 0; i < 8; i++) {
u16 reg = 0x80;
if (value & 1)
reg |= 0x20;
value >>= 1;
outw(reg, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
outw(reg | 0x40, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
}
}
// After programming, set GPIO bit 4 high again.
// This appears to be a config word that the rev1 Hana
// firmware reads; weird things happen without this.
outw(0x10, emu->port + A_GPIO);
write_post = inw(emu->port + A_GPIO);
}
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
{ {
unsigned long flags; unsigned long flags;
......
...@@ -7467,6 +7467,10 @@ enum { ...@@ -7467,6 +7467,10 @@ enum {
ALC285_FIXUP_CS35L56_I2C_2, ALC285_FIXUP_CS35L56_I2C_2,
ALC285_FIXUP_CS35L56_I2C_4, ALC285_FIXUP_CS35L56_I2C_4,
ALC285_FIXUP_ASUS_GA403U, ALC285_FIXUP_ASUS_GA403U,
ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1
}; };
/* A special fixup for Lenovo C940 and Yoga Duet 7; /* A special fixup for Lenovo C940 and Yoga Duet 7;
...@@ -9690,6 +9694,38 @@ static const struct hda_fixup alc269_fixups[] = { ...@@ -9690,6 +9694,38 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_asus_ga403u, .v.func = alc285_fixup_asus_ga403u,
}, },
[ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, 0x03a11050 },
{ 0x1b, 0x03a11c30 },
{ }
},
.chained = true,
.chain_id = ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1
},
[ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_speaker2_to_dac1,
.chained = true,
.chain_id = ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
},
[ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, 0x03a11050 },
{ 0x1b, 0x03a11c30 },
{ }
},
.chained = true,
.chain_id = ALC285_FIXUP_CS35L56_SPI_2
},
[ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_speaker2_to_dac1,
.chained = true,
.chain_id = ALC285_FIXUP_ASUS_GA403U,
},
}; };
static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct snd_pci_quirk alc269_fixup_tbl[] = {
...@@ -10149,7 +10185,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10149,7 +10185,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B), SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U), SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2),
...@@ -10157,7 +10193,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10157,7 +10193,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_CS35L56_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
...@@ -10234,6 +10270,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10234,6 +10270,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x152d, 0x1262, "Huawei NBLB-WAX9N", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
...@@ -10339,6 +10376,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10339,6 +10376,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460), SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460), SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
SND_PCI_QUIRK(0x17aa, 0x2234, "Thinkpad ICE-1", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
...@@ -10402,8 +10440,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10402,8 +10440,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
...@@ -10465,6 +10503,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -10465,6 +10503,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment