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"); 455