summaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_intel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r--sound/pci/hda/hda_intel.c87
1 files changed, 79 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c38c68f57..3b3658297 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -312,6 +312,10 @@ enum {
(AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\
AZX_DCAPS_I915_POWERWELL)
+#define AZX_DCAPS_INTEL_BROXTON \
+ (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\
+ AZX_DCAPS_I915_POWERWELL)
+
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
(AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB |\
@@ -334,10 +338,11 @@ enum {
#define AZX_DCAPS_PRESET_CTHDA \
(AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB |\
+ AZX_DCAPS_NO_64BIT |\
AZX_DCAPS_4K_BDLE_BOUNDARY | AZX_DCAPS_SNOOP_OFF)
/*
- * VGA-switcher support
+ * vga_switcheroo support
*/
#ifdef SUPPORT_VGA_SWITCHEROO
#define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo)
@@ -350,6 +355,8 @@ enum {
((pci)->device == 0x0d0c) || \
((pci)->device == 0x160c))
+#define IS_BROXTON(pci) ((pci)->device == 0x5a98)
+
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -501,15 +508,36 @@ static void azx_init_pci(struct azx *chip)
}
}
+/*
+ * In BXT-P A0, HD-Audio DMA requests is later than expected,
+ * and makes an audio stream sensitive to system latencies when
+ * 24/32 bits are playing.
+ * Adjusting threshold of DMA fifo to force the DMA request
+ * sooner to improve latency tolerance at the expense of power.
+ */
+static void bxt_reduce_dma_latency(struct azx *chip)
+{
+ u32 val;
+
+ val = azx_readl(chip, SKL_EM4L);
+ val &= (0x3 << 20);
+ azx_writel(chip, SKL_EM4L, val);
+}
+
static void hda_intel_init_chip(struct azx *chip, bool full_reset)
{
struct hdac_bus *bus = azx_bus(chip);
+ struct pci_dev *pci = chip->pci;
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_hdac_set_codec_wakeup(bus, true);
azx_init_chip(chip, full_reset);
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_hdac_set_codec_wakeup(bus, false);
+
+ /* reduce dma latency to avoid noise */
+ if (IS_BROXTON(pci))
+ bxt_reduce_dma_latency(chip);
}
/* calculate runtime delay from LPIB */
@@ -926,6 +954,36 @@ static int azx_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP || SUPPORT_VGA_SWITCHEROO */
+#ifdef CONFIG_PM_SLEEP
+/* put codec down to D3 at hibernation for Intel SKL+;
+ * 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)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+
+ if (IS_SKL_PLUS(pci))
+ pci_set_power_state(pci, PCI_D3hot);
+
+ return 0;
+}
+
+static int azx_thaw_noirq(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+
+ if (IS_SKL_PLUS(pci))
+ pci_set_power_state(pci, PCI_D0);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
#ifdef CONFIG_PM
static int azx_runtime_suspend(struct device *dev)
{
@@ -1035,6 +1093,10 @@ static int azx_runtime_idle(struct device *dev)
static const struct dev_pm_ops azx_pm = {
SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
+#ifdef CONFIG_PM_SLEEP
+ .freeze_noirq = azx_freeze_noirq,
+ .thaw_noirq = azx_thaw_noirq,
+#endif
SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
};
@@ -1076,12 +1138,12 @@ static void azx_vs_set_state(struct pci_dev *pci,
}
}
} else {
- dev_info(chip->card->dev, "%s via VGA-switcheroo\n",
+ dev_info(chip->card->dev, "%s via vga_switcheroo\n",
disabled ? "Disabling" : "Enabling");
if (disabled) {
pm_runtime_put_sync_suspend(card->dev);
azx_suspend(card->dev);
- /* when we get suspended by vga switcheroo we end up in D3cold,
+ /* when we get suspended by vga_switcheroo we end up in D3cold,
* however we have no ACPI handle, so pci/acpi can't put us there,
* put ourselves there */
pci->current_state = PCI_D3cold;
@@ -1121,7 +1183,7 @@ static void init_vga_switcheroo(struct azx *chip)
struct pci_dev *p = get_bound_vga(chip->pci);
if (p) {
dev_info(chip->card->dev,
- "Handle VGA-switcheroo audio client\n");
+ "Handle vga_switcheroo audio client\n");
hda->use_vga_switcheroo = 1;
pci_dev_put(p);
}
@@ -1143,8 +1205,7 @@ static int register_vga_switcheroo(struct azx *chip)
* is there any machine with two switchable HDMI audio controllers?
*/
err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
- VGA_SWITCHEROO_DIS,
- hda->probe_continued);
+ VGA_SWITCHEROO_DIS);
if (err < 0)
return err;
hda->vga_switcheroo_registered = 1;
@@ -1233,7 +1294,7 @@ static int azx_dev_free(struct snd_device *device)
#ifdef SUPPORT_VGA_SWITCHEROO
/*
- * Check of disabled HDMI controller by vga-switcheroo
+ * Check of disabled HDMI controller by vga_switcheroo
*/
static struct pci_dev *get_bound_vga(struct pci_dev *pci)
{
@@ -1918,7 +1979,7 @@ static int azx_probe(struct pci_dev *pci,
err = register_vga_switcheroo(chip);
if (err < 0) {
- dev_err(card->dev, "Error registering VGA-switcheroo client\n");
+ dev_err(card->dev, "Error registering vga_switcheroo client\n");
goto out_free;
}
@@ -2104,6 +2165,11 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
{ PCI_DEVICE(0x8086, 0x8d21),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+ /* Lewisburg */
+ { PCI_DEVICE(0x8086, 0xa1f0),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+ { PCI_DEVICE(0x8086, 0xa270),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@@ -2119,6 +2185,9 @@ static const struct pci_device_id azx_ids[] = {
/* Sunrise Point-LP */
{ PCI_DEVICE(0x8086, 0x9d70),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+ /* Broxton-P(Apollolake) */
+ { PCI_DEVICE(0x8086, 0x5a98),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
/* Haswell */
{ PCI_DEVICE(0x8086, 0x0a0c),
.driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
@@ -2284,11 +2353,13 @@ static const struct pci_device_id azx_ids[] = {
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_NO_64BIT |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#else
/* this entry seems still valid -- i.e. without emu20kx chip */
{ PCI_DEVICE(0x1102, 0x0009),
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_NO_64BIT |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#endif
/* CM8888 */