1 // SPDX-License-Identifier: (GPL-2.0-only 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/dmi.h> 13 #include <linux/module.h> 14 #include <linux/pci.h> 15 #include <linux/pm_runtime.h> 16 #include <sound/intel-dsp-config.h> 17 #include <sound/soc-acpi.h> 18 #include <sound/soc-acpi-intel-match.h> 19 #include <sound/sof.h> 20 #include "ops.h" 21 22 /* platform specific devices */ 23 #include "intel/shim.h" 24 #include "intel/hda.h" 25 26 static char *fw_path; 27 module_param(fw_path, charp, 0444); 28 MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); 29 30 static char *tplg_path; 31 module_param(tplg_path, charp, 0444); 32 MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); 33 34 static int sof_pci_debug; 35 module_param_named(sof_pci_debug, sof_pci_debug, int, 0444); 36 MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)"); 37 38 static const char *sof_override_tplg_name; 39 40 #define SOF_PCI_DISABLE_PM_RUNTIME BIT(0) 41 42 static int sof_tplg_cb(const struct dmi_system_id *id) 43 { 44 sof_override_tplg_name = id->driver_data; 45 return 1; 46 } 47 48 static const struct dmi_system_id sof_tplg_table[] = { 49 { 50 .callback = sof_tplg_cb, 51 .matches = { 52 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"), 53 DMI_MATCH(DMI_PRODUCT_NAME, "Terrador"), 54 }, 55 .driver_data = "sof-tgl-rt5682-ssp0-max98373-ssp2.tplg", 56 }, 57 {} 58 }; 59 60 static const struct dmi_system_id community_key_platforms[] = { 61 { 62 .ident = "Up Squared", 63 .matches = { 64 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 65 DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), 66 } 67 }, 68 { 69 .ident = "Google Chromebooks", 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 72 } 73 }, 74 {}, 75 }; 76 77 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 78 static const struct sof_dev_desc bxt_desc = { 79 .machines = snd_soc_acpi_intel_bxt_machines, 80 .resindex_lpe_base = 0, 81 .resindex_pcicfg_base = -1, 82 .resindex_imr_base = -1, 83 .irqindex_host_ipc = -1, 84 .resindex_dma_base = -1, 85 .chip_info = &apl_chip_info, 86 .default_fw_path = "intel/sof", 87 .default_tplg_path = "intel/sof-tplg", 88 .default_fw_filename = "sof-apl.ri", 89 .nocodec_tplg_filename = "sof-apl-nocodec.tplg", 90 .ops = &sof_apl_ops, 91 }; 92 #endif 93 94 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 95 static const struct sof_dev_desc glk_desc = { 96 .machines = snd_soc_acpi_intel_glk_machines, 97 .resindex_lpe_base = 0, 98 .resindex_pcicfg_base = -1, 99 .resindex_imr_base = -1, 100 .irqindex_host_ipc = -1, 101 .resindex_dma_base = -1, 102 .chip_info = &apl_chip_info, 103 .default_fw_path = "intel/sof", 104 .default_tplg_path = "intel/sof-tplg", 105 .default_fw_filename = "sof-glk.ri", 106 .nocodec_tplg_filename = "sof-glk-nocodec.tplg", 107 .ops = &sof_apl_ops, 108 }; 109 #endif 110 111 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 112 static struct snd_soc_acpi_mach sof_tng_machines[] = { 113 { 114 .id = "INT343A", 115 .drv_name = "edison", 116 .sof_fw_filename = "sof-byt.ri", 117 .sof_tplg_filename = "sof-byt.tplg", 118 }, 119 {} 120 }; 121 122 static const struct sof_dev_desc tng_desc = { 123 .machines = sof_tng_machines, 124 .resindex_lpe_base = 3, /* IRAM, but subtract IRAM offset */ 125 .resindex_pcicfg_base = -1, 126 .resindex_imr_base = 0, 127 .irqindex_host_ipc = -1, 128 .resindex_dma_base = -1, 129 .chip_info = &tng_chip_info, 130 .default_fw_path = "intel/sof", 131 .default_tplg_path = "intel/sof-tplg", 132 .default_fw_filename = "sof-byt.ri", 133 .nocodec_tplg_filename = "sof-byt.tplg", 134 .ops = &sof_tng_ops, 135 }; 136 #endif 137 138 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 139 static const struct sof_dev_desc cnl_desc = { 140 .machines = snd_soc_acpi_intel_cnl_machines, 141 .alt_machines = snd_soc_acpi_intel_cnl_sdw_machines, 142 .resindex_lpe_base = 0, 143 .resindex_pcicfg_base = -1, 144 .resindex_imr_base = -1, 145 .irqindex_host_ipc = -1, 146 .resindex_dma_base = -1, 147 .chip_info = &cnl_chip_info, 148 .default_fw_path = "intel/sof", 149 .default_tplg_path = "intel/sof-tplg", 150 .default_fw_filename = "sof-cnl.ri", 151 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 152 .ops = &sof_cnl_ops, 153 }; 154 #endif 155 156 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 157 static const struct sof_dev_desc cfl_desc = { 158 .machines = snd_soc_acpi_intel_cfl_machines, 159 .alt_machines = snd_soc_acpi_intel_cfl_sdw_machines, 160 .resindex_lpe_base = 0, 161 .resindex_pcicfg_base = -1, 162 .resindex_imr_base = -1, 163 .irqindex_host_ipc = -1, 164 .resindex_dma_base = -1, 165 .chip_info = &cnl_chip_info, 166 .default_fw_path = "intel/sof", 167 .default_tplg_path = "intel/sof-tplg", 168 .default_fw_filename = "sof-cfl.ri", 169 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 170 .ops = &sof_cnl_ops, 171 }; 172 #endif 173 174 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 175 static const struct sof_dev_desc cml_desc = { 176 .machines = snd_soc_acpi_intel_cml_machines, 177 .alt_machines = snd_soc_acpi_intel_cml_sdw_machines, 178 .resindex_lpe_base = 0, 179 .resindex_pcicfg_base = -1, 180 .resindex_imr_base = -1, 181 .irqindex_host_ipc = -1, 182 .resindex_dma_base = -1, 183 .chip_info = &cnl_chip_info, 184 .default_fw_path = "intel/sof", 185 .default_tplg_path = "intel/sof-tplg", 186 .default_fw_filename = "sof-cml.ri", 187 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 188 .ops = &sof_cnl_ops, 189 }; 190 #endif 191 192 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 193 static const struct sof_dev_desc icl_desc = { 194 .machines = snd_soc_acpi_intel_icl_machines, 195 .alt_machines = snd_soc_acpi_intel_icl_sdw_machines, 196 .resindex_lpe_base = 0, 197 .resindex_pcicfg_base = -1, 198 .resindex_imr_base = -1, 199 .irqindex_host_ipc = -1, 200 .resindex_dma_base = -1, 201 .chip_info = &icl_chip_info, 202 .default_fw_path = "intel/sof", 203 .default_tplg_path = "intel/sof-tplg", 204 .default_fw_filename = "sof-icl.ri", 205 .nocodec_tplg_filename = "sof-icl-nocodec.tplg", 206 .ops = &sof_cnl_ops, 207 }; 208 #endif 209 210 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 211 static const struct sof_dev_desc tgl_desc = { 212 .machines = snd_soc_acpi_intel_tgl_machines, 213 .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, 214 .resindex_lpe_base = 0, 215 .resindex_pcicfg_base = -1, 216 .resindex_imr_base = -1, 217 .irqindex_host_ipc = -1, 218 .resindex_dma_base = -1, 219 .chip_info = &tgl_chip_info, 220 .default_fw_path = "intel/sof", 221 .default_tplg_path = "intel/sof-tplg", 222 .default_fw_filename = "sof-tgl.ri", 223 .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", 224 .ops = &sof_tgl_ops, 225 }; 226 #endif 227 228 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 229 static const struct sof_dev_desc ehl_desc = { 230 .machines = snd_soc_acpi_intel_ehl_machines, 231 .resindex_lpe_base = 0, 232 .resindex_pcicfg_base = -1, 233 .resindex_imr_base = -1, 234 .irqindex_host_ipc = -1, 235 .resindex_dma_base = -1, 236 .chip_info = &ehl_chip_info, 237 .default_fw_path = "intel/sof", 238 .default_tplg_path = "intel/sof-tplg", 239 .default_fw_filename = "sof-ehl.ri", 240 .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", 241 .ops = &sof_cnl_ops, 242 }; 243 #endif 244 245 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 246 static const struct sof_dev_desc jsl_desc = { 247 .machines = snd_soc_acpi_intel_jsl_machines, 248 .resindex_lpe_base = 0, 249 .resindex_pcicfg_base = -1, 250 .resindex_imr_base = -1, 251 .irqindex_host_ipc = -1, 252 .resindex_dma_base = -1, 253 .chip_info = &jsl_chip_info, 254 .default_fw_path = "intel/sof", 255 .default_tplg_path = "intel/sof-tplg", 256 .default_fw_filename = "sof-jsl.ri", 257 .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", 258 .ops = &sof_cnl_ops, 259 }; 260 #endif 261 262 static const struct dev_pm_ops sof_pci_pm = { 263 .prepare = snd_sof_prepare, 264 .complete = snd_sof_complete, 265 SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) 266 SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, 267 snd_sof_runtime_idle) 268 }; 269 270 static void sof_pci_probe_complete(struct device *dev) 271 { 272 dev_dbg(dev, "Completing SOF PCI probe"); 273 274 if (sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME) 275 return; 276 277 /* allow runtime_pm */ 278 pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); 279 pm_runtime_use_autosuspend(dev); 280 281 /* 282 * runtime pm for pci device is "forbidden" by default. 283 * so call pm_runtime_allow() to enable it. 284 */ 285 pm_runtime_allow(dev); 286 287 /* mark last_busy for pm_runtime to make sure not suspend immediately */ 288 pm_runtime_mark_last_busy(dev); 289 290 /* follow recommendation in pci-driver.c to decrement usage counter */ 291 pm_runtime_put_noidle(dev); 292 } 293 294 static int sof_pci_probe(struct pci_dev *pci, 295 const struct pci_device_id *pci_id) 296 { 297 struct device *dev = &pci->dev; 298 const struct sof_dev_desc *desc = 299 (const struct sof_dev_desc *)pci_id->driver_data; 300 struct snd_sof_pdata *sof_pdata; 301 const struct snd_sof_dsp_ops *ops; 302 int ret; 303 304 ret = snd_intel_dsp_driver_probe(pci); 305 if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) { 306 dev_dbg(&pci->dev, "SOF PCI driver not selected, aborting probe\n"); 307 return -ENODEV; 308 } 309 dev_dbg(&pci->dev, "PCI DSP detected"); 310 311 /* get ops for platform */ 312 ops = desc->ops; 313 if (!ops) { 314 dev_err(dev, "error: no matching PCI descriptor ops\n"); 315 return -ENODEV; 316 } 317 318 sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); 319 if (!sof_pdata) 320 return -ENOMEM; 321 322 ret = pcim_enable_device(pci); 323 if (ret < 0) 324 return ret; 325 326 ret = pci_request_regions(pci, "Audio DSP"); 327 if (ret < 0) 328 return ret; 329 330 sof_pdata->name = pci_name(pci); 331 sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; 332 sof_pdata->dev = dev; 333 sof_pdata->fw_filename = desc->default_fw_filename; 334 335 /* 336 * for platforms using the SOF community key, change the 337 * default path automatically to pick the right files from the 338 * linux-firmware tree. This can be overridden with the 339 * fw_path kernel parameter, e.g. for developers. 340 */ 341 342 /* alternate fw and tplg filenames ? */ 343 if (fw_path) { 344 sof_pdata->fw_filename_prefix = fw_path; 345 346 dev_dbg(dev, 347 "Module parameter used, changed fw path to %s\n", 348 sof_pdata->fw_filename_prefix); 349 350 } else if (dmi_check_system(community_key_platforms)) { 351 sof_pdata->fw_filename_prefix = 352 devm_kasprintf(dev, GFP_KERNEL, "%s/%s", 353 sof_pdata->desc->default_fw_path, 354 "community"); 355 356 dev_dbg(dev, 357 "Platform uses community key, changed fw path to %s\n", 358 sof_pdata->fw_filename_prefix); 359 } else { 360 sof_pdata->fw_filename_prefix = 361 sof_pdata->desc->default_fw_path; 362 } 363 364 if (tplg_path) 365 sof_pdata->tplg_filename_prefix = tplg_path; 366 else 367 sof_pdata->tplg_filename_prefix = 368 sof_pdata->desc->default_tplg_path; 369 370 dmi_check_system(sof_tplg_table); 371 if (sof_override_tplg_name) 372 sof_pdata->tplg_filename = sof_override_tplg_name; 373 374 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 375 /* set callback to enable runtime_pm */ 376 sof_pdata->sof_probe_complete = sof_pci_probe_complete; 377 #endif 378 /* call sof helper for DSP hardware probe */ 379 ret = snd_sof_device_probe(dev, sof_pdata); 380 if (ret) { 381 dev_err(dev, "error: failed to probe DSP hardware!\n"); 382 goto release_regions; 383 } 384 385 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 386 sof_pci_probe_complete(dev); 387 #endif 388 389 return ret; 390 391 release_regions: 392 pci_release_regions(pci); 393 394 return ret; 395 } 396 397 static void sof_pci_remove(struct pci_dev *pci) 398 { 399 /* call sof helper for DSP hardware remove */ 400 snd_sof_device_remove(&pci->dev); 401 402 /* follow recommendation in pci-driver.c to increment usage counter */ 403 if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) 404 pm_runtime_get_noresume(&pci->dev); 405 406 /* release pci regions and disable device */ 407 pci_release_regions(pci); 408 } 409 410 /* PCI IDs */ 411 static const struct pci_device_id sof_pci_ids[] = { 412 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 413 { PCI_DEVICE(0x8086, 0x119a), 414 .driver_data = (unsigned long)&tng_desc}, 415 #endif 416 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 417 /* BXT-P & Apollolake */ 418 { PCI_DEVICE(0x8086, 0x5a98), 419 .driver_data = (unsigned long)&bxt_desc}, 420 { PCI_DEVICE(0x8086, 0x1a98), 421 .driver_data = (unsigned long)&bxt_desc}, 422 #endif 423 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 424 { PCI_DEVICE(0x8086, 0x3198), 425 .driver_data = (unsigned long)&glk_desc}, 426 #endif 427 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 428 { PCI_DEVICE(0x8086, 0x9dc8), 429 .driver_data = (unsigned long)&cnl_desc}, 430 #endif 431 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 432 { PCI_DEVICE(0x8086, 0xa348), 433 .driver_data = (unsigned long)&cfl_desc}, 434 #endif 435 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 436 { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */ 437 .driver_data = (unsigned long)&icl_desc}, 438 { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */ 439 .driver_data = (unsigned long)&icl_desc}, 440 441 #endif 442 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 443 { PCI_DEVICE(0x8086, 0x38c8), 444 .driver_data = (unsigned long)&jsl_desc}, 445 { PCI_DEVICE(0x8086, 0x4dc8), 446 .driver_data = (unsigned long)&jsl_desc}, 447 #endif 448 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 449 { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */ 450 .driver_data = (unsigned long)&cml_desc}, 451 { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */ 452 .driver_data = (unsigned long)&cml_desc}, 453 { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */ 454 .driver_data = (unsigned long)&cml_desc}, 455 #endif 456 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 457 { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */ 458 .driver_data = (unsigned long)&tgl_desc}, 459 { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */ 460 .driver_data = (unsigned long)&tgl_desc}, 461 462 #endif 463 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 464 { PCI_DEVICE(0x8086, 0x4b55), 465 .driver_data = (unsigned long)&ehl_desc}, 466 { PCI_DEVICE(0x8086, 0x4b58), 467 .driver_data = (unsigned long)&ehl_desc}, 468 #endif 469 { 0, } 470 }; 471 MODULE_DEVICE_TABLE(pci, sof_pci_ids); 472 473 /* pci_driver definition */ 474 static struct pci_driver snd_sof_pci_driver = { 475 .name = "sof-audio-pci", 476 .id_table = sof_pci_ids, 477 .probe = sof_pci_probe, 478 .remove = sof_pci_remove, 479 .driver = { 480 .pm = &sof_pci_pm, 481 }, 482 }; 483 module_pci_driver(snd_sof_pci_driver); 484 485 MODULE_LICENSE("Dual BSD/GPL"); 486 MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD); 487 MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); 488