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