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_cnl_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_hda_machines, 290 .resindex_lpe_base = 0, 291 .resindex_pcicfg_base = -1, 292 .resindex_imr_base = -1, 293 .irqindex_host_ipc = -1, 294 .resindex_dma_base = -1, 295 .chip_info = &adls_chip_info, 296 .default_fw_path = "intel/sof", 297 .default_tplg_path = "intel/sof-tplg", 298 .default_fw_filename = "sof-adl-s.ri", 299 .nocodec_tplg_filename = "sof-adl-nocodec.tplg", 300 .ops = &sof_tgl_ops, 301 }; 302 #endif 303 304 static const struct dev_pm_ops sof_pci_pm = { 305 .prepare = snd_sof_prepare, 306 .complete = snd_sof_complete, 307 SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) 308 SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, 309 snd_sof_runtime_idle) 310 }; 311 312 static void sof_pci_probe_complete(struct device *dev) 313 { 314 dev_dbg(dev, "Completing SOF PCI probe"); 315 316 if (sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME) 317 return; 318 319 /* allow runtime_pm */ 320 pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); 321 pm_runtime_use_autosuspend(dev); 322 323 /* 324 * runtime pm for pci device is "forbidden" by default. 325 * so call pm_runtime_allow() to enable it. 326 */ 327 pm_runtime_allow(dev); 328 329 /* mark last_busy for pm_runtime to make sure not suspend immediately */ 330 pm_runtime_mark_last_busy(dev); 331 332 /* follow recommendation in pci-driver.c to decrement usage counter */ 333 pm_runtime_put_noidle(dev); 334 } 335 336 static int sof_pci_probe(struct pci_dev *pci, 337 const struct pci_device_id *pci_id) 338 { 339 struct device *dev = &pci->dev; 340 const struct sof_dev_desc *desc = 341 (const struct sof_dev_desc *)pci_id->driver_data; 342 struct snd_sof_pdata *sof_pdata; 343 const struct snd_sof_dsp_ops *ops; 344 int ret; 345 346 ret = snd_intel_dsp_driver_probe(pci); 347 if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) { 348 dev_dbg(&pci->dev, "SOF PCI driver not selected, aborting probe\n"); 349 return -ENODEV; 350 } 351 dev_dbg(&pci->dev, "PCI DSP detected"); 352 353 /* get ops for platform */ 354 ops = desc->ops; 355 if (!ops) { 356 dev_err(dev, "error: no matching PCI descriptor ops\n"); 357 return -ENODEV; 358 } 359 360 sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); 361 if (!sof_pdata) 362 return -ENOMEM; 363 364 ret = pcim_enable_device(pci); 365 if (ret < 0) 366 return ret; 367 368 ret = pci_request_regions(pci, "Audio DSP"); 369 if (ret < 0) 370 return ret; 371 372 sof_pdata->name = pci_name(pci); 373 sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; 374 sof_pdata->dev = dev; 375 sof_pdata->fw_filename = desc->default_fw_filename; 376 377 /* 378 * for platforms using the SOF community key, change the 379 * default path automatically to pick the right files from the 380 * linux-firmware tree. This can be overridden with the 381 * fw_path kernel parameter, e.g. for developers. 382 */ 383 384 /* alternate fw and tplg filenames ? */ 385 if (fw_path) { 386 sof_pdata->fw_filename_prefix = fw_path; 387 388 dev_dbg(dev, 389 "Module parameter used, changed fw path to %s\n", 390 sof_pdata->fw_filename_prefix); 391 392 } else if (dmi_check_system(community_key_platforms)) { 393 sof_pdata->fw_filename_prefix = 394 devm_kasprintf(dev, GFP_KERNEL, "%s/%s", 395 sof_pdata->desc->default_fw_path, 396 "community"); 397 398 dev_dbg(dev, 399 "Platform uses community key, changed fw path to %s\n", 400 sof_pdata->fw_filename_prefix); 401 } else { 402 sof_pdata->fw_filename_prefix = 403 sof_pdata->desc->default_fw_path; 404 } 405 406 if (tplg_path) 407 sof_pdata->tplg_filename_prefix = tplg_path; 408 else 409 sof_pdata->tplg_filename_prefix = 410 sof_pdata->desc->default_tplg_path; 411 412 dmi_check_system(sof_tplg_table); 413 if (sof_override_tplg_name) 414 sof_pdata->tplg_filename = sof_override_tplg_name; 415 416 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 417 /* set callback to enable runtime_pm */ 418 sof_pdata->sof_probe_complete = sof_pci_probe_complete; 419 #endif 420 /* call sof helper for DSP hardware probe */ 421 ret = snd_sof_device_probe(dev, sof_pdata); 422 if (ret) { 423 dev_err(dev, "error: failed to probe DSP hardware!\n"); 424 goto release_regions; 425 } 426 427 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 428 sof_pci_probe_complete(dev); 429 #endif 430 431 return ret; 432 433 release_regions: 434 pci_release_regions(pci); 435 436 return ret; 437 } 438 439 static void sof_pci_remove(struct pci_dev *pci) 440 { 441 /* call sof helper for DSP hardware remove */ 442 snd_sof_device_remove(&pci->dev); 443 444 /* follow recommendation in pci-driver.c to increment usage counter */ 445 if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) 446 pm_runtime_get_noresume(&pci->dev); 447 448 /* release pci regions and disable device */ 449 pci_release_regions(pci); 450 } 451 452 /* PCI IDs */ 453 static const struct pci_device_id sof_pci_ids[] = { 454 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 455 { PCI_DEVICE(0x8086, 0x119a), 456 .driver_data = (unsigned long)&tng_desc}, 457 #endif 458 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 459 /* BXT-P & Apollolake */ 460 { PCI_DEVICE(0x8086, 0x5a98), 461 .driver_data = (unsigned long)&bxt_desc}, 462 { PCI_DEVICE(0x8086, 0x1a98), 463 .driver_data = (unsigned long)&bxt_desc}, 464 #endif 465 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 466 { PCI_DEVICE(0x8086, 0x3198), 467 .driver_data = (unsigned long)&glk_desc}, 468 #endif 469 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 470 { PCI_DEVICE(0x8086, 0x9dc8), 471 .driver_data = (unsigned long)&cnl_desc}, 472 #endif 473 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 474 { PCI_DEVICE(0x8086, 0xa348), 475 .driver_data = (unsigned long)&cfl_desc}, 476 #endif 477 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 478 { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */ 479 .driver_data = (unsigned long)&icl_desc}, 480 { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */ 481 .driver_data = (unsigned long)&icl_desc}, 482 483 #endif 484 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 485 { PCI_DEVICE(0x8086, 0x38c8), 486 .driver_data = (unsigned long)&jsl_desc}, 487 { PCI_DEVICE(0x8086, 0x4dc8), 488 .driver_data = (unsigned long)&jsl_desc}, 489 #endif 490 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 491 { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */ 492 .driver_data = (unsigned long)&cml_desc}, 493 { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */ 494 .driver_data = (unsigned long)&cml_desc}, 495 { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */ 496 .driver_data = (unsigned long)&cml_desc}, 497 #endif 498 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 499 { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */ 500 .driver_data = (unsigned long)&tgl_desc}, 501 { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */ 502 .driver_data = (unsigned long)&tglh_desc}, 503 504 #endif 505 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 506 { PCI_DEVICE(0x8086, 0x4b55), 507 .driver_data = (unsigned long)&ehl_desc}, 508 { PCI_DEVICE(0x8086, 0x4b58), 509 .driver_data = (unsigned long)&ehl_desc}, 510 #endif 511 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 512 { PCI_DEVICE(0x8086, 0x7ad0), 513 .driver_data = (unsigned long)&adls_desc}, 514 #endif 515 { 0, } 516 }; 517 MODULE_DEVICE_TABLE(pci, sof_pci_ids); 518 519 /* pci_driver definition */ 520 static struct pci_driver snd_sof_pci_driver = { 521 .name = "sof-audio-pci", 522 .id_table = sof_pci_ids, 523 .probe = sof_pci_probe, 524 .remove = sof_pci_remove, 525 .driver = { 526 .pm = &sof_pci_pm, 527 }, 528 }; 529 module_pci_driver(snd_sof_pci_driver); 530 531 MODULE_LICENSE("Dual BSD/GPL"); 532 MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD); 533 MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); 534