Merge branch 'topic/hda-dmic' into for-next
[linux-2.6-block.git] / sound / pci / hda / hda_intel.c
index fdde80d959663ea34ff4e212b42eb764894dce39..635d971b003bfd3dca8428d2e780b7a537313344 100644 (file)
@@ -46,6 +46,7 @@
 #include <sound/initval.h>
 #include <sound/hdaudio.h>
 #include <sound/hda_i915.h>
+#include <sound/intel-nhlt.h>
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/firmware.h>
@@ -124,6 +125,7 @@ static char *patch[SNDRV_CARDS];
 static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
                                        CONFIG_SND_HDA_INPUT_BEEP_MODE};
 #endif
+static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC);
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -158,6 +160,8 @@ module_param_array(beep_mode, bool, NULL, 0444);
 MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
                            "(0=off, 1=on) (default=1).");
 #endif
+module_param(dmic_detect, bool, 0444);
+MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms");
 
 #ifdef CONFIG_PM
 static 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 = {
        .position_check = azx_position_check,
 };
 
+static int azx_check_dmic(struct pci_dev *pci, struct azx *chip)
+{
+       struct nhlt_acpi_table *nhlt;
+       int ret = 0;
+
+       if (chip->driver_type == AZX_DRIVER_SKL &&
+           pci->class != 0x040300) {
+               nhlt = intel_nhlt_init(&pci->dev);
+               if (nhlt) {
+                       if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) {
+                               ret = -ENODEV;
+                               dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n");
+                       }
+                       intel_nhlt_free(nhlt);
+               }
+       }
+       return ret;
+}
+
 static int azx_probe(struct pci_dev *pci,
                     const struct pci_device_id *pci_id)
 {
@@ -2055,6 +2078,17 @@ static int azx_probe(struct pci_dev *pci,
        card->private_data = chip;
        hda = container_of(chip, struct hda_intel, chip);
 
+       /*
+        * stop probe if digital microphones detected on Skylake+ platform
+        * with the DSP enabled. This is an opt-in behavior defined at build
+        * time or at run-time with a module parameter
+        */
+       if (dmic_detect) {
+               err = azx_check_dmic(pci, chip);
+               if (err < 0)
+                       goto out_free;
+       }
+
        pci_set_drvdata(pci, card);
 
        err = register_vga_switcheroo(chip);