diff options
author | Mark Brown <broonie@kernel.org> | 2023-09-13 21:48:57 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-09-13 21:48:57 +0100 |
commit | bc51fbeea39e34b9a01820fea5b6092fcc5b48f2 (patch) | |
tree | 05511dd8413ff4dcb2e69671f0121379825b9122 | |
parent | 8885ab34201c5c34a82539ba2753e8e743b38f38 (diff) | |
parent | 1a1c3d794ef65ef2978c5e65e1aed3fe6f014e90 (diff) |
ASoC: cs35l56: Use PCI SSID to select specific
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:
The PCI device registers contain a subsystem ID (SSID), that is
separate from the silicon ID. The PCI specification defines it thus:
"They provide a mechanism for board vendors to distiguish their
boards from one another even thought the boards may have the same
PCI controller on them."
This allows the driver for the silicon part to apply board-speficic
settings based on this SSID.
The CS35L56 driver uses this to select the correct firmware file for
the board. The actual ID is part of the PCI register set of the
host audio interface so this set of patches includes extracting the
SSID from the Intel audio controller and passing it to the machine
driver and then to ASoC components. Other PCI audio controllers
will have the same SSID registers, so can use the same mechanism to
pass the SSID.
-rw-r--r-- | include/sound/soc-acpi.h | 7 | ||||
-rw-r--r-- | include/sound/soc-card.h | 37 | ||||
-rw-r--r-- | include/sound/soc.h | 11 | ||||
-rw-r--r-- | include/sound/sof.h | 8 | ||||
-rw-r--r-- | sound/soc/codecs/cs35l56.c | 11 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_sdw.c | 6 | ||||
-rw-r--r-- | sound/soc/sof/sof-audio.c | 7 | ||||
-rw-r--r-- | sound/soc/sof/sof-pci-dev.c | 8 |
8 files changed, 95 insertions, 0 deletions
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 6d31d535e8f6..23d6d6bfb073 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -68,6 +68,10 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @i2s_link_mask: I2S/TDM links enabled on the board * @num_dai_drivers: number of elements in @dai_drivers * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode + * @subsystem_vendor: optional PCI SSID vendor value + * @subsystem_device: optional PCI SSID device value + * @subsystem_id_set: true if a value has been written to + * subsystem_vendor and subsystem_device. */ struct snd_soc_acpi_mach_params { u32 acpi_ipc_irq_index; @@ -80,6 +84,9 @@ struct snd_soc_acpi_mach_params { u32 i2s_link_mask; u32 num_dai_drivers; struct snd_soc_dai_driver *dai_drivers; + unsigned short subsystem_vendor; + unsigned short subsystem_device; + bool subsystem_id_set; }; /** diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index fc94dfb0021f..e8ff2e089cd0 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -59,6 +59,43 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card, void snd_soc_card_remove_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +#ifdef CONFIG_PCI +static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card, + unsigned short vendor, + unsigned short device) +{ + card->pci_subsystem_vendor = vendor; + card->pci_subsystem_device = device; + card->pci_subsystem_set = true; +} + +static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card, + unsigned short *vendor, + unsigned short *device) +{ + if (!card->pci_subsystem_set) + return -ENOENT; + + *vendor = card->pci_subsystem_vendor; + *device = card->pci_subsystem_device; + + return 0; +} +#else /* !CONFIG_PCI */ +static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card, + unsigned short vendor, + unsigned short device) +{ +} + +static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card, + unsigned short *vendor, + unsigned short *device) +{ + return -ENOENT; +} +#endif /* CONFIG_PCI */ + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/include/sound/soc.h b/include/sound/soc.h index 509386ff5212..81ed08c5c67d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -929,6 +929,17 @@ struct snd_soc_card { #ifdef CONFIG_DMI char dmi_longname[80]; #endif /* CONFIG_DMI */ + +#ifdef CONFIG_PCI + /* + * PCI does not define 0 as invalid, so pci_subsystem_set indicates + * whether a value has been written to these fields. + */ + unsigned short pci_subsystem_vendor; + unsigned short pci_subsystem_device; + bool pci_subsystem_set; +#endif /* CONFIG_PCI */ + char topology_shortname[32]; struct device *dev; diff --git a/include/sound/sof.h b/include/sound/sof.h index d3c41f87ac31..51294f2ba302 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -64,6 +64,14 @@ struct snd_sof_pdata { const char *name; const char *platform; + /* + * PCI SSID. As PCI does not define 0 as invalid, the subsystem_id_set + * flag indicates that a value has been written to these members. + */ + unsigned short subsystem_vendor; + unsigned short subsystem_device; + bool subsystem_id_set; + struct device *dev; /* diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index f2e7c6d0be46..e6e366333a47 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -772,9 +772,20 @@ static int cs35l56_component_probe(struct snd_soc_component *component) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); struct dentry *debugfs_root = component->debugfs_root; + unsigned short vendor, device; BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); + if (!cs35l56->dsp.system_name && + (snd_soc_card_get_pci_ssid(component->card, &vendor, &device) == 0)) { + cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev, + GFP_KERNEL, + "%04x%04x", + vendor, device); + if (!cs35l56->dsp.system_name) + return -ENOMEM; + } + if (!wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) { dev_err(cs35l56->base.dev, "%s: init_completion timed out\n", __func__); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5a1c750e6ae6..961241100012 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1924,6 +1924,12 @@ static int mc_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) codec_info_list[i].amp_num = 0; + if (mach->mach_params.subsystem_id_set) { + snd_soc_card_set_pci_ssid(card, + mach->mach_params.subsystem_vendor, + mach->mach_params.subsystem_device); + } + ret = sof_card_dai_links_create(card); if (ret < 0) return ret; diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index e7ef77012c35..9c2359d10ecf 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -1031,6 +1031,13 @@ int sof_machine_check(struct snd_sof_dev *sdev) mach = snd_sof_machine_select(sdev); if (mach) { sof_pdata->machine = mach; + + if (sof_pdata->subsystem_id_set) { + mach->mach_params.subsystem_vendor = sof_pdata->subsystem_vendor; + mach->mach_params.subsystem_device = sof_pdata->subsystem_device; + mach->mach_params.subsystem_id_set = true; + } + snd_sof_set_mach_params(mach, sdev); return 0; } diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index f5ece43d0ec2..146d25983b08 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -214,6 +214,14 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return ret; sof_pdata->name = pci_name(pci); + + /* PCI defines a vendor ID of 0xFFFF as invalid. */ + if (pci->subsystem_vendor != 0xFFFF) { + sof_pdata->subsystem_vendor = pci->subsystem_vendor; + sof_pdata->subsystem_device = pci->subsystem_device; + sof_pdata->subsystem_id_set = true; + } + sof_pdata->desc = desc; sof_pdata->dev = dev; |