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