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_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"), 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 = "Up Extreme", 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 72 DMI_MATCH(DMI_BOARD_NAME, "UP-WHL01"), 73 } 74 }, 75 { 76 .ident = "Google Chromebooks", 77 .matches = { 78 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 79 } 80 }, 81 {}, 82 }; 83 84 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 85 static const struct sof_dev_desc bxt_desc = { 86 .machines = snd_soc_acpi_intel_bxt_machines, 87 .use_acpi_target_states = true, 88 .resindex_lpe_base = 0, 89 .resindex_pcicfg_base = -1, 90 .resindex_imr_base = -1, 91 .irqindex_host_ipc = -1, 92 .resindex_dma_base = -1, 93 .chip_info = &apl_chip_info, 94 .default_fw_path = "intel/sof", 95 .default_tplg_path = "intel/sof-tplg", 96 .default_fw_filename = "sof-apl.ri", 97 .nocodec_tplg_filename = "sof-apl-nocodec.tplg", 98 .ops = &sof_apl_ops, 99 }; 100 #endif 101 102 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 103 static const struct sof_dev_desc glk_desc = { 104 .machines = snd_soc_acpi_intel_glk_machines, 105 .use_acpi_target_states = true, 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 = &apl_chip_info, 112 .default_fw_path = "intel/sof", 113 .default_tplg_path = "intel/sof-tplg", 114 .default_fw_filename = "sof-glk.ri", 115 .nocodec_tplg_filename = "sof-glk-nocodec.tplg", 116 .ops = &sof_apl_ops, 117 }; 118 #endif 119 120 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 121 static struct snd_soc_acpi_mach sof_tng_machines[] = { 122 { 123 .id = "INT343A", 124 .drv_name = "edison", 125 .sof_fw_filename = "sof-byt.ri", 126 .sof_tplg_filename = "sof-byt.tplg", 127 }, 128 {} 129 }; 130 131 static const struct sof_dev_desc tng_desc = { 132 .machines = sof_tng_machines, 133 .resindex_lpe_base = 3, /* IRAM, but subtract IRAM offset */ 134 .resindex_pcicfg_base = -1, 135 .resindex_imr_base = 0, 136 .irqindex_host_ipc = -1, 137 .resindex_dma_base = -1, 138 .chip_info = &tng_chip_info, 139 .default_fw_path = "intel/sof", 140 .default_tplg_path = "intel/sof-tplg", 141 .default_fw_filename = "sof-byt.ri", 142 .nocodec_tplg_filename = "sof-byt.tplg", 143 .ops = &sof_tng_ops, 144 }; 145 #endif 146 147 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 148 static const struct sof_dev_desc cnl_desc = { 149 .machines = snd_soc_acpi_intel_cnl_machines, 150 .alt_machines = snd_soc_acpi_intel_cnl_sdw_machines, 151 .use_acpi_target_states = true, 152 .resindex_lpe_base = 0, 153 .resindex_pcicfg_base = -1, 154 .resindex_imr_base = -1, 155 .irqindex_host_ipc = -1, 156 .resindex_dma_base = -1, 157 .chip_info = &cnl_chip_info, 158 .default_fw_path = "intel/sof", 159 .default_tplg_path = "intel/sof-tplg", 160 .default_fw_filename = "sof-cnl.ri", 161 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 162 .ops = &sof_cnl_ops, 163 }; 164 #endif 165 166 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 167 static const struct sof_dev_desc cfl_desc = { 168 .machines = snd_soc_acpi_intel_cfl_machines, 169 .alt_machines = snd_soc_acpi_intel_cfl_sdw_machines, 170 .use_acpi_target_states = true, 171 .resindex_lpe_base = 0, 172 .resindex_pcicfg_base = -1, 173 .resindex_imr_base = -1, 174 .irqindex_host_ipc = -1, 175 .resindex_dma_base = -1, 176 .chip_info = &cnl_chip_info, 177 .default_fw_path = "intel/sof", 178 .default_tplg_path = "intel/sof-tplg", 179 .default_fw_filename = "sof-cfl.ri", 180 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 181 .ops = &sof_cnl_ops, 182 }; 183 #endif 184 185 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 186 static const struct sof_dev_desc cml_desc = { 187 .machines = snd_soc_acpi_intel_cml_machines, 188 .alt_machines = snd_soc_acpi_intel_cml_sdw_machines, 189 .use_acpi_target_states = true, 190 .resindex_lpe_base = 0, 191 .resindex_pcicfg_base = -1, 192 .resindex_imr_base = -1, 193 .irqindex_host_ipc = -1, 194 .resindex_dma_base = -1, 195 .chip_info = &cnl_chip_info, 196 .default_fw_path = "intel/sof", 197 .default_tplg_path = "intel/sof-tplg", 198 .default_fw_filename = "sof-cml.ri", 199 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 200 .ops = &sof_cnl_ops, 201 }; 202 #endif 203 204 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 205 static const struct sof_dev_desc icl_desc = { 206 .machines = snd_soc_acpi_intel_icl_machines, 207 .alt_machines = snd_soc_acpi_intel_icl_sdw_machines, 208 .use_acpi_target_states = true, 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 = &icl_chip_info, 215 .default_fw_path = "intel/sof", 216 .default_tplg_path = "intel/sof-tplg", 217 .default_fw_filename = "sof-icl.ri", 218 .nocodec_tplg_filename = "sof-icl-nocodec.tplg", 219 .ops = &sof_icl_ops, 220 }; 221 #endif 222 223 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) || IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 224 static const struct sof_dev_desc tgl_desc = { 225 .machines = snd_soc_acpi_intel_tgl_machines, 226 .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, 227 .use_acpi_target_states = true, 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 = &tgl_chip_info, 234 .default_fw_path = "intel/sof", 235 .default_tplg_path = "intel/sof-tplg", 236 .default_fw_filename = "sof-tgl.ri", 237 .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", 238 .ops = &sof_tgl_ops, 239 }; 240 #endif 241 242 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 243 static const struct sof_dev_desc tglh_desc = { 244 .machines = snd_soc_acpi_intel_tgl_machines, 245 .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, 246 .resindex_lpe_base = 0, 247 .resindex_pcicfg_base = -1, 248 .resindex_imr_base = -1, 249 .irqindex_host_ipc = -1, 250 .resindex_dma_base = -1, 251 .chip_info = &tglh_chip_info, 252 .default_fw_path = "intel/sof", 253 .default_tplg_path = "intel/sof-tplg", 254 .default_fw_filename = "sof-tgl-h.ri", 255 .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", 256 .ops = &sof_tgl_ops, 257 }; 258 #endif 259 260 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 261 static const struct sof_dev_desc ehl_desc = { 262 .machines = snd_soc_acpi_intel_ehl_machines, 263 .use_acpi_target_states = true, 264 .resindex_lpe_base = 0, 265 .resindex_pcicfg_base = -1, 266 .resindex_imr_base = -1, 267 .irqindex_host_ipc = -1, 268 .resindex_dma_base = -1, 269 .chip_info = &ehl_chip_info, 270 .default_fw_path = "intel/sof", 271 .default_tplg_path = "intel/sof-tplg", 272 .default_fw_filename = "sof-ehl.ri", 273 .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", 274 .ops = &sof_cnl_ops, 275 }; 276 #endif 277 278 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 279 static const struct sof_dev_desc jsl_desc = { 280 .machines = snd_soc_acpi_intel_jsl_machines, 281 .use_acpi_target_states = true, 282 .resindex_lpe_base = 0, 283 .resindex_pcicfg_base = -1, 284 .resindex_imr_base = -1, 285 .irqindex_host_ipc = -1, 286 .resindex_dma_base = -1, 287 .chip_info = &jsl_chip_info, 288 .default_fw_path = "intel/sof", 289 .default_tplg_path = "intel/sof-tplg", 290 .default_fw_filename = "sof-jsl.ri", 291 .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", 292 .ops = &sof_cnl_ops, 293 }; 294 #endif 295 296 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 297 static const struct sof_dev_desc adls_desc = { 298 .machines = snd_soc_acpi_intel_adl_machines, 299 .alt_machines = snd_soc_acpi_intel_adl_sdw_machines, 300 .resindex_lpe_base = 0, 301 .resindex_pcicfg_base = -1, 302 .resindex_imr_base = -1, 303 .irqindex_host_ipc = -1, 304 .resindex_dma_base = -1, 305 .chip_info = &adls_chip_info, 306 .default_fw_path = "intel/sof", 307 .default_tplg_path = "intel/sof-tplg", 308 .default_fw_filename = "sof-adl-s.ri", 309 .nocodec_tplg_filename = "sof-adl-nocodec.tplg", 310 .ops = &sof_tgl_ops, 311 }; 312 #endif 313 314 static const struct dev_pm_ops sof_pci_pm = { 315 .prepare = snd_sof_prepare, 316 .complete = snd_sof_complete, 317 SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) 318 SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, 319 snd_sof_runtime_idle) 320 }; 321 322 static void sof_pci_probe_complete(struct device *dev) 323 { 324 dev_dbg(dev, "Completing SOF PCI probe"); 325 326 if (sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME) 327 return; 328 329 /* allow runtime_pm */ 330 pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); 331 pm_runtime_use_autosuspend(dev); 332 333 /* 334 * runtime pm for pci device is "forbidden" by default. 335 * so call pm_runtime_allow() to enable it. 336 */ 337 pm_runtime_allow(dev); 338 339 /* mark last_busy for pm_runtime to make sure not suspend immediately */ 340 pm_runtime_mark_last_busy(dev); 341 342 /* follow recommendation in pci-driver.c to decrement usage counter */ 343 pm_runtime_put_noidle(dev); 344 } 345 346 static int sof_pci_probe(struct pci_dev *pci, 347 const struct pci_device_id *pci_id) 348 { 349 struct device *dev = &pci->dev; 350 const struct sof_dev_desc *desc = 351 (const struct sof_dev_desc *)pci_id->driver_data; 352 struct snd_sof_pdata *sof_pdata; 353 const struct snd_sof_dsp_ops *ops; 354 int ret; 355 356 if (IS_REACHABLE(CONFIG_SND_INTEL_DSP_CONFIG)) { 357 ret = snd_intel_dsp_driver_probe(pci); 358 if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) { 359 dev_dbg(&pci->dev, "SOF PCI driver not selected, aborting probe\n"); 360 return -ENODEV; 361 } 362 } 363 dev_dbg(&pci->dev, "PCI DSP detected"); 364 365 /* get ops for platform */ 366 ops = desc->ops; 367 if (!ops) { 368 dev_err(dev, "error: no matching PCI descriptor ops\n"); 369 return -ENODEV; 370 } 371 372 sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); 373 if (!sof_pdata) 374 return -ENOMEM; 375 376 ret = pcim_enable_device(pci); 377 if (ret < 0) 378 return ret; 379 380 ret = pci_request_regions(pci, "Audio DSP"); 381 if (ret < 0) 382 return ret; 383 384 sof_pdata->name = pci_name(pci); 385 sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; 386 sof_pdata->dev = dev; 387 sof_pdata->fw_filename = desc->default_fw_filename; 388 389 /* 390 * for platforms using the SOF community key, change the 391 * default path automatically to pick the right files from the 392 * linux-firmware tree. This can be overridden with the 393 * fw_path kernel parameter, e.g. for developers. 394 */ 395 396 /* alternate fw and tplg filenames ? */ 397 if (fw_path) { 398 sof_pdata->fw_filename_prefix = fw_path; 399 400 dev_dbg(dev, 401 "Module parameter used, changed fw path to %s\n", 402 sof_pdata->fw_filename_prefix); 403 404 } else if (dmi_check_system(community_key_platforms)) { 405 sof_pdata->fw_filename_prefix = 406 devm_kasprintf(dev, GFP_KERNEL, "%s/%s", 407 sof_pdata->desc->default_fw_path, 408 "community"); 409 410 dev_dbg(dev, 411 "Platform uses community key, changed fw path to %s\n", 412 sof_pdata->fw_filename_prefix); 413 } else { 414 sof_pdata->fw_filename_prefix = 415 sof_pdata->desc->default_fw_path; 416 } 417 418 if (tplg_path) 419 sof_pdata->tplg_filename_prefix = tplg_path; 420 else 421 sof_pdata->tplg_filename_prefix = 422 sof_pdata->desc->default_tplg_path; 423 424 dmi_check_system(sof_tplg_table); 425 if (sof_override_tplg_name) 426 sof_pdata->tplg_filename = sof_override_tplg_name; 427 428 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 429 /* set callback to enable runtime_pm */ 430 sof_pdata->sof_probe_complete = sof_pci_probe_complete; 431 #endif 432 /* call sof helper for DSP hardware probe */ 433 ret = snd_sof_device_probe(dev, sof_pdata); 434 if (ret) { 435 dev_err(dev, "error: failed to probe DSP hardware!\n"); 436 goto release_regions; 437 } 438 439 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 440 sof_pci_probe_complete(dev); 441 #endif 442 443 return ret; 444 445 release_regions: 446 pci_release_regions(pci); 447 448 return ret; 449 } 450 451 static void sof_pci_remove(struct pci_dev *pci) 452 { 453 /* call sof helper for DSP hardware remove */ 454 snd_sof_device_remove(&pci->dev); 455 456 /* follow recommendation in pci-driver.c to increment usage counter */ 457 if (snd_sof_device_probe_completed(&pci->dev) && 458 !(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) 459 pm_runtime_get_noresume(&pci->dev); 460 461 /* release pci regions and disable device */ 462 pci_release_regions(pci); 463 } 464 465 static void sof_pci_shutdown(struct pci_dev *pci) 466 { 467 snd_sof_device_shutdown(&pci->dev); 468 } 469 470 /* PCI IDs */ 471 static const struct pci_device_id sof_pci_ids[] = { 472 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 473 { PCI_DEVICE(0x8086, 0x119a), 474 .driver_data = (unsigned long)&tng_desc}, 475 #endif 476 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 477 /* BXT-P & Apollolake */ 478 { PCI_DEVICE(0x8086, 0x5a98), 479 .driver_data = (unsigned long)&bxt_desc}, 480 { PCI_DEVICE(0x8086, 0x1a98), 481 .driver_data = (unsigned long)&bxt_desc}, 482 #endif 483 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 484 { PCI_DEVICE(0x8086, 0x3198), 485 .driver_data = (unsigned long)&glk_desc}, 486 #endif 487 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 488 { PCI_DEVICE(0x8086, 0x9dc8), 489 .driver_data = (unsigned long)&cnl_desc}, 490 #endif 491 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 492 { PCI_DEVICE(0x8086, 0xa348), 493 .driver_data = (unsigned long)&cfl_desc}, 494 #endif 495 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 496 { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */ 497 .driver_data = (unsigned long)&icl_desc}, 498 { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */ 499 .driver_data = (unsigned long)&icl_desc}, 500 501 #endif 502 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 503 { PCI_DEVICE(0x8086, 0x38c8), 504 .driver_data = (unsigned long)&jsl_desc}, 505 { PCI_DEVICE(0x8086, 0x4dc8), 506 .driver_data = (unsigned long)&jsl_desc}, 507 #endif 508 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 509 { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */ 510 .driver_data = (unsigned long)&cml_desc}, 511 { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */ 512 .driver_data = (unsigned long)&cml_desc}, 513 { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */ 514 .driver_data = (unsigned long)&cml_desc}, 515 #endif 516 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 517 { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */ 518 .driver_data = (unsigned long)&tgl_desc}, 519 { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */ 520 .driver_data = (unsigned long)&tglh_desc}, 521 522 #endif 523 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 524 { PCI_DEVICE(0x8086, 0x4b55), 525 .driver_data = (unsigned long)&ehl_desc}, 526 { PCI_DEVICE(0x8086, 0x4b58), 527 .driver_data = (unsigned long)&ehl_desc}, 528 #endif 529 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 530 { PCI_DEVICE(0x8086, 0x7ad0), 531 .driver_data = (unsigned long)&adls_desc}, 532 { PCI_DEVICE(0x8086, 0x51c8), 533 .driver_data = (unsigned long)&tgl_desc}, 534 #endif 535 { 0, } 536 }; 537 MODULE_DEVICE_TABLE(pci, sof_pci_ids); 538 539 /* pci_driver definition */ 540 static struct pci_driver snd_sof_pci_driver = { 541 .name = "sof-audio-pci", 542 .id_table = sof_pci_ids, 543 .probe = sof_pci_probe, 544 .remove = sof_pci_remove, 545 .shutdown = sof_pci_shutdown, 546 .driver = { 547 .pm = &sof_pci_pm, 548 }, 549 }; 550 module_pci_driver(snd_sof_pci_driver); 551 552 MODULE_LICENSE("Dual BSD/GPL"); 553 MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD); 554 MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); 555