Commit 06508575 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Takashi Iwai

ALSA: hda: add autodetection for SoundWire

When an ACPI companion device is present and the SoundWire link mask
information is available, use SoundWire instead of legacy HDA or
Skylake drivers.

The SOF driver is selected when SoundWire or DMIC are detected. There
is no precedence at this level. In the SOF driver proper, SoundWire
will be handled first since it is mutually exclusive with HDaudio.

Known devices with an existing DMI quirk bypass this detection to
avoid any dependency on ACPI/DSDT tables.
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200409190251.16569-1-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4963d66b
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz> // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz>
#include <linux/acpi.h>
#include <linux/bits.h> #include <linux/bits.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/intel-dsp-config.h> #include <sound/intel-dsp-config.h>
#include <sound/intel-nhlt.h> #include <sound/intel-nhlt.h>
...@@ -14,9 +17,13 @@ static int dsp_driver; ...@@ -14,9 +17,13 @@ static int dsp_driver;
module_param(dsp_driver, int, 0444); module_param(dsp_driver, int, 0444);
MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)"); MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)");
#define FLAG_SST BIT(0) #define FLAG_SST BIT(0)
#define FLAG_SOF BIT(1) #define FLAG_SOF BIT(1)
#define FLAG_SOF_ONLY_IF_DMIC BIT(16) #define FLAG_SOF_ONLY_IF_DMIC BIT(16)
#define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17)
#define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \
FLAG_SOF_ONLY_IF_SOUNDWIRE)
struct config_entry { struct config_entry {
u32 flags; u32 flags;
...@@ -166,7 +173,7 @@ static const struct config_entry config_table[] = { ...@@ -166,7 +173,7 @@ static const struct config_entry config_table[] = {
} }
}, },
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x9dc8, .device = 0x9dc8,
}, },
#endif #endif
...@@ -187,7 +194,7 @@ static const struct config_entry config_table[] = { ...@@ -187,7 +194,7 @@ static const struct config_entry config_table[] = {
} }
}, },
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0xa348, .device = 0xa348,
}, },
#endif #endif
...@@ -204,18 +211,50 @@ static const struct config_entry config_table[] = { ...@@ -204,18 +211,50 @@ static const struct config_entry config_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_SYS_VENDOR, "Google"),
} }
}, },
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
},
},
{
/* early version of SKU 09C6 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
},
},
{} {}
} }
}, },
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x02c8, .device = 0x02c8,
}, },
#endif #endif
/* Cometlake-H */ /* Cometlake-H */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF,
.device = 0x06c8,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
},
},
{}
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x06c8, .device = 0x06c8,
}, },
#endif #endif
...@@ -236,7 +275,7 @@ static const struct config_entry config_table[] = { ...@@ -236,7 +275,7 @@ static const struct config_entry config_table[] = {
} }
}, },
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x34c8, .device = 0x34c8,
}, },
#endif #endif
...@@ -256,9 +295,8 @@ static const struct config_entry config_table[] = { ...@@ -256,9 +295,8 @@ static const struct config_entry config_table[] = {
{} {}
} }
}, },
{ {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0xa0c8, .device = 0xa0c8,
}, },
#endif #endif
...@@ -303,6 +341,28 @@ static int snd_intel_dsp_check_dmic(struct pci_dev *pci) ...@@ -303,6 +341,28 @@ static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
return ret; return ret;
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
{
struct sdw_intel_acpi_info info;
acpi_handle handle;
int ret;
handle = ACPI_HANDLE(&pci->dev);
ret = sdw_intel_acpi_scan(handle, &info);
if (ret < 0)
return ret;
return info.link_mask;
}
#else
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
{
return 0;
}
#endif
int snd_intel_dsp_driver_probe(struct pci_dev *pci) int snd_intel_dsp_driver_probe(struct pci_dev *pci)
{ {
const struct config_entry *cfg; const struct config_entry *cfg;
...@@ -336,14 +396,18 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) ...@@ -336,14 +396,18 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci)
return SND_INTEL_DSP_DRIVER_ANY; return SND_INTEL_DSP_DRIVER_ANY;
if (cfg->flags & FLAG_SOF) { if (cfg->flags & FLAG_SOF) {
if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC) { if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
if (snd_intel_dsp_check_dmic(pci)) { snd_intel_dsp_check_soundwire(pci) > 0) {
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
return SND_INTEL_DSP_DRIVER_SOF; return SND_INTEL_DSP_DRIVER_SOF;
} }
} else { if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
snd_intel_dsp_check_dmic(pci)) {
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
return SND_INTEL_DSP_DRIVER_SOF; return SND_INTEL_DSP_DRIVER_SOF;
} }
if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
return SND_INTEL_DSP_DRIVER_SOF;
} }
if (cfg->flags & FLAG_SST) if (cfg->flags & FLAG_SST)
...@@ -355,3 +419,4 @@ EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); ...@@ -355,3 +419,4 @@ EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel DSP config driver"); MODULE_DESCRIPTION("Intel DSP config driver");
MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);
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