]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/pci/hda/hda_intel.c
ALSA: hda: Add Clevo W65_67SB the power_save blacklist
[linux.git] / sound / pci / hda / hda_intel.c
index cf53fbd872ee34526d277bd4f479c1a5024b32b6..e2d0a7c3ab261212b20dba5cb6cbbbd4a68b8fc4 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/clocksource.h>
 #include <linux/time.h>
 #include <linux/completion.h>
+#include <linux/acpi.h>
 
 #ifdef CONFIG_X86
 /* for snoop control */
@@ -46,7 +47,7 @@
 #include <sound/initval.h>
 #include <sound/hdaudio.h>
 #include <sound/hda_i915.h>
-#include <sound/intel-nhlt.h>
+#include <sound/intel-dsp-config.h>
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/firmware.h>
@@ -124,7 +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);
+static bool dmic_detect = 1;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -160,7 +161,9 @@ 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");
+MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
+                            "(0=off, 1=on) (default=1); "
+                "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
 
 #ifdef CONFIG_PM
 static int param_set_xint(const char *val, const struct kernel_param *kp);
@@ -280,12 +283,13 @@ enum {
 
 /* quirks for old Intel chipsets */
 #define AZX_DCAPS_INTEL_ICH \
-       (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE)
+       (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE |\
+        AZX_DCAPS_SYNC_WRITE)
 
 /* quirks for Intel PCH */
 #define AZX_DCAPS_INTEL_PCH_BASE \
        (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 /* PCH up to IVB; no runtime PM; bind with i915 gfx */
 #define AZX_DCAPS_INTEL_PCH_NOPM \
@@ -300,13 +304,13 @@ enum {
 #define AZX_DCAPS_INTEL_HASWELL \
        (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\
         AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */
 #define AZX_DCAPS_INTEL_BROADWELL \
        (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\
         AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 #define AZX_DCAPS_INTEL_BAYTRAIL \
        (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
@@ -368,8 +372,6 @@ enum {
                                        ((pci)->device == 0x160c))
 
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
-#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8)
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -1280,11 +1282,17 @@ static void init_vga_switcheroo(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
        struct pci_dev *p = get_bound_vga(chip->pci);
+       struct pci_dev *parent;
        if (p) {
                dev_info(chip->card->dev,
                         "Handle vga_switcheroo audio client\n");
                hda->use_vga_switcheroo = 1;
-               chip->bus.keep_power = 1; /* cleared in either gpu_bound op or codec probe */
+
+               /* cleared in either gpu_bound op or codec probe, or when its
+                * upstream port has _PR3 (i.e. dGPU).
+                */
+               parent = pci_upstream_bridge(p);
+               chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1;
                chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
                pci_dev_put(p);
        }
@@ -1382,8 +1390,11 @@ static int azx_free(struct azx *chip)
 static int azx_dev_disconnect(struct snd_device *device)
 {
        struct azx *chip = device->device_data;
+       struct hdac_bus *bus = azx_bus(chip);
 
        chip->bus.shutdown = 1;
+       cancel_work_sync(&bus->unsol_work);
+
        return 0;
 }
 
@@ -1393,6 +1404,43 @@ static int azx_dev_free(struct snd_device *device)
 }
 
 #ifdef SUPPORT_VGA_SWITCHEROO
+#ifdef CONFIG_ACPI
+/* ATPX is in the integrated GPU's namespace */
+static bool atpx_present(void)
+{
+       struct pci_dev *pdev = NULL;
+       acpi_handle dhandle, atpx_handle;
+       acpi_status status;
+
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+               dhandle = ACPI_HANDLE(&pdev->dev);
+               if (dhandle) {
+                       status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+                       if (!ACPI_FAILURE(status)) {
+                               pci_dev_put(pdev);
+                               return true;
+                       }
+               }
+       }
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+               dhandle = ACPI_HANDLE(&pdev->dev);
+               if (dhandle) {
+                       status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+                       if (!ACPI_FAILURE(status)) {
+                               pci_dev_put(pdev);
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+#else
+static bool atpx_present(void)
+{
+       return false;
+}
+#endif
+
 /*
  * Check of disabled HDMI controller by vga_switcheroo
  */
@@ -1404,6 +1452,22 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci)
        switch (pci->vendor) {
        case PCI_VENDOR_ID_ATI:
        case PCI_VENDOR_ID_AMD:
+               if (pci->devfn == 1) {
+                       p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
+                                                       pci->bus->number, 0);
+                       if (p) {
+                               /* ATPX is in the integrated GPU's ACPI namespace
+                                * rather than the dGPU's namespace. However,
+                                * the dGPU is the one who is involved in
+                                * vgaswitcheroo.
+                                */
+                               if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
+                                   atpx_present())
+                                       return p;
+                               pci_dev_put(p);
+                       }
+               }
+               break;
        case PCI_VENDOR_ID_NVIDIA:
                if (pci->devfn == 1) {
                        p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
@@ -1753,10 +1817,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
        if (!azx_snoop(chip))
                azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
 
-       /* Workaround for a communication error on CFL (bko#199007) and CNL */
-       if (IS_CFL(pci) || IS_CNL(pci))
-               azx_bus(chip)->polling_mode = 1;
-
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
                chip->bus.needs_damn_long_delay = 1;
@@ -2020,25 +2080,6 @@ 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)
 {
@@ -2056,6 +2097,18 @@ static int azx_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
+       /*
+        * stop probe if another Intel's DSP driver should be activated
+        */
+       if (dmic_detect) {
+               err = snd_intel_dsp_driver_probe(pci);
+               if (err != SND_INTEL_DSP_DRIVER_ANY &&
+                   err != SND_INTEL_DSP_DRIVER_LEGACY)
+                       return -ENODEV;
+       } else {
+               dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
+       }
+
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                           0, &card);
        if (err < 0) {
@@ -2069,17 +2122,6 @@ 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);
@@ -2146,6 +2188,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */
        SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
@@ -2396,6 +2440,9 @@ static const struct pci_device_id azx_ids[] = {
        /* CometLake-H */
        { PCI_DEVICE(0x8086, 0x06C8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* CometLake-S */
+       { PCI_DEVICE(0x8086, 0xa3f0),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Icelake */
        { PCI_DEVICE(0x8086, 0x34c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
@@ -2560,13 +2607,38 @@ static const struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x1002, 0xaac8),
          .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
        { PCI_DEVICE(0x1002, 0xaad8),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
-       { PCI_DEVICE(0x1002, 0xaae8),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        { PCI_DEVICE(0x1002, 0xaae0),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xaae8),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        { PCI_DEVICE(0x1002, 0xaaf0),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xaaf8),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab00),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab08),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab10),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab18),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab20),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
+       { PCI_DEVICE(0x1002, 0xab38),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        /* VIA VT8251/VT8237A */
        { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
        /* VIA GFX VT7122/VX900 */