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);
......
This diff is collapsed.
...@@ -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