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