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