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