root/sound/soc/sof/sof-pci-dev.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sof_pci_probe_complete
  2. sof_pci_probe
  3. sof_pci_remove

   1 // SPDX-License-Identifier: (GPL-2.0 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/module.h>
  13 #include <linux/pci.h>
  14 #include <linux/pm_runtime.h>
  15 #include <sound/soc-acpi.h>
  16 #include <sound/soc-acpi-intel-match.h>
  17 #include <sound/sof.h>
  18 #include "ops.h"
  19 
  20 /* platform specific devices */
  21 #include "intel/shim.h"
  22 #include "intel/hda.h"
  23 
  24 static char *fw_path;
  25 module_param(fw_path, charp, 0444);
  26 MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
  27 
  28 static char *tplg_path;
  29 module_param(tplg_path, charp, 0444);
  30 MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
  31 
  32 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
  33 static const struct sof_dev_desc bxt_desc = {
  34         .machines               = snd_soc_acpi_intel_bxt_machines,
  35         .resindex_lpe_base      = 0,
  36         .resindex_pcicfg_base   = -1,
  37         .resindex_imr_base      = -1,
  38         .irqindex_host_ipc      = -1,
  39         .resindex_dma_base      = -1,
  40         .chip_info = &apl_chip_info,
  41         .default_fw_path = "intel/sof",
  42         .default_tplg_path = "intel/sof-tplg",
  43         .nocodec_fw_filename = "sof-apl.ri",
  44         .nocodec_tplg_filename = "sof-apl-nocodec.tplg",
  45         .ops = &sof_apl_ops,
  46         .arch_ops = &sof_xtensa_arch_ops
  47 };
  48 #endif
  49 
  50 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
  51 static const struct sof_dev_desc glk_desc = {
  52         .machines               = snd_soc_acpi_intel_glk_machines,
  53         .resindex_lpe_base      = 0,
  54         .resindex_pcicfg_base   = -1,
  55         .resindex_imr_base      = -1,
  56         .irqindex_host_ipc      = -1,
  57         .resindex_dma_base      = -1,
  58         .chip_info = &apl_chip_info,
  59         .default_fw_path = "intel/sof",
  60         .default_tplg_path = "intel/sof-tplg",
  61         .nocodec_fw_filename = "sof-glk.ri",
  62         .nocodec_tplg_filename = "sof-glk-nocodec.tplg",
  63         .ops = &sof_apl_ops,
  64         .arch_ops = &sof_xtensa_arch_ops
  65 };
  66 #endif
  67 
  68 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
  69 static struct snd_soc_acpi_mach sof_tng_machines[] = {
  70         {
  71                 .id = "INT343A",
  72                 .drv_name = "edison",
  73                 .sof_fw_filename = "sof-byt.ri",
  74                 .sof_tplg_filename = "sof-byt.tplg",
  75         },
  76         {}
  77 };
  78 
  79 static const struct sof_dev_desc tng_desc = {
  80         .machines               = sof_tng_machines,
  81         .resindex_lpe_base      = 3,    /* IRAM, but subtract IRAM offset */
  82         .resindex_pcicfg_base   = -1,
  83         .resindex_imr_base      = 0,
  84         .irqindex_host_ipc      = -1,
  85         .resindex_dma_base      = -1,
  86         .chip_info = &tng_chip_info,
  87         .default_fw_path = "intel/sof",
  88         .default_tplg_path = "intel/sof-tplg",
  89         .nocodec_fw_filename = "sof-byt.ri",
  90         .nocodec_tplg_filename = "sof-byt.tplg",
  91         .ops = &sof_tng_ops,
  92         .arch_ops = &sof_xtensa_arch_ops
  93 };
  94 #endif
  95 
  96 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
  97 static const struct sof_dev_desc cnl_desc = {
  98         .machines               = snd_soc_acpi_intel_cnl_machines,
  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 = &cnl_chip_info,
 105         .default_fw_path = "intel/sof",
 106         .default_tplg_path = "intel/sof-tplg",
 107         .nocodec_fw_filename = "sof-cnl.ri",
 108         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
 109         .ops = &sof_cnl_ops,
 110         .arch_ops = &sof_xtensa_arch_ops
 111 };
 112 #endif
 113 
 114 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
 115 static const struct sof_dev_desc cfl_desc = {
 116         .machines               = snd_soc_acpi_intel_cnl_machines,
 117         .resindex_lpe_base      = 0,
 118         .resindex_pcicfg_base   = -1,
 119         .resindex_imr_base      = -1,
 120         .irqindex_host_ipc      = -1,
 121         .resindex_dma_base      = -1,
 122         .chip_info = &cnl_chip_info,
 123         .default_fw_path = "intel/sof",
 124         .default_tplg_path = "intel/sof-tplg",
 125         .nocodec_fw_filename = "sof-cnl.ri",
 126         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
 127         .ops = &sof_cnl_ops,
 128         .arch_ops = &sof_xtensa_arch_ops
 129 };
 130 #endif
 131 
 132 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \
 133         IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
 134 
 135 static const struct sof_dev_desc cml_desc = {
 136         .machines               = snd_soc_acpi_intel_cnl_machines,
 137         .resindex_lpe_base      = 0,
 138         .resindex_pcicfg_base   = -1,
 139         .resindex_imr_base      = -1,
 140         .irqindex_host_ipc      = -1,
 141         .resindex_dma_base      = -1,
 142         .chip_info = &cnl_chip_info,
 143         .default_fw_path = "intel/sof",
 144         .default_tplg_path = "intel/sof-tplg",
 145         .nocodec_fw_filename = "sof-cnl.ri",
 146         .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
 147         .ops = &sof_cnl_ops,
 148         .arch_ops = &sof_xtensa_arch_ops
 149 };
 150 #endif
 151 
 152 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
 153 static const struct sof_dev_desc icl_desc = {
 154         .machines               = snd_soc_acpi_intel_icl_machines,
 155         .resindex_lpe_base      = 0,
 156         .resindex_pcicfg_base   = -1,
 157         .resindex_imr_base      = -1,
 158         .irqindex_host_ipc      = -1,
 159         .resindex_dma_base      = -1,
 160         .chip_info = &icl_chip_info,
 161         .default_fw_path = "intel/sof",
 162         .default_tplg_path = "intel/sof-tplg",
 163         .nocodec_fw_filename = "sof-icl.ri",
 164         .nocodec_tplg_filename = "sof-icl-nocodec.tplg",
 165         .ops = &sof_cnl_ops,
 166         .arch_ops = &sof_xtensa_arch_ops
 167 };
 168 #endif
 169 
 170 #if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE)
 171 static const struct sof_dev_desc skl_desc = {
 172         .machines               = snd_soc_acpi_intel_skl_machines,
 173         .resindex_lpe_base      = 0,
 174         .resindex_pcicfg_base   = -1,
 175         .resindex_imr_base      = -1,
 176         .irqindex_host_ipc      = -1,
 177         .resindex_dma_base      = -1,
 178         .chip_info = &skl_chip_info,
 179         .default_fw_path = "intel/sof",
 180         .default_tplg_path = "intel/sof-tplg",
 181         .nocodec_fw_filename = "sof-skl.ri",
 182         .nocodec_tplg_filename = "sof-skl-nocodec.tplg",
 183         .ops = &sof_skl_ops,
 184         .arch_ops = &sof_xtensa_arch_ops
 185 };
 186 #endif
 187 
 188 #if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE)
 189 static const struct sof_dev_desc kbl_desc = {
 190         .machines               = snd_soc_acpi_intel_kbl_machines,
 191         .resindex_lpe_base      = 0,
 192         .resindex_pcicfg_base   = -1,
 193         .resindex_imr_base      = -1,
 194         .irqindex_host_ipc      = -1,
 195         .resindex_dma_base      = -1,
 196         .chip_info = &skl_chip_info,
 197         .default_fw_path = "intel/sof",
 198         .default_tplg_path = "intel/sof-tplg",
 199         .nocodec_fw_filename = "sof-kbl.ri",
 200         .nocodec_tplg_filename = "sof-kbl-nocodec.tplg",
 201         .ops = &sof_skl_ops,
 202         .arch_ops = &sof_xtensa_arch_ops
 203 };
 204 #endif
 205 
 206 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
 207 static const struct sof_dev_desc tgl_desc = {
 208         .machines               = snd_soc_acpi_intel_tgl_machines,
 209         .resindex_lpe_base      = 0,
 210         .resindex_pcicfg_base   = -1,
 211         .resindex_imr_base      = -1,
 212         .irqindex_host_ipc      = -1,
 213         .resindex_dma_base      = -1,
 214         .chip_info = &tgl_chip_info,
 215         .default_fw_path = "intel/sof",
 216         .default_tplg_path = "intel/sof-tplg",
 217         .nocodec_fw_filename = "sof-tgl.ri",
 218         .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
 219         .ops = &sof_cnl_ops,
 220         .arch_ops = &sof_xtensa_arch_ops
 221 };
 222 #endif
 223 
 224 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
 225 static const struct sof_dev_desc ehl_desc = {
 226         .machines               = snd_soc_acpi_intel_ehl_machines,
 227         .resindex_lpe_base      = 0,
 228         .resindex_pcicfg_base   = -1,
 229         .resindex_imr_base      = -1,
 230         .irqindex_host_ipc      = -1,
 231         .resindex_dma_base      = -1,
 232         .chip_info = &ehl_chip_info,
 233         .default_fw_path = "intel/sof",
 234         .default_tplg_path = "intel/sof-tplg",
 235         .nocodec_fw_filename = "sof-ehl.ri",
 236         .nocodec_tplg_filename = "sof-ehl-nocodec.tplg",
 237         .ops = &sof_cnl_ops,
 238         .arch_ops = &sof_xtensa_arch_ops
 239 };
 240 #endif
 241 
 242 static const struct dev_pm_ops sof_pci_pm = {
 243         SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
 244         SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
 245                            snd_sof_runtime_idle)
 246 };
 247 
 248 static void sof_pci_probe_complete(struct device *dev)
 249 {
 250         dev_dbg(dev, "Completing SOF PCI probe");
 251 
 252         /* allow runtime_pm */
 253         pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
 254         pm_runtime_use_autosuspend(dev);
 255 
 256         /*
 257          * runtime pm for pci device is "forbidden" by default.
 258          * so call pm_runtime_allow() to enable it.
 259          */
 260         pm_runtime_allow(dev);
 261 
 262         /* mark last_busy for pm_runtime to make sure not suspend immediately */
 263         pm_runtime_mark_last_busy(dev);
 264 
 265         /* follow recommendation in pci-driver.c to decrement usage counter */
 266         pm_runtime_put_noidle(dev);
 267 }
 268 
 269 static int sof_pci_probe(struct pci_dev *pci,
 270                          const struct pci_device_id *pci_id)
 271 {
 272         struct device *dev = &pci->dev;
 273         const struct sof_dev_desc *desc =
 274                 (const struct sof_dev_desc *)pci_id->driver_data;
 275         struct snd_soc_acpi_mach *mach;
 276         struct snd_sof_pdata *sof_pdata;
 277         const struct snd_sof_dsp_ops *ops;
 278         int ret;
 279 
 280         dev_dbg(&pci->dev, "PCI DSP detected");
 281 
 282         /* get ops for platform */
 283         ops = desc->ops;
 284         if (!ops) {
 285                 dev_err(dev, "error: no matching PCI descriptor ops\n");
 286                 return -ENODEV;
 287         }
 288 
 289         sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
 290         if (!sof_pdata)
 291                 return -ENOMEM;
 292 
 293         ret = pcim_enable_device(pci);
 294         if (ret < 0)
 295                 return ret;
 296 
 297         ret = pci_request_regions(pci, "Audio DSP");
 298         if (ret < 0)
 299                 return ret;
 300 
 301 #if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
 302         /* force nocodec mode */
 303         dev_warn(dev, "Force to use nocodec mode\n");
 304         mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
 305         if (!mach) {
 306                 ret = -ENOMEM;
 307                 goto release_regions;
 308         }
 309         ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
 310         if (ret < 0)
 311                 goto release_regions;
 312 
 313 #else
 314         /* find machine */
 315         mach = snd_soc_acpi_find_machine(desc->machines);
 316         if (!mach) {
 317                 dev_warn(dev, "warning: No matching ASoC machine driver found\n");
 318         } else {
 319                 mach->mach_params.platform = dev_name(dev);
 320                 sof_pdata->fw_filename = mach->sof_fw_filename;
 321                 sof_pdata->tplg_filename = mach->sof_tplg_filename;
 322         }
 323 #endif /* CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE */
 324 
 325         sof_pdata->name = pci_name(pci);
 326         sof_pdata->machine = mach;
 327         sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
 328         sof_pdata->dev = dev;
 329         sof_pdata->platform = dev_name(dev);
 330 
 331         /* alternate fw and tplg filenames ? */
 332         if (fw_path)
 333                 sof_pdata->fw_filename_prefix = fw_path;
 334         else
 335                 sof_pdata->fw_filename_prefix =
 336                         sof_pdata->desc->default_fw_path;
 337 
 338         if (tplg_path)
 339                 sof_pdata->tplg_filename_prefix = tplg_path;
 340         else
 341                 sof_pdata->tplg_filename_prefix =
 342                         sof_pdata->desc->default_tplg_path;
 343 
 344 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
 345         /* set callback to enable runtime_pm */
 346         sof_pdata->sof_probe_complete = sof_pci_probe_complete;
 347 #endif
 348         /* call sof helper for DSP hardware probe */
 349         ret = snd_sof_device_probe(dev, sof_pdata);
 350         if (ret) {
 351                 dev_err(dev, "error: failed to probe DSP hardware!\n");
 352                 goto release_regions;
 353         }
 354 
 355 #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
 356         sof_pci_probe_complete(dev);
 357 #endif
 358 
 359         return ret;
 360 
 361 release_regions:
 362         pci_release_regions(pci);
 363 
 364         return ret;
 365 }
 366 
 367 static void sof_pci_remove(struct pci_dev *pci)
 368 {
 369         /* call sof helper for DSP hardware remove */
 370         snd_sof_device_remove(&pci->dev);
 371 
 372         /* follow recommendation in pci-driver.c to increment usage counter */
 373         pm_runtime_get_noresume(&pci->dev);
 374 
 375         /* release pci regions and disable device */
 376         pci_release_regions(pci);
 377 }
 378 
 379 /* PCI IDs */
 380 static const struct pci_device_id sof_pci_ids[] = {
 381 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
 382         { PCI_DEVICE(0x8086, 0x119a),
 383                 .driver_data = (unsigned long)&tng_desc},
 384 #endif
 385 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
 386         /* BXT-P & Apollolake */
 387         { PCI_DEVICE(0x8086, 0x5a98),
 388                 .driver_data = (unsigned long)&bxt_desc},
 389         { PCI_DEVICE(0x8086, 0x1a98),
 390                 .driver_data = (unsigned long)&bxt_desc},
 391 #endif
 392 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
 393         { PCI_DEVICE(0x8086, 0x3198),
 394                 .driver_data = (unsigned long)&glk_desc},
 395 #endif
 396 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
 397         { PCI_DEVICE(0x8086, 0x9dc8),
 398                 .driver_data = (unsigned long)&cnl_desc},
 399 #endif
 400 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
 401         { PCI_DEVICE(0x8086, 0xa348),
 402                 .driver_data = (unsigned long)&cfl_desc},
 403 #endif
 404 #if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE)
 405         { PCI_DEVICE(0x8086, 0x9d71),
 406                 .driver_data = (unsigned long)&kbl_desc},
 407 #endif
 408 #if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE)
 409         { PCI_DEVICE(0x8086, 0x9d70),
 410                 .driver_data = (unsigned long)&skl_desc},
 411 #endif
 412 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
 413         { PCI_DEVICE(0x8086, 0x34C8),
 414                 .driver_data = (unsigned long)&icl_desc},
 415 #endif
 416 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
 417         { PCI_DEVICE(0x8086, 0x02c8),
 418                 .driver_data = (unsigned long)&cml_desc},
 419 #endif
 420 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
 421         { PCI_DEVICE(0x8086, 0x06c8),
 422                 .driver_data = (unsigned long)&cml_desc},
 423 #endif
 424 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
 425         { PCI_DEVICE(0x8086, 0xa0c8),
 426                 .driver_data = (unsigned long)&tgl_desc},
 427 #endif
 428 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
 429         { PCI_DEVICE(0x8086, 0x4b55),
 430                 .driver_data = (unsigned long)&ehl_desc},
 431 #endif
 432         { 0, }
 433 };
 434 MODULE_DEVICE_TABLE(pci, sof_pci_ids);
 435 
 436 /* pci_driver definition */
 437 static struct pci_driver snd_sof_pci_driver = {
 438         .name = "sof-audio-pci",
 439         .id_table = sof_pci_ids,
 440         .probe = sof_pci_probe,
 441         .remove = sof_pci_remove,
 442         .driver = {
 443                 .pm = &sof_pci_pm,
 444         },
 445 };
 446 module_pci_driver(snd_sof_pci_driver);
 447 
 448 MODULE_LICENSE("Dual BSD/GPL");

/* [<][>][^][v][top][bottom][index][help] */