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