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