Commit c213341e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "Things got calmed down for rc6, as it seems, and we have only a few
  HD-audio fixes at this time: a fix for Skylake codec probe errors, a
  fix for missing interrupt handling, and a few Dell and HP quirks"

* tag 'sound-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Loop interrupt handling until really cleared
  ALSA: hda - Fix headset support and noise on HP EliteBook 755 G2
  ALSA: hda - Fixup speaker pass-through control for nid 0x14 on ALC225
  ALSA: hda - Fixing background noise on Dell Inspiron 3162
  ALSA: hda - Apply clock gate workaround to Skylake, too
parents bb134ff5 473f4145
...@@ -343,7 +343,7 @@ void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); ...@@ -343,7 +343,7 @@ void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
void snd_hdac_bus_update_rirb(struct hdac_bus *bus); void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
void (*ack)(struct hdac_bus *, void (*ack)(struct hdac_bus *,
struct hdac_stream *)); struct hdac_stream *));
......
...@@ -426,18 +426,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip); ...@@ -426,18 +426,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
* @bus: HD-audio core bus * @bus: HD-audio core bus
* @status: INTSTS register value * @status: INTSTS register value
* @ask: callback to be called for woken streams * @ask: callback to be called for woken streams
*
* Returns the bits of handled streams, or zero if no stream is handled.
*/ */
void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
void (*ack)(struct hdac_bus *, void (*ack)(struct hdac_bus *,
struct hdac_stream *)) struct hdac_stream *))
{ {
struct hdac_stream *azx_dev; struct hdac_stream *azx_dev;
u8 sd_status; u8 sd_status;
int handled = 0;
list_for_each_entry(azx_dev, &bus->stream_list, list) { list_for_each_entry(azx_dev, &bus->stream_list, list) {
if (status & azx_dev->sd_int_sta_mask) { if (status & azx_dev->sd_int_sta_mask) {
sd_status = snd_hdac_stream_readb(azx_dev, SD_STS); sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
handled |= 1 << azx_dev->index;
if (!azx_dev->substream || !azx_dev->running || if (!azx_dev->substream || !azx_dev->running ||
!(sd_status & SD_INT_COMPLETE)) !(sd_status & SD_INT_COMPLETE))
continue; continue;
...@@ -445,6 +449,7 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, ...@@ -445,6 +449,7 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
ack(bus, azx_dev); ack(bus, azx_dev);
} }
} }
return handled;
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq); EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
......
...@@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) ...@@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
struct azx *chip = dev_id; struct azx *chip = dev_id;
struct hdac_bus *bus = azx_bus(chip); struct hdac_bus *bus = azx_bus(chip);
u32 status; u32 status;
bool active, handled = false;
int repeat = 0; /* count for avoiding endless loop */
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (azx_has_pm_runtime(chip)) if (azx_has_pm_runtime(chip))
...@@ -939,22 +941,23 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) ...@@ -939,22 +941,23 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
spin_lock(&bus->reg_lock); spin_lock(&bus->reg_lock);
if (chip->disabled) { if (chip->disabled)
spin_unlock(&bus->reg_lock); goto unlock;
return IRQ_NONE;
}
do {
status = azx_readl(chip, INTSTS); status = azx_readl(chip, INTSTS);
if (status == 0 || status == 0xffffffff) { if (status == 0 || status == 0xffffffff)
spin_unlock(&bus->reg_lock); break;
return IRQ_NONE;
}
snd_hdac_bus_handle_stream_irq(bus, status, stream_update); handled = true;
active = false;
if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
active = true;
/* clear rirb int */ /* clear rirb int */
status = azx_readb(chip, RIRBSTS); status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) { if (status & RIRB_INT_MASK) {
active = true;
if (status & RIRB_INT_RESPONSE) { if (status & RIRB_INT_RESPONSE) {
if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
udelay(80); udelay(80);
...@@ -962,10 +965,12 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) ...@@ -962,10 +965,12 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
} }
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
} }
} while (active && ++repeat < 10);
unlock:
spin_unlock(&bus->reg_lock); spin_unlock(&bus->reg_lock);
return IRQ_HANDLED; return IRQ_RETVAL(handled);
} }
EXPORT_SYMBOL_GPL(azx_interrupt); EXPORT_SYMBOL_GPL(azx_interrupt);
......
...@@ -363,7 +363,10 @@ enum { ...@@ -363,7 +363,10 @@ enum {
((pci)->device == 0x0d0c) || \ ((pci)->device == 0x0d0c) || \
((pci)->device == 0x160c)) ((pci)->device == 0x160c))
#define IS_BROXTON(pci) ((pci)->device == 0x5a98) #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
static char *driver_short_names[] = { static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_ICH] = "HDA Intel",
...@@ -540,13 +543,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) ...@@ -540,13 +543,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_hdac_set_codec_wakeup(bus, true); snd_hdac_set_codec_wakeup(bus, true);
if (IS_BROXTON(pci)) { if (IS_SKL_PLUS(pci)) {
pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
} }
azx_init_chip(chip, full_reset); azx_init_chip(chip, full_reset);
if (IS_BROXTON(pci)) { if (IS_SKL_PLUS(pci)) {
pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
val = val | INTEL_HDA_CGCTL_MISCBDCGE; val = val | INTEL_HDA_CGCTL_MISCBDCGE;
pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
...@@ -555,7 +558,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) ...@@ -555,7 +558,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
snd_hdac_set_codec_wakeup(bus, false); snd_hdac_set_codec_wakeup(bus, false);
/* reduce dma latency to avoid noise */ /* reduce dma latency to avoid noise */
if (IS_BROXTON(pci)) if (IS_BXT(pci))
bxt_reduce_dma_latency(chip); bxt_reduce_dma_latency(chip);
} }
...@@ -977,11 +980,6 @@ static int azx_resume(struct device *dev) ...@@ -977,11 +980,6 @@ static int azx_resume(struct device *dev)
/* put codec down to D3 at hibernation for Intel SKL+; /* put codec down to D3 at hibernation for Intel SKL+;
* otherwise BIOS may still access the codec and screw up the driver * otherwise BIOS may still access the codec and screw up the driver
*/ */
#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
static int azx_freeze_noirq(struct device *dev) static int azx_freeze_noirq(struct device *dev)
{ {
struct pci_dev *pci = to_pci_dev(dev); struct pci_dev *pci = to_pci_dev(dev);
......
...@@ -3801,6 +3801,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, ...@@ -3801,6 +3801,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
static void alc_headset_mode_default(struct hda_codec *codec) static void alc_headset_mode_default(struct hda_codec *codec)
{ {
static struct coef_fw coef0225[] = {
UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
{}
};
static struct coef_fw coef0255[] = { static struct coef_fw coef0255[] = {
WRITE_COEF(0x45, 0xc089), WRITE_COEF(0x45, 0xc089),
WRITE_COEF(0x45, 0xc489), WRITE_COEF(0x45, 0xc489),
...@@ -3842,6 +3846,9 @@ static void alc_headset_mode_default(struct hda_codec *codec) ...@@ -3842,6 +3846,9 @@ static void alc_headset_mode_default(struct hda_codec *codec)
}; };
switch (codec->core.vendor_id) { switch (codec->core.vendor_id) {
case 0x10ec0225:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0255: case 0x10ec0255:
case 0x10ec0256: case 0x10ec0256:
alc_process_coef_fw(codec, coef0255); alc_process_coef_fw(codec, coef0255);
...@@ -4749,6 +4756,9 @@ enum { ...@@ -4749,6 +4756,9 @@ enum {
ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
ALC293_FIXUP_LENOVO_SPK_NOISE, ALC293_FIXUP_LENOVO_SPK_NOISE,
ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
ALC255_FIXUP_DELL_SPK_NOISE,
ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC280_FIXUP_HP_HEADSET_MIC,
}; };
static const struct hda_fixup alc269_fixups[] = { static const struct hda_fixup alc269_fixups[] = {
...@@ -5368,6 +5378,29 @@ static const struct hda_fixup alc269_fixups[] = { ...@@ -5368,6 +5378,29 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = alc233_fixup_lenovo_line2_mic_hotkey, .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
}, },
[ALC255_FIXUP_DELL_SPK_NOISE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_disable_aamix,
.chained = true,
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
},
[ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* Disable pass-through path for FRONT 14h */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
{}
},
.chained = true,
.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
},
[ALC280_FIXUP_HP_HEADSET_MIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_disable_aamix,
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MIC,
},
}; };
static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct snd_pci_quirk alc269_fixup_tbl[] = {
...@@ -5410,6 +5443,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -5410,6 +5443,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
...@@ -5470,6 +5504,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -5470,6 +5504,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
...@@ -5638,10 +5673,10 @@ static const struct hda_model_fixup alc269_fixup_models[] = { ...@@ -5638,10 +5673,10 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{0x21, 0x03211020} {0x21, 0x03211020}
static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC225_STANDARD_PINS, ALC225_STANDARD_PINS,
{0x14, 0x901701a0}), {0x14, 0x901701a0}),
SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC225_STANDARD_PINS, ALC225_STANDARD_PINS,
{0x14, 0x901701b0}), {0x14, 0x901701b0}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
......
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