1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz>
4 #include <linux/bits.h>
6 #include <linux/module.h>
8 #include <sound/core.h>
9 #include <sound/intel-dsp-config.h>
10 #include <sound/intel-nhlt.h>
12 static int dsp_driver;
14 module_param(dsp_driver, int, 0444);
15 MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)");
17 #define FLAG_SST BIT(0)
18 #define FLAG_SOF BIT(1)
19 #define FLAG_SOF_ONLY_IF_DMIC BIT(16)
24 const struct dmi_system_id *dmi_table;
29 * - the order of similar PCI ID entries is important!
30 * - the first successful match will win
32 static const struct config_entry config_table[] = {
34 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_LP)
40 #elif IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
47 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_H)
52 #elif IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
59 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
66 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
68 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
73 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
77 .dmi_table = (const struct dmi_system_id []) {
79 .ident = "Google Chromebooks",
81 DMI_MATCH(DMI_SYS_VENDOR, "Google"),
88 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK)
95 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
97 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
102 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
104 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
108 /* Appololake (Broxton-P) */
109 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
113 .dmi_table = (const struct dmi_system_id []) {
115 .ident = "Up Squared",
117 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
118 DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"),
125 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL)
132 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
134 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
138 /* Sunrise Point-LP */
139 #if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE)
141 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
146 #if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE)
148 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
153 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
155 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
160 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
162 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
168 static const struct config_entry *snd_intel_dsp_find_config
169 (struct pci_dev *pci, const struct config_entry *table, u32 len)
173 device = pci->device;
174 for (; len > 0; len--, table++) {
175 if (table->device != device)
177 if (table->dmi_table && !dmi_check_system(table->dmi_table))
184 static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
186 struct nhlt_acpi_table *nhlt;
189 nhlt = intel_nhlt_init(&pci->dev);
191 if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt))
193 intel_nhlt_free(nhlt);
198 int snd_intel_dsp_driver_probe(struct pci_dev *pci)
200 const struct config_entry *cfg;
202 if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
205 /* Intel vendor only */
206 if (snd_BUG_ON(pci->vendor != 0x8086))
207 return SND_INTEL_DSP_DRIVER_ANY;
210 * detect DSP by checking class/subclass/prog-id information
211 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
212 * class=04 subclass 01 prog-if 00: DSP is present
213 * (and may be required e.g. for DMIC or SSP support)
214 * class=04 subclass 03 prog-if 80: use DSP or legacy mode
216 if (pci->class == 0x040300)
217 return SND_INTEL_DSP_DRIVER_LEGACY;
218 if (pci->class != 0x040100 && pci->class != 0x040380) {
219 dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDA legacy driver\n", pci->class);
220 return SND_INTEL_DSP_DRIVER_LEGACY;
223 dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
225 /* find the configuration for the specific device */
226 cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
228 return SND_INTEL_DSP_DRIVER_ANY;
230 if (cfg->flags & FLAG_SOF) {
231 if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC) {
232 if (snd_intel_dsp_check_dmic(pci)) {
233 dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
234 return SND_INTEL_DSP_DRIVER_SOF;
237 return SND_INTEL_DSP_DRIVER_SOF;
241 if (cfg->flags & FLAG_SST)
242 return SND_INTEL_DSP_DRIVER_SST;
244 return SND_INTEL_DSP_DRIVER_LEGACY;
246 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
248 MODULE_LICENSE("GPL v2");
249 MODULE_DESCRIPTION("Intel DSP config driver");