summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>2019-07-29 11:51:51 -0400
committerTakashi Iwai <tiwai@suse.de>2019-07-31 09:46:02 -0400
commit8c57588313805d4e12a3d470dee3405c2236655f (patch)
tree7430de901d9b194b18cd61fcb62801bf2fef7414
parent1169cbf6b98e11397715d457e42070e066325fc0 (diff)
ALSA: hda/intel: stop probe if DMICS are detected on Skylake+ platforms
The legacy HD-Audio driver cannot handle Skylake+ platforms with digital microphones. For those platforms, the SOF or SST drivers need to be used. This patch provides an automatic way of detecting the presence of DMICs using NHTL information reported by the BIOS. A kernel kconfig option or a kernel module parameter provide an opt-in means of stopping the probe. The kernel would then look for an alternate driver registered for the same PCI ID to probe. With this capability, distros no longer have to blacklist snd-hda-intel, but still need to make sure the SOF/SST drivers are functional by providing the relevant firmware and topology files in /lib/firmware/intel The coexistence between SOF and SST drivers and their dynamic detection is not addressed by this patch, different mechanisms need to be used, e.g. DMI-based quirks. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/Kconfig10
-rw-r--r--sound/pci/hda/hda_intel.c34
2 files changed, 44 insertions, 0 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 35d934309cb2..b5966014b5f7 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -12,6 +12,7 @@ config SND_HDA_INTEL
12 tristate "HD Audio PCI" 12 tristate "HD Audio PCI"
13 depends on SND_PCI 13 depends on SND_PCI
14 select SND_HDA 14 select SND_HDA
15 select SND_INTEL_NHLT if ACPI
15 help 16 help
16 Say Y here to include support for Intel "High Definition 17 Say Y here to include support for Intel "High Definition
17 Audio" (Azalia) and its compatible devices. 18 Audio" (Azalia) and its compatible devices.
@@ -22,6 +23,15 @@ config SND_HDA_INTEL
22 To compile this driver as a module, choose M here: the module 23 To compile this driver as a module, choose M here: the module
23 will be called snd-hda-intel. 24 will be called snd-hda-intel.
24 25
26config SND_HDA_INTEL_DETECT_DMIC
27 bool "DMIC detection and probe abort"
28 depends on SND_HDA_INTEL
29 help
30 Say Y to detect digital microphones on SKL+ devices. DMICs
31 cannot be handled by the HDaudio legacy driver and are
32 currently only supported by the SOF driver.
33 If unsure say N.
34
25config SND_HDA_TEGRA 35config SND_HDA_TEGRA
26 tristate "NVIDIA Tegra HD Audio" 36 tristate "NVIDIA Tegra HD Audio"
27 depends on ARCH_TEGRA 37 depends on ARCH_TEGRA
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cb8b0945547c..ae9c13248a1d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -46,6 +46,7 @@
46#include <sound/initval.h> 46#include <sound/initval.h>
47#include <sound/hdaudio.h> 47#include <sound/hdaudio.h>
48#include <sound/hda_i915.h> 48#include <sound/hda_i915.h>
49#include <sound/intel-nhlt.h>
49#include <linux/vgaarb.h> 50#include <linux/vgaarb.h>
50#include <linux/vga_switcheroo.h> 51#include <linux/vga_switcheroo.h>
51#include <linux/firmware.h> 52#include <linux/firmware.h>
@@ -124,6 +125,7 @@ static char *patch[SNDRV_CARDS];
124static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 125static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
125 CONFIG_SND_HDA_INPUT_BEEP_MODE}; 126 CONFIG_SND_HDA_INPUT_BEEP_MODE};
126#endif 127#endif
128static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC);
127 129
128module_param_array(index, int, NULL, 0444); 130module_param_array(index, int, NULL, 0444);
129MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); 131MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -158,6 +160,8 @@ module_param_array(beep_mode, bool, NULL, 0444);
158MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " 160MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
159 "(0=off, 1=on) (default=1)."); 161 "(0=off, 1=on) (default=1).");
160#endif 162#endif
163module_param(dmic_detect, bool, 0444);
164MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms");
161 165
162#ifdef CONFIG_PM 166#ifdef CONFIG_PM
163static int param_set_xint(const char *val, const struct kernel_param *kp); 167static int param_set_xint(const char *val, const struct kernel_param *kp);
@@ -2025,6 +2029,25 @@ static const struct hda_controller_ops pci_hda_ops = {
2025 .position_check = azx_position_check, 2029 .position_check = azx_position_check,
2026}; 2030};
2027 2031
2032static int azx_check_dmic(struct pci_dev *pci, struct azx *chip)
2033{
2034 struct nhlt_acpi_table *nhlt;
2035 int ret = 0;
2036
2037 if (chip->driver_type == AZX_DRIVER_SKL &&
2038 pci->class != 0x040300) {
2039 nhlt = intel_nhlt_init(&pci->dev);
2040 if (nhlt) {
2041 if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) {
2042 ret = -ENODEV;
2043 dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n");
2044 }
2045 intel_nhlt_free(nhlt);
2046 }
2047 }
2048 return ret;
2049}
2050
2028static int azx_probe(struct pci_dev *pci, 2051static int azx_probe(struct pci_dev *pci,
2029 const struct pci_device_id *pci_id) 2052 const struct pci_device_id *pci_id)
2030{ 2053{
@@ -2055,6 +2078,17 @@ static int azx_probe(struct pci_dev *pci,
2055 card->private_data = chip; 2078 card->private_data = chip;
2056 hda = container_of(chip, struct hda_intel, chip); 2079 hda = container_of(chip, struct hda_intel, chip);
2057 2080
2081 /*
2082 * stop probe if digital microphones detected on Skylake+ platform
2083 * with the DSP enabled. This is an opt-in behavior defined at build
2084 * time or at run-time with a module parameter
2085 */
2086 if (dmic_detect) {
2087 err = azx_check_dmic(pci, chip);
2088 if (err < 0)
2089 goto out_free;
2090 }
2091
2058 pci_set_drvdata(pci, card); 2092 pci_set_drvdata(pci, card);
2059 2093
2060 err = register_vga_switcheroo(chip); 2094 err = register_vga_switcheroo(chip);