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

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.com


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4963d66b
Loading
Loading
Loading
Loading
+81 −16
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz>

#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/core.h>
#include <sound/intel-dsp-config.h>
#include <sound/intel-nhlt.h>
@@ -17,6 +20,10 @@ MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=lega
#define FLAG_SST			BIT(0)
#define FLAG_SOF			BIT(1)
#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 {
	u32 flags;
@@ -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,
	},
#endif
@@ -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,
	},
#endif
@@ -204,18 +211,50 @@ static const struct config_entry config_table[] = {
					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,
	},
#endif
/* 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,
	},
#endif
@@ -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,
	},
#endif
@@ -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,
	},
#endif
@@ -303,6 +341,28 @@ static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
	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)
{
	const struct config_entry *cfg;
@@ -336,14 +396,18 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci)
		return SND_INTEL_DSP_DRIVER_ANY;

	if (cfg->flags & FLAG_SOF) {
		if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC) {
			if (snd_intel_dsp_check_dmic(pci)) {
				dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
		if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
		    snd_intel_dsp_check_soundwire(pci) > 0) {
			dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
			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;
		}
		if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
			return SND_INTEL_DSP_DRIVER_SOF;
	}

	if (cfg->flags & FLAG_SST)
@@ -355,3 +419,4 @@ EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel DSP config driver");
MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);