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

ALSA: HD-Audio: SKL+: force HDaudio legacy or SKL+ driver selection

For HDaudio and Skylake drivers, add module parameter "pci_binding"

When pci_binding == 0 (AUTO), the PCI class/subclass info is used to
select drivers based on the presence of the DSP.

pci_binding == 1 (LEGACY) forces the use of the HDAudio legacy driver,
even if the DSP is present.

pci_binding == 2 (ASOC) forces the use of the ASOC driver. The
information on the DSP presence is bypassed.

The value for the module parameter needs to be identical for both
drivers. This parameter is intended as a back-up solution if the
automatic detection fails or when the DSP usage fails. Such cases
should be reported on the alsa-devel mailing list for analysis.
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c337104b
...@@ -98,6 +98,12 @@ enum { ...@@ -98,6 +98,12 @@ enum {
HDA_DEV_ASOC, HDA_DEV_ASOC,
}; };
enum {
SND_SKL_PCI_BIND_AUTO, /* automatic selection based on pci class */
SND_SKL_PCI_BIND_LEGACY,/* bind only with legacy driver */
SND_SKL_PCI_BIND_ASOC /* bind only with ASoC driver */
};
/* direction */ /* direction */
enum { enum {
HDA_INPUT, HDA_OUTPUT HDA_INPUT, HDA_OUTPUT
......
...@@ -172,6 +172,9 @@ module_param_array(beep_mode, bool, NULL, 0444); ...@@ -172,6 +172,9 @@ module_param_array(beep_mode, bool, NULL, 0444);
MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
"(0=off, 1=on) (default=1)."); "(0=off, 1=on) (default=1).");
#endif #endif
static int skl_pci_binding;
module_param_named(pci_binding, skl_pci_binding, int, 0444);
MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc");
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int param_set_xint(const char *val, const struct kernel_param *kp); static int param_set_xint(const char *val, const struct kernel_param *kp);
...@@ -2050,9 +2053,26 @@ static int azx_probe(struct pci_dev *pci, ...@@ -2050,9 +2053,26 @@ static int azx_probe(struct pci_dev *pci,
int err; int err;
/* check if this driver can be used on SKL+ Intel platforms */ /* check if this driver can be used on SKL+ Intel platforms */
if ((pci_id->driver_data & AZX_DCAPS_INTEL_SHARED) && if (pci_id->driver_data & AZX_DCAPS_INTEL_SHARED) {
pci->class != 0x040300) switch (skl_pci_binding) {
case SND_SKL_PCI_BIND_AUTO:
if (pci->class != 0x040300) {
dev_info(&pci->dev, "The DSP is enabled on this platform, aborting probe\n");
return -ENODEV; return -ENODEV;
}
dev_info(&pci->dev, "No DSP detected, continuing HDaudio legacy probe\n");
break;
case SND_SKL_PCI_BIND_LEGACY:
dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, bypassed detection logic\n");
break;
case SND_SKL_PCI_BIND_ASOC:
dev_info(&pci->dev, "Module parameter forced binding with SKL+ ASoC driver, aborting probe\n");
return -ENODEV;
default:
dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n");
break;
}
}
if (dev >= SNDRV_CARDS) if (dev >= SNDRV_CARDS)
return -ENODEV; return -ENODEV;
......
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
#include "../../../soc/codecs/hdac_hda.h" #include "../../../soc/codecs/hdac_hda.h"
#endif #endif
static int skl_pci_binding;
module_param_named(pci_binding, skl_pci_binding, int, 0444);
MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc");
/* /*
* initialize the PCI registers * initialize the PCI registers
...@@ -896,21 +899,6 @@ static int skl_first_init(struct hdac_bus *bus) ...@@ -896,21 +899,6 @@ static int skl_first_init(struct hdac_bus *bus)
unsigned short gcap; unsigned short gcap;
int cp_streams, pb_streams, start_idx; int cp_streams, pb_streams, start_idx;
/*
* detect DSP by checking class/subclass/prog-id information
* class=04 subclass 03 prog-if 00: no DSP, legacy driver needs to be used
* 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: either of DSP or legacy mode can be used
*/
if (pci->class == 0x040300) {
dev_err(bus->dev, "The DSP is not enabled on this platform, aborting probe\n");
return -ENODEV;
} else if (pci->class != 0x040100 && pci->class != 0x040380) {
dev_err(bus->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class);
return -ENODEV;
}
dev_info(bus->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
err = pci_request_regions(pci, "Skylake HD audio"); err = pci_request_regions(pci, "Skylake HD audio");
if (err < 0) if (err < 0)
return err; return err;
...@@ -984,6 +972,36 @@ static int skl_probe(struct pci_dev *pci, ...@@ -984,6 +972,36 @@ static int skl_probe(struct pci_dev *pci,
struct hdac_bus *bus = NULL; struct hdac_bus *bus = NULL;
int err; int err;
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");
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");
return -ENODEV;
case SND_SKL_PCI_BIND_ASOC:
dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n");
break;
default:
dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n");
break;
}
/* we use ext core ops, so provide NULL for ops here */ /* we use ext core ops, so provide NULL for ops here */
err = skl_create(pci, NULL, &skl); err = skl_create(pci, NULL, &skl);
if (err < 0) if (err < 0)
......
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