ALSA: hda: add Intel DSP configuration / probe code
[linux-2.6-block.git] / sound / soc / sof / sof-pci-dev.c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10
11 #include <linux/firmware.h>
12 #include <linux/module.h>
13 #include <linux/pci.h>
14 #include <linux/pm_runtime.h>
15 #include <sound/intel-dsp-config.h>
16 #include <sound/soc-acpi.h>
17 #include <sound/soc-acpi-intel-match.h>
18 #include <sound/sof.h>
19 #include "ops.h"
20
21 /* platform specific devices */
22 #include "intel/shim.h"
23 #include "intel/hda.h"
24
25 static char *fw_path;
26 module_param(fw_path, charp, 0444);
27 MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
28
29 static char *tplg_path;
30 module_param(tplg_path, charp, 0444);
31 MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
32
33 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
34 static const struct sof_dev_desc bxt_desc = {
35         .machines               = snd_soc_acpi_intel_bxt_machines,
36         .resindex_lpe_base      = 0,
37         .resindex_pcicfg_base   = -1,
38         .resindex_imr_base      = -1,
39         .irqindex_host_ipc      = -1,
40         .resindex_dma_base      = -1,
41         .chip_info = &apl_chip_info,
42         .default_fw_path = "intel/sof",
43         .default_tplg_path = "intel/sof-tplg",
44         .nocodec_fw_filename = "sof-apl.ri",
45         .nocodec_tplg_filename = "sof-apl-nocodec.tplg",
46         .ops = &sof_apl_ops,
47         .arch_ops = &sof_xtensa_arch_ops
48 };
49 #endif
50
51 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
52 static const struct sof_dev_desc glk_desc = {
53         .machines               = snd_soc_acpi_intel_glk_machines,
54         .resindex_lpe_base      = 0,
55         .resindex_pcicfg_base   = -1,
56         .resindex_imr_base      = -1,
57         .irqindex_host_ipc      = -1,
58         .resindex_dma_base      = -1,
59         .chip_info = &apl_chip_info,
60         .default_fw_path = "intel/sof",
61         .default_tplg_path = "intel/sof-tplg",
62         .nocodec_fw_filename = "sof-glk.ri",
63         .nocodec_tplg_filename = "sof-glk-nocodec.tplg",
64         .ops = &sof_apl_ops,
65         .arch_ops = &sof_xtensa_arch_ops
66 };
67 #endif
68
69 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
70 static struct snd_soc_acpi_mach sof_tng_machines[] = {
71         {
72                 .id = "INT343A",
73                 .drv_name = "edison",
74                 .sof_fw_filename = "sof-byt.ri",
75                 .sof_tplg_filename = "sof-byt.tplg",
76         },
77         {}
78 };
79
80 static const struct sof_dev_desc tng_desc = {
81         .machines               = sof_tng_machines,
82         .resindex_lpe_base      = 3,    /* IRAM, but subtract IRAM offset */
83         .resindex_pcicfg_base   = -1,
84         .resindex_imr_base      = 0,
85         .irqindex_host_ipc      = -1,
86         .resindex_dma_base      = -1,
87         .chip_info = &tng_chip_info,
88         .default_fw_path = "intel/sof",
89         .default_tplg_path = "intel/sof-tplg",
90         .nocodec_fw_filename = "sof-byt.ri",
91         .nocodec_tplg_filename = "sof-byt.tplg",
92         .ops = &sof_tng_ops,
93         .arch_ops = &sof_xtensa_arch_ops
94 };
95 #endif
96
97 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
98 static const struct sof_dev_desc cnl_desc = {
99         .machines               = snd_soc_acpi_intel_cnl_machines,
100         .resindex_lpe_base      = 0,
101         .resindex_pcicfg_base   = -1,
102         .resindex_imr_base      = -1,
103         .irqindex_host_ipc      = -1,
104         .resindex_dma_base      = -1,
105         .chip_info = &cnl_chip_info,
106         .default_fw_path = "intel/sof",
107         .default_tplg_path = "intel/sof-tplg",
108         .nocodec_fw_filename = "sof-cnl.ri",
109         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
110         .ops = &sof_cnl_ops,
111         .arch_ops = &sof_xtensa_arch_ops
112 };
113 #endif
114
115 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
116 static const struct sof_dev_desc cfl_desc = {
117         .machines               = snd_soc_acpi_intel_cnl_machines,
118         .resindex_lpe_base      = 0,
119         .resindex_pcicfg_base   = -1,
120         .resindex_imr_base      = -1,
121         .irqindex_host_ipc      = -1,
122         .resindex_dma_base      = -1,
123         .chip_info = &cnl_chip_info,
124         .default_fw_path = "intel/sof",
125         .default_tplg_path = "intel/sof-tplg",
126         .nocodec_fw_filename = "sof-cnl.ri",
127         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
128         .ops = &sof_cnl_ops,
129         .arch_ops = &sof_xtensa_arch_ops
130 };
131 #endif
132
133 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \
134         IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
135
136 static const struct sof_dev_desc cml_desc = {
137         .machines               = snd_soc_acpi_intel_cnl_machines,
138         .resindex_lpe_base      = 0,
139         .resindex_pcicfg_base   = -1,
140         .resindex_imr_base      = -1,
141         .irqindex_host_ipc      = -1,
142         .resindex_dma_base      = -1,
143         .chip_info = &cnl_chip_info,
144         .default_fw_path = "intel/sof",
145         .default_tplg_path = "intel/sof-tplg",
146         .nocodec_fw_filename = "sof-cnl.ri",
147         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
148         .ops = &sof_cnl_ops,
149         .arch_ops = &sof_xtensa_arch_ops
150 };
151 #endif
152
153 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
154 static const struct sof_dev_desc icl_desc = {
155         .machines               = snd_soc_acpi_intel_icl_machines,
156         .resindex_lpe_base      = 0,
157         .resindex_pcicfg_base   = -1,
158         .resindex_imr_base      = -1,
159         .irqindex_host_ipc      = -1,
160         .resindex_dma_base      = -1,
161         .chip_info = &icl_chip_info,
162         .default_fw_path = "intel/sof",
163         .default_tplg_path = "intel/sof-tplg",
164         .nocodec_fw_filename = "sof-icl.ri",
165         .nocodec_tplg_filename = "sof-icl-nocodec.tplg",
166         .ops = &sof_cnl_ops,
167         .arch_ops = &sof_xtensa_arch_ops
168 };
169 #endif
170
171 #if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE)
172 static const struct sof_dev_desc skl_desc = {
173         .machines               = snd_soc_acpi_intel_skl_machines,
174         .resindex_lpe_base      = 0,
175         .resindex_pcicfg_base   = -1,
176         .resindex_imr_base      = -1,
177         .irqindex_host_ipc      = -1,
178         .resindex_dma_base      = -1,
179         .chip_info = &skl_chip_info,
180         .default_fw_path = "intel/sof",
181         .default_tplg_path = "intel/sof-tplg",
182         .nocodec_fw_filename = "sof-skl.ri",
183         .nocodec_tplg_filename = "sof-skl-nocodec.tplg",
184         .ops = &sof_skl_ops,
185         .arch_ops = &sof_xtensa_arch_ops
186 };
187 #endif
188
189 #if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE)
190 static const struct sof_dev_desc kbl_desc = {
191         .machines               = snd_soc_acpi_intel_kbl_machines,
192         .resindex_lpe_base      = 0,
193         .resindex_pcicfg_base   = -1,
194         .resindex_imr_base      = -1,
195         .irqindex_host_ipc      = -1,
196         .resindex_dma_base      = -1,
197         .chip_info = &skl_chip_info,
198         .default_fw_path = "intel/sof",
199         .default_tplg_path = "intel/sof-tplg",
200         .nocodec_fw_filename = "sof-kbl.ri",
201         .nocodec_tplg_filename = "sof-kbl-nocodec.tplg",
202         .ops = &sof_skl_ops,
203         .arch_ops = &sof_xtensa_arch_ops
204 };
205 #endif
206
207 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
208 static const struct sof_dev_desc tgl_desc = {
209         .machines               = snd_soc_acpi_intel_tgl_machines,
210         .resindex_lpe_base      = 0,
211         .resindex_pcicfg_base   = -1,
212         .resindex_imr_base      = -1,
213         .irqindex_host_ipc      = -1,
214         .resindex_dma_base      = -1,
215         .chip_info = &tgl_chip_info,
216         .default_fw_path = "intel/sof",
217         .default_tplg_path = "intel/sof-tplg",
218         .nocodec_fw_filename = "sof-tgl.ri",
219         .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
220         .ops = &sof_cnl_ops,
221         .arch_ops = &sof_xtensa_arch_ops
222 };
223 #endif
224
225 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
226 static const struct sof_dev_desc ehl_desc = {
227         .machines               = snd_soc_acpi_intel_ehl_machines,
228         .resindex_lpe_base      = 0,
229         .resindex_pcicfg_base   = -1,
230         .resindex_imr_base      = -1,
231         .irqindex_host_ipc      = -1,
232         .resindex_dma_base      = -1,
233         .chip_info = &ehl_chip_info,
234         .default_fw_path = "intel/sof",
235         .default_tplg_path = "intel/sof-tplg",
236         .nocodec_fw_filename = "sof-ehl.ri",
237         .nocodec_tplg_filename = "sof-ehl-nocodec.tplg",
238         .ops = &sof_cnl_ops,
239         .arch_ops = &sof_xtensa_arch_ops
240 };
241 #endif
242
243 static const struct dev_pm_ops sof_pci_pm = {
244         SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
245         SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
246                            snd_sof_runtime_idle)
247 };
248
249 static void sof_pci_probe_complete(struct device *dev)
250 {
251         dev_dbg(dev, "Completing SOF PCI probe");
252
253         /* allow runtime_pm */
254         pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
255         pm_runtime_use_autosuspend(dev);
256
257         /*
258          * runtime pm for pci device is "forbidden" by default.
259          * so call pm_runtime_allow() to enable it.
260          */
261         pm_runtime_allow(dev);
262
263         /* mark last_busy for pm_runtime to make sure not suspend immediately */
264         pm_runtime_mark_last_busy(dev);
265
266         /* follow recommendation in pci-driver.c to decrement usage counter */
267         pm_runtime_put_noidle(dev);
268 }
269
270 static int sof_pci_probe(struct pci_dev *pci,
271                          const struct pci_device_id *pci_id)
272 {
273         struct device *dev = &pci->dev;
274         const struct sof_dev_desc *desc =
275                 (const struct sof_dev_desc *)pci_id->driver_data;
276         struct snd_soc_acpi_mach *mach;
277         struct snd_sof_pdata *sof_pdata;
278         const struct snd_sof_dsp_ops *ops;
279         int ret;
280
281         ret = snd_intel_dsp_driver_probe(pci);
282         if (ret != SND_INTEL_DSP_DRIVER_ANY &&
283             ret != SND_INTEL_DSP_DRIVER_SOF)
284                 return -ENODEV;
285
286         dev_dbg(&pci->dev, "PCI DSP detected");
287
288         /* get ops for platform */
289         ops = desc->ops;
290         if (!ops) {
291                 dev_err(dev, "error: no matching PCI descriptor ops\n");
292                 return -ENODEV;
293         }
294
295         sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
296         if (!sof_pdata)
297                 return -ENOMEM;
298
299         ret = pcim_enable_device(pci);
300         if (ret < 0)
301                 return ret;
302
303         ret = pci_request_regions(pci, "Audio DSP");
304         if (ret < 0)
305                 return ret;
306
307 #if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
308         /* force nocodec mode */
309         dev_warn(dev, "Force to use nocodec mode\n");
310         mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
311         if (!mach) {
312                 ret = -ENOMEM;
313                 goto release_regions;
314         }
315         ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
316         if (ret < 0)
317                 goto release_regions;
318
319 #else
320         /* find machine */
321         mach = snd_soc_acpi_find_machine(desc->machines);
322         if (!mach) {
323                 dev_warn(dev, "warning: No matching ASoC machine driver found\n");
324         } else {
325                 mach->mach_params.platform = dev_name(dev);
326                 sof_pdata->fw_filename = mach->sof_fw_filename;
327                 sof_pdata->tplg_filename = mach->sof_tplg_filename;
328         }
329 #endif /* CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE */
330
331         sof_pdata->name = pci_name(pci);
332         sof_pdata->machine = mach;
333         sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
334         sof_pdata->dev = dev;
335         sof_pdata->platform = dev_name(dev);
336
337         /* alternate fw and tplg filenames ? */
338         if (fw_path)
339                 sof_pdata->fw_filename_prefix = fw_path;
340         else
341                 sof_pdata->fw_filename_prefix =
342                         sof_pdata->desc->default_fw_path;
343
344         if (tplg_path)
345                 sof_pdata->tplg_filename_prefix = tplg_path;
346         else
347                 sof_pdata->tplg_filename_prefix =
348                         sof_pdata->desc->default_tplg_path;
349
350 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
351         /* set callback to enable runtime_pm */
352         sof_pdata->sof_probe_complete = sof_pci_probe_complete;
353 #endif
354         /* call sof helper for DSP hardware probe */
355         ret = snd_sof_device_probe(dev, sof_pdata);
356         if (ret) {
357                 dev_err(dev, "error: failed to probe DSP hardware!\n");
358                 goto release_regions;
359         }
360
361 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
362         sof_pci_probe_complete(dev);
363 #endif
364
365         return ret;
366
367 release_regions:
368         pci_release_regions(pci);
369
370         return ret;
371 }
372
373 static void sof_pci_remove(struct pci_dev *pci)
374 {
375         /* call sof helper for DSP hardware remove */
376         snd_sof_device_remove(&pci->dev);
377
378         /* follow recommendation in pci-driver.c to increment usage counter */
379         pm_runtime_get_noresume(&pci->dev);
380
381         /* release pci regions and disable device */
382         pci_release_regions(pci);
383 }
384
385 /* PCI IDs */
386 static const struct pci_device_id sof_pci_ids[] = {
387 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
388         { PCI_DEVICE(0x8086, 0x119a),
389                 .driver_data = (unsigned long)&tng_desc},
390 #endif
391 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
392         /* BXT-P & Apollolake */
393         { PCI_DEVICE(0x8086, 0x5a98),
394                 .driver_data = (unsigned long)&bxt_desc},
395         { PCI_DEVICE(0x8086, 0x1a98),
396                 .driver_data = (unsigned long)&bxt_desc},
397 #endif
398 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
399         { PCI_DEVICE(0x8086, 0x3198),
400                 .driver_data = (unsigned long)&glk_desc},
401 #endif
402 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
403         { PCI_DEVICE(0x8086, 0x9dc8),
404                 .driver_data = (unsigned long)&cnl_desc},
405 #endif
406 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
407         { PCI_DEVICE(0x8086, 0xa348),
408                 .driver_data = (unsigned long)&cfl_desc},
409 #endif
410 #if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE)
411         { PCI_DEVICE(0x8086, 0x9d71),
412                 .driver_data = (unsigned long)&kbl_desc},
413 #endif
414 #if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE)
415         { PCI_DEVICE(0x8086, 0x9d70),
416                 .driver_data = (unsigned long)&skl_desc},
417 #endif
418 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
419         { PCI_DEVICE(0x8086, 0x34C8),
420                 .driver_data = (unsigned long)&icl_desc},
421 #endif
422 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
423         { PCI_DEVICE(0x8086, 0x02c8),
424                 .driver_data = (unsigned long)&cml_desc},
425 #endif
426 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
427         { PCI_DEVICE(0x8086, 0x06c8),
428                 .driver_data = (unsigned long)&cml_desc},
429 #endif
430 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
431         { PCI_DEVICE(0x8086, 0xa0c8),
432                 .driver_data = (unsigned long)&tgl_desc},
433 #endif
434 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
435         { PCI_DEVICE(0x8086, 0x4b55),
436                 .driver_data = (unsigned long)&ehl_desc},
437 #endif
438         { 0, }
439 };
440 MODULE_DEVICE_TABLE(pci, sof_pci_ids);
441
442 /* pci_driver definition */
443 static struct pci_driver snd_sof_pci_driver = {
444         .name = "sof-audio-pci",
445         .id_table = sof_pci_ids,
446         .probe = sof_pci_probe,
447         .remove = sof_pci_remove,
448         .driver = {
449                 .pm = &sof_pci_pm,
450         },
451 };
452 module_pci_driver(snd_sof_pci_driver);
453
454 MODULE_LICENSE("Dual BSD/GPL");