[alsa-devel] [PATCH] ALSA: hda: add Intel DSP configuration / probe code

Jaroslav Kysela perex at perex.cz
Wed Oct 2 18:39:04 CEST 2019


Dne 02. 10. 19 v 18:00 Pierre-Louis Bossart napsal(a):
> Thanks Jaroslav, see comments below.
> 
> No real objections on the concept, but we should fold NODSP/LEGACY 
> together, deal with all the PCI IDs handled by SOF and deal with the 
> cases where we want the SKL driver (SKL/KBL/APL Chromebooks with DMICs)

Thank you for your comment. It was just a first shot to resolve the detection
issue properly.

>> diff --git a/include/sound/intel-dsp-config.h b/include/sound/intel-dsp-config.h
>> new file mode 100644
>> index 000000000000..700f86282a83
>> --- /dev/null
>> +++ b/include/sound/intel-dsp-config.h
>> @@ -0,0 +1,35 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + *  intel-dsp-config.h - Intel DSP config
>> + *
>> + *  Copyright (c) 2019 Jaroslav Kysela <perex at perex.cz>
>> + */
>> +
>> +#ifndef __INTEL_DSP_CONFIG_H__
>> +#define __INTEL_DSP_CONFIG_H__
>> +
>> +struct pci_dev;
>> +
>> +enum {
>> +	SND_INTEL_DSP_DRIVER_ANY = 0,
>> +	SND_INTEL_DSP_DRIVER_NODSP,
>> +	SND_INTEL_DSP_DRIVER_LEGACY,
> 
> not sure what 'LEGACY' means here? This is really the same as NODSP.
> 
>> +	SND_INTEL_DSP_DRIVER_SST,
>> +	SND_INTEL_DSP_DRIVER_SOF,
>> +	SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_SOF
>> +};
> 
>> +static int dsp_driver;
>> +
>> +module_param(dsp_driver, int, 0444);
>> +MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=noDSP, 2=legacy, 3=SST, 4=SOF)");
> 
> Same here, noDSP==legacy.

I just had a good feeling to add another state where we know that the DSP is
not present. But yes, for the driver selection it's an extra state and
everything will fall-back to the legacy hda driver.

>> +
>> +static const u16 sof_skl_table[] = {
> 
> we should remove the reference to SKL, this is historical and there are 
> already 2 generations that have little to do with SKL.
> 
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
>> +	0x02c8,	/* Cometlake-LP */
>> +#endif
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
>> +	0x06c8,	/* Cometlake-H */
>> +#endif
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
>> +	0x3198,	/* Geminilake */
>> +#endif
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
>> +	0x5a98,	/* Broxton-P (Appololake) */
>> +#endif
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
>> +	0x9dc8, /* Cannonlake */
>> +#endif
>> +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
>> +	0xa348, /* Coffelake */
>> +#endif
> 
> What about all the other PCI IDs that SOF handles, e.g. TigerLake, etc?

There is no PCI ID clash, only one driver will call the DSP probe and
SND_INTEL_DSP_DRIVER_ANY will be returned in this case.

> Also how do you deal with SKL/KBL cases with DMICs? They would need to 
> use the SST driver (for Chromebooks mainly)

As I noted in the comment, we can add dmi quirks on top. I just do not have
enough information - can I take the hints from the pull request (your code)
you already mentioned?

> Even for APL, the 'official' driver is still SST for Chromebooks. SOF 
> should work but there will probably be missing firmware/topology files.

I can rework this part of course. I'll send v2 patch.

>> +};
>> +
>> +static int snd_intel_dsp_check_device(u16 device, const u16 *table, u32 len)
>> +{
>> +	for (; len > 0; len--, table++) {
>> +		if (*table == device)
>> +			return 1;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
>> +{
>> +	struct nhlt_acpi_table *nhlt;
>> +	int ret = 0;
>> +
>> +	if (snd_intel_dsp_check_device(pci->device, sof_skl_table, ARRAY_SIZE(sof_skl_table))) {
>> +		nhlt = intel_nhlt_init(&pci->dev);
>> +		if (nhlt) {
>> +			if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt))
>> +				ret = 1;
>> +			intel_nhlt_free(nhlt);
>> +		}
>> +	}
>> +	return ret;
>> +}
>> +
>> +int snd_intel_dsp_driver_probe(struct pci_dev *pci)
>> +{
>> +	if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
>> +		return dsp_driver;
>> +
>> +	/* Intel vendor only */
>> +	if (snd_BUG_ON(pci->vendor != 0x8086))
>> +		return SND_INTEL_DSP_DRIVER_ANY;
>> +
>> +	/*
>> +	 * detect DSP by checking class/subclass/prog-id information
>> +	 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
>> +	 * class=04 subclass 01 prog-if 00: DSP is present
>> +	 *  (and may be required e.g. for DMIC or SSP support)
>> +	 * class=04 subclass 03 prog-if 80: use DSP or legacy mode
>> +	 */
>> +	if (pci->class == 0x040300)
>> +		return SND_INTEL_DSP_DRIVER_NODSP;
>> +	if (pci->class != 0x040100 && pci->class != 0x040380) {
>> +		dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDA legacy driver\n", pci->class);
>> +		return SND_INTEL_DSP_DRIVER_LEGACY;
> 
> Again these two cases are the same. The DSP is not enabled so the 
> HDaudio legacy driver needs to be used.
> 
>> +	}
>> +
>> +	dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
>> +
>> +	/* DMIC check for Skylake+ */
>> +	if (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;
> 
> That's not fully correct, see comment above on Chromebooks.

And it's really visible now at least :-) I welcome any hints what's wrong.

>> +	}
>> +
>> +	return SND_INTEL_DSP_DRIVER_ANY;
>> +}
>> +
>> +EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
>> +
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_DESCRIPTION("Intel DSP config driver");
>> diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c
>> index daede96f28ee..097ff6c10099 100644
>> --- a/sound/hda/intel-nhlt.c
>> +++ b/sound/hda/intel-nhlt.c
>> @@ -102,6 +102,3 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
>>   	return dmic_geo;
>>   }
>>   EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);
>> -
>> -MODULE_LICENSE("GPL v2");
>> -MODULE_DESCRIPTION("Intel NHLT driver");
>> diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
>> index dae47a45b2b8..bd48335d09d7 100644
>> --- a/sound/pci/hda/Kconfig
>> +++ b/sound/pci/hda/Kconfig
>> @@ -12,7 +12,7 @@ config SND_HDA_INTEL
>>   	tristate "HD Audio PCI"
>>   	depends on SND_PCI
>>   	select SND_HDA
>> -	select SND_INTEL_NHLT if ACPI
>> +	select SND_INTEL_DSP_CONFIG
>>   	help
>>   	  Say Y here to include support for Intel "High Definition
>>   	  Audio" (Azalia) and its compatible devices.
>> @@ -23,15 +23,6 @@ config SND_HDA_INTEL
>>   	  To compile this driver as a module, choose M here: the module
>>   	  will be called snd-hda-intel.
>>   
>> -config SND_HDA_INTEL_DETECT_DMIC
>> -	bool "DMIC detection and probe abort"
>> -	depends on SND_HDA_INTEL
>> -	help
>> -	  Say Y to detect digital microphones on SKL+ devices. DMICs
>> -	  cannot be handled by the HDaudio legacy driver and are
>> -	  currently only supported by the SOF driver.
>> -	  If unsure say N.
>> -
>>   config SND_HDA_TEGRA
>>   	tristate "NVIDIA Tegra HD Audio"
>>   	depends on ARCH_TEGRA
>> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
>> index 240f4ca76391..c76c2deea47c 100644
>> --- a/sound/pci/hda/hda_intel.c
>> +++ b/sound/pci/hda/hda_intel.c
>> @@ -46,7 +46,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 +124,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 no_dsp_driver;
>>   
>>   module_param_array(index, int, NULL, 0444);
>>   MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
>> @@ -159,8 +159,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");
>> +module_param(no_dsp_driver, bool, 0444);
>> +MODULE_PARM_DESC(no_dsp_driver, "Do not return from probe when another DSP driver claims device");
> 
> maybe: "force this driver to be used and bypass DSP driver selection"
> 
>>   
>>   #ifdef CONFIG_PM
>>   static int param_set_xint(const char *val, const struct kernel_param *kp);
>> @@ -2020,25 +2020,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 +2037,17 @@ static int azx_probe(struct pci_dev *pci,
>>   		return -ENOENT;
>>   	}
>>   
>> +	/*
>> +	 * stop probe if another Intel's DSP driver should be activated
>> +	 */
>> +	if (!no_dsp_driver) {
>> +		err = snd_intel_dsp_driver_probe(pci);
>> +		if (err != SND_INTEL_DSP_DRIVER_ANY &&
>> +		    err != SND_INTEL_DSP_DRIVER_NODSP &&
>> +		    err != SND_INTEL_DSP_DRIVER_LEGACY)
> 
> merge these last two
> 
>> +			return -ENODEV;
>> +	}
>> +
> 
> [snip]
> 
>> diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
>> index 141dbbf975ac..58ba3e9469ba 100644
>> --- a/sound/soc/intel/skylake/skl.c
>> +++ b/sound/soc/intel/skylake/skl.c
>> @@ -27,6 +27,7 @@
>>   #include <sound/hda_i915.h>
>>   #include <sound/hda_codec.h>
>>   #include <sound/intel-nhlt.h>
>> +#include <sound/intel-dsp-config.h>
>>   #include "skl.h"
>>   #include "skl-sst-dsp.h"
>>   #include "skl-sst-ipc.h"
>> @@ -987,22 +988,10 @@ static int skl_probe(struct pci_dev *pci,
>>   
>>   	switch (skl_pci_binding) {
>>   	case SND_SKL_PCI_BIND_AUTO:
>> -		/*
>> -		 * detect DSP by checking class/subclass/prog-id information
>> -		 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
>> -		 * class=04 subclass 01 prog-if 00: DSP is present
>> -		 *   (and may be required e.g. for DMIC or SSP support)
>> -		 * class=04 subclass 03 prog-if 80: use DSP or legacy mode
>> -		 */
>> -		if (pci->class == 0x040300) {
>> -			dev_info(&pci->dev, "The DSP is not enabled on this platform, aborting probe\n");
>> +		err = snd_intel_dsp_driver_probe(pci);
>> +		if (err != SND_INTEL_DSP_DRIVER_ANY &&
>> +		    err != SND_INTEL_DSP_DRIVER_SST)
> 
> I didn't see a case where SST was selected?
> 
>>   			return -ENODEV;
>> -		}
>> -		if (pci->class != 0x040100 && pci->class != 0x040380) {
>> -			dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class);
>> -			return -ENODEV;
>> -		}
>> -		dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
>>   		break;
>>   	case SND_SKL_PCI_BIND_LEGACY:
>>   		dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, aborting probe\n");
> 
> Do we still need this skl_pci_binding now? I think it's remaining code 
> from the time when we only used the PCI class, which led to breaking 
> Linus' laptop (and others)...
> 
>> diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
>> index 479ba249e219..8a5d5c0f95f2 100644
>> --- a/sound/soc/sof/intel/Kconfig
>> +++ b/sound/soc/sof/intel/Kconfig
>> @@ -286,7 +286,7 @@ config SND_SOC_SOF_HDA
>>   	tristate
>>   	select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK
>>   	select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC
>> -	select SND_INTEL_NHLT if ACPI
>> +	select SND_INTEL_DSP_CONFIG
>>   	help
>>   	  This option is not user-selectable but automagically handled by
>>   	  'select' statements at a higher level
>> diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
>> index d66412a77873..3a9e0e2a150d 100644
>> --- a/sound/soc/sof/sof-pci-dev.c
>> +++ b/sound/soc/sof/sof-pci-dev.c
>> @@ -12,6 +12,7 @@
>>   #include <linux/module.h>
>>   #include <linux/pci.h>
>>   #include <linux/pm_runtime.h>
>> +#include <sound/intel-dsp-config.h>
>>   #include <sound/soc-acpi.h>
>>   #include <sound/soc-acpi-intel-match.h>
>>   #include <sound/sof.h>
>> @@ -277,6 +278,11 @@ static int sof_pci_probe(struct pci_dev *pci,
>>   	const struct snd_sof_dsp_ops *ops;
>>   	int ret;
>>   
>> +	ret = snd_intel_dsp_driver_probe(pci);
>> +	if (ret != SND_INTEL_DSP_DRIVER_ANY &&
>> +	    ret != SND_INTEL_DSP_DRIVER_SOF)
>> +		return -ENODEV;
>> +
>>   	dev_dbg(&pci->dev, "PCI DSP detected");
>>   
>>   	/* get ops for platform */
>>


-- 
Jaroslav Kysela <perex at perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.


More information about the Alsa-devel mailing list