[PATCH 0/6] Add generic AMD Soundwire machine driver for Legacy(No
This patch series add SoundWire machines for RT711, RT714, RT1316 and RT722 codecs for ACP 6.3 platform. Also, it adds a generic SoundWire machine driver code for legacy(No DSP) stack.
Vijendar Mukunda (6): ASoC: amd: acp: add rt722 based soundwire machines ASoC: amd: acp: add RT711, RT714 & RT1316 support for acp 6.3 platform ASoC: amd: ps: add soundwire machines for acp6.3 platform ASoC: amd: acp: move get_acp63_cpu_pin_id() to common file ASoC: amd: acp: add soundwire machine driver for legacy stack ASoC: amd: ps: fix the pcm device numbering for acp 6.3 platform
sound/soc/amd/acp/Kconfig | 29 ++ sound/soc/amd/acp/Makefile | 4 + sound/soc/amd/acp/acp-sdw-legacy-mach.c | 486 +++++++++++++++++++++++ sound/soc/amd/acp/acp-sdw-mach-common.c | 64 +++ sound/soc/amd/acp/acp-sdw-sof-mach.c | 49 +-- sound/soc/amd/acp/amd-acp63-acpi-match.c | 54 +++ sound/soc/amd/acp/soc_amd_sdw_common.h | 4 + sound/soc/amd/mach-config.h | 1 + sound/soc/amd/ps/pci-ps.c | 1 + sound/soc/amd/ps/ps-sdw-dma.c | 2 + 10 files changed, 646 insertions(+), 48 deletions(-) create mode 100644 sound/soc/amd/acp/acp-sdw-legacy-mach.c create mode 100644 sound/soc/amd/acp/acp-sdw-mach-common.c
Add RT722 based soundwire machines for legacy(NO DSP) stack for acp 6.3 platform.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/acp/amd-acp63-acpi-match.c | 49 ++++++++++++++++++++++++ sound/soc/amd/mach-config.h | 1 + 2 files changed, 50 insertions(+)
diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c index be9367913073..5e506c9e3da6 100644 --- a/sound/soc/amd/acp/amd-acp63-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -73,6 +73,45 @@ static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = { {} };
+static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { + { + .adr = 0x000030025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_link_adr acp63_rt722_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { { .link_mask = BIT(0) | BIT(1), @@ -85,6 +124,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { }; EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines);
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = { + { + .link_mask = BIT(0), + .links = acp63_rt722_only, + .drv_name = "amd_sdw", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines); + MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index 1a967da35a0f..a86c76f781f9 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -23,6 +23,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[];
This patch add supports for corresponding codecs on acp6.3 platform hardware configuration. SDW0: RT711 Jack SDW0: RT1316 Left Speaker SDW0: RT1316 Right Speaker SDW1: RT714 DMIC
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/acp/amd-acp63-acpi-match.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c index 5e506c9e3da6..9b6a49c051cd 100644 --- a/sound/soc/amd/acp/amd-acp63-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -130,6 +130,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = { .links = acp63_rt722_only, .drv_name = "amd_sdw", }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_4_in_1_sdca, + .drv_name = "amd_sdw", + }, {}, }; EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines);
Add SoundWire machines for acp 6.3 platform for legacy(No DSP) stack.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/ps/pci-ps.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 4365499c8f82..a7583844f5b4 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -598,6 +598,7 @@ static int snd_acp63_probe(struct pci_dev *pci, dev_err(&pci->dev, "ACP platform devices creation failed\n"); goto de_init; } + adata->machines = snd_soc_acpi_amd_acp63_sdw_machines; ret = acp63_machine_register(&pci->dev); if (ret) { dev_err(&pci->dev, "ACP machine register failed\n");
get_acp63_cpu_pin_id() is the common SoundWire machine driver helper function will be used for AMD Legacy(No DSP) generic SoundWire machine driver as well. Move get_acp63_cpu_pin_id() function to common place holder.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/acp/Kconfig | 7 +++ sound/soc/amd/acp/Makefile | 2 + sound/soc/amd/acp/acp-sdw-mach-common.c | 64 +++++++++++++++++++++++++ sound/soc/amd/acp/acp-sdw-sof-mach.c | 49 +------------------ sound/soc/amd/acp/soc_amd_sdw_common.h | 2 + 5 files changed, 76 insertions(+), 48 deletions(-) create mode 100644 sound/soc/amd/acp/acp-sdw-mach-common.c
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 88391e4c17e3..acd047d558bd 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -119,10 +119,17 @@ config SND_SOC_AMD_SOF_MACH help This option enables SOF sound card support for ACP audio.
+config SND_SOC_AMD_SDW_MACH_COMMON + tristate + help + This option enables common SoundWire Machine driver module for + AMD platforms. + config SND_SOC_AMD_SOF_SDW_MACH tristate "AMD SOF Soundwire Machine Driver Support" depends on X86 && PCI && ACPI depends on SOUNDWIRE + select SND_SOC_AMD_SDW_MACH_COMMON select SND_SOC_SDW_UTILS select SND_SOC_DMIC select SND_SOC_RT711_SDW diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 82cf5d180b3a..0e6c4022e7a2 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -23,6 +23,7 @@ snd-acp-mach-y := acp-mach-common.o snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o snd-acp-sof-mach-y := acp-sof-mach.o snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o +snd-acp-sdw-mach-y := acp-sdw-mach-common.o snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o @@ -41,4 +42,5 @@ obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o +obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c new file mode 100644 index 000000000000..d9393cc4a302 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-mach-common.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-mach-common - Common machine driver helper functions for + * legacy(No DSP) stack and SOF stack. + */ + +#include <linux/device.h> +#include <linux/module.h> +#include "soc_amd_sdw_common.h" + +int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + case SOC_SDW_AMP_IN_DAI_ID: + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_RX; + break; + default: + dev_err(dev, "invalid be_id:%d\n", be_id); + return -EINVAL; + } + break; + default: + dev_err(dev, "Invalid link id:%d\n", sdw_link_id); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, SND_SOC_AMD_SDW_MACH); + +MODULE_DESCRIPTION("AMD SoundWire Common Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda Vijendar.Mukunda@amd.com"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c index 8fce8cb957c9..0d256c0749c9 100644 --- a/sound/soc/amd/acp/acp-sdw-sof-mach.c +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -64,54 +64,6 @@ static const struct snd_soc_ops sdw_ops = { .shutdown = asoc_sdw_shutdown, };
-static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) -{ - switch (sdw_link_id) { - case AMD_SDW0: - switch (be_id) { - case SOC_SDW_JACK_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO0_TX; - break; - case SOC_SDW_JACK_IN_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO0_RX; - break; - case SOC_SDW_AMP_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO1_TX; - break; - case SOC_SDW_AMP_IN_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO1_RX; - break; - case SOC_SDW_DMIC_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO2_RX; - break; - default: - dev_err(dev, "Invalid be id:%d\n", be_id); - return -EINVAL; - } - break; - case AMD_SDW1: - switch (be_id) { - case SOC_SDW_JACK_OUT_DAI_ID: - case SOC_SDW_AMP_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW1_AUDIO0_TX; - break; - case SOC_SDW_JACK_IN_DAI_ID: - case SOC_SDW_AMP_IN_DAI_ID: - case SOC_SDW_DMIC_DAI_ID: - *cpu_pin_id = ACP63_SW1_AUDIO0_RX; - break; - default: - dev_err(dev, "invalid be_id:%d\n", be_id); - return -EINVAL; - } - break; - default: - dev_err(dev, "Invalid link id:%d\n", sdw_link_id); - return -EINVAL; - } - return 0; -} - static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
static int create_sdw_dailink(struct snd_soc_card *card, @@ -491,3 +443,4 @@ MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver"); MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); +MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH); diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h index f1bd5a7afc8e..eba92cd004d4 100644 --- a/sound/soc/amd/acp/soc_amd_sdw_common.h +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -41,4 +41,6 @@ struct amd_mc_ctx { unsigned int max_sdw_links; };
+int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev); + #endif
Add SoundWire machine driver for legacy(No DSP) stack for ACP6.3 platform.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/acp/Kconfig | 22 ++ sound/soc/amd/acp/Makefile | 2 + sound/soc/amd/acp/acp-sdw-legacy-mach.c | 486 ++++++++++++++++++++++++ sound/soc/amd/acp/soc_amd_sdw_common.h | 2 + 4 files changed, 512 insertions(+) create mode 100644 sound/soc/amd/acp/acp-sdw-legacy-mach.c
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index acd047d558bd..03f3fcbba5af 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -144,6 +144,28 @@ config SND_SOC_AMD_SOF_SDW_MACH on AMD platform. If unsure select "N".
+config SND_SOC_AMD_LEGACY_SDW_MACH + tristate "AMD Legacy(No DSP) Soundwire Machine Driver Support" + depends on X86 && PCI && ACPI + depends on SOUNDWIRE + select SND_SOC_AMD_SDW_MACH_COMMON + select SND_SOC_SDW_UTILS + select SND_SOC_DMIC + select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW + select SND_SOC_RT712_SDCA_SDW + select SND_SOC_RT712_SDCA_DMIC_SDW + select SND_SOC_RT1316_SDW + select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW + select SND_SOC_RT722_SDCA_SDW + help + This option enables Legacy(No DSP) sound card support for SoundWire + enabled AMD platforms along with ACP PDM controller. + Say Y if you want to enable SoundWire based machine driver support + on AMD platform. + If unsure select "N". + endif # SND_SOC_AMD_ACP_COMMON
config SND_AMD_SOUNDWIRE_ACPI diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 0e6c4022e7a2..bb2702036338 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -25,6 +25,7 @@ snd-acp-sof-mach-y := acp-sof-mach.o snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o snd-acp-sdw-mach-y := acp-sdw-mach-common.o snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o +snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o @@ -44,3 +45,4 @@ obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o +obj-$(CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH) += snd-acp-sdw-legacy-mach.o diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c new file mode 100644 index 000000000000..48952a238946 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-legacy-mach - ASoC legacy Machine driver for AMD SoundWire platforms + */ + +#include <linux/bitmap.h> +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "soc_amd_sdw_common.h" +#include "../../codecs/rt711.h" + +static unsigned long soc_sdw_quirk = RT711_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); + +static void log_quirks(struct device *dev) +{ + if (SOC_JACK_JDSRC(soc_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOC_JACK_JDSRC(soc_sdw_quirk)); + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) + dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); +} + +static int soc_sdw_quirk_cb(const struct dmi_system_id *id) +{ + soc_sdw_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id soc_sdw_quirk_table[] = { + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), + DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"), + }, + .driver_data = (void *)RT711_JD2, + }, + {} +}; + +static const struct snd_soc_ops sdw_ops = { + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_hw_free, + .shutdown = asoc_sdw_shutdown, +}; + +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + +static int create_sdw_dailink(struct snd_soc_card *card, + struct asoc_sdw_dailink *soc_dai, + struct snd_soc_dai_link **dai_links, + int *be_id, struct snd_soc_codec_conf **codec_conf, + struct snd_soc_dai_link_component *sdw_platform_component) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct asoc_sdw_endpoint *soc_end; + int cpu_pin_id; + int stream; + int ret; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (soc_end->name_prefix) { + (*codec_conf)->dlc.name = soc_end->codec_name; + (*codec_conf)->name_prefix = soc_end->name_prefix; + (*codec_conf)++; + } + + if (soc_end->include_sidecar) { + ret = soc_end->codec_info->add_sidecar(card, dai_links, codec_conf); + if (ret) + return ret; + } + } + + for_each_pcm_streams(stream) { + static const char * const sdw_stream_name[] = { + "SDW%d-PIN%d-PLAYBACK", + "SDW%d-PIN%d-CAPTURE", + "SDW%d-PIN%d-PLAYBACK-%s", + "SDW%d-PIN%d-CAPTURE-%s", + }; + struct snd_soc_dai_link_ch_map *codec_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + int num_cpus = hweight32(soc_dai->link_mask[stream]); + int num_codecs = soc_dai->num_devs[stream]; + int playback, capture; + int j = 0; + char *name; + + if (!soc_dai->num_devs[stream]) + continue; + + soc_end = list_first_entry(&soc_dai->endpoints, + struct asoc_sdw_endpoint, list); + + *be_id = soc_end->dai_info->dailink[stream]; + if (*be_id < 0) { + dev_err(dev, "Invalid dailink id %d\n", *be_id); + return -EINVAL; + } + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + ret = get_acp63_cpu_pin_id(ffs(soc_end->link_mask - 1), + *be_id, &cpu_pin_id, dev); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + /* create stream name according to first link id */ + if (ctx->append_dai_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], + ffs(soc_end->link_mask) - 1, + cpu_pin_id, + type_strings[soc_end->dai_info->dai_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], + ffs(soc_end->link_mask) - 1, + cpu_pin_id); + } + if (!name) + return -ENOMEM; + + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); + if (!cpus) + return -ENOMEM; + + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); + if (!codec_maps) + return -ENOMEM; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (!soc_end->dai_info->direction[stream]) + continue; + + int link_num = ffs(soc_end->link_mask) - 1; + + cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", + link_num, cpu_pin_id); + dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); + if (!cpus->dai_name) + return -ENOMEM; + + codec_maps[j].cpu = 0; + codec_maps[j].codec = j; + + codecs[j].name = soc_end->codec_name; + codecs[j].dai_name = soc_end->dai_info->dai_name; + j++; + } + + WARN_ON(j != num_codecs); + + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); + + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, num_cpus, sdw_platform_component, + 1, codecs, num_codecs, + 0, asoc_sdw_rtd_init, &sdw_ops); + /* + * SoundWire DAILINKs use 'stream' functions and Bank Switch operations + * based on wait_for_completion(), tag them as 'nonatomic'. + */ + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = codec_maps; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (soc_end->dai_info->init) + soc_end->dai_info->init(card, *dai_links, + soc_end->codec_info, + playback); + } + + (*dai_links)++; + } + + return 0; +} + +static int create_sdw_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct asoc_sdw_dailink *soc_dais, + struct snd_soc_codec_conf **codec_conf) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct snd_soc_dai_link_component *sdw_platform_component; + int ret; + + sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), + GFP_KERNEL); + if (!sdw_platform_component) + return -ENOMEM; + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + sdw_platform_component->name = "amd_ps_sdw_dma.0"; + break; + default: + return -EINVAL; + } + + /* generate DAI links by each sdw link */ + while (soc_dais->initialised) { + int current_be_id; + + ret = create_sdw_dailink(card, soc_dais, dai_links, + ¤t_be_id, codec_conf, sdw_platform_component); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + soc_dais++; + } + + return 0; +} + +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct snd_soc_dai_link_component *pdm_cpu; + struct snd_soc_dai_link_component *pdm_platform; + int ret; + + pdm_cpu = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_cpu) + return -ENOMEM; + + pdm_platform = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_platform) + return -ENOMEM; + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + pdm_cpu->name = "acp_ps_pdm_dma.0"; + pdm_platform->name = "acp_ps_pdm_dma.0"; + break; + default: + return -EINVAL; + } + + *be_id = ACP_DMIC_BE_ID; + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec", + 0, 1, // DMIC only supports capture + pdm_cpu->name, pdm_platform->name, 1, + "dmic-codec.0", "dmic-hifi", no_pcm, + asoc_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + +static int soc_card_dai_links_create(struct snd_soc_card *card) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); + int sdw_be_num = 0, dmic_num = 0; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + struct asoc_sdw_endpoint *soc_ends __free(kfree) = NULL; + struct asoc_sdw_dailink *soc_dais __free(kfree) = NULL; + struct snd_soc_codec_conf *codec_conf; + struct snd_soc_dai_link *dai_links; + int num_devs = 0; + int num_ends = 0; + int num_links; + int be_id = 0; + int ret; + + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + /* One per DAI link, worst case is a DAI link for every endpoint */ + soc_dais = kcalloc(num_ends, sizeof(*soc_dais), GFP_KERNEL); + if (!soc_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + soc_ends = kcalloc(num_ends, sizeof(*soc_ends), GFP_KERNEL); + if (!soc_ends) + return -ENOMEM; + + ret = asoc_sdw_parse_sdw_endpoints(card, soc_dais, soc_ends, &num_devs); + if (ret < 0) + return ret; + + sdw_be_num = ret; + + /* enable dmic */ + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num) + dmic_num = 1; + + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); + + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) + return -ENOMEM; + + /* allocate BE dailinks */ + num_links = sdw_be_num + dmic_num; + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); + if (!dai_links) + return -ENOMEM; + + card->codec_conf = codec_conf; + card->num_configs = num_devs; + card->dai_link = dai_links; + card->num_links = num_links; + + /* SDW */ + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, + soc_dais, &codec_conf); + if (ret) + return ret; + } + + /* dmic */ + if (dmic_num > 0) { + if (ctx->ignore_internal_dmic) { + dev_warn(dev, "Ignoring ACP DMIC\n"); + } else { + ret = create_dmic_dailinks(card, &dai_links, &be_id, 0); + if (ret) + return ret; + } + } + + WARN_ON(codec_conf != card->codec_conf + card->num_configs); + WARN_ON(dai_links != card->dai_link + card->num_links); + + return ret; +} + +static int mc_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); + struct snd_soc_card *card; + struct amd_mc_ctx *amd_ctx; + struct asoc_sdw_mc_private *ctx; + int amp_num = 0, i; + int ret; + + amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL); + if (!amd_ctx) + return -ENOMEM; + + amd_ctx->acp_rev = mach->mach_params.subsystem_rev; + amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS; + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); + ctx->private = amd_ctx; + card = &ctx->card; + card->dev = &pdev->dev; + card->name = "amd-soundwire"; + card->owner = THIS_MODULE; + card->late_probe = asoc_sdw_card_late_probe; + + snd_soc_card_set_drvdata(card, ctx); + + dmi_check_system(soc_sdw_quirk_table); + + if (quirk_override != -1) { + dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", + soc_sdw_quirk, quirk_override); + soc_sdw_quirk = quirk_override; + } + + log_quirks(card->dev); + + ctx->mc_quirk = soc_sdw_quirk; + dev_dbg(card->dev, "legacy quirk 0x%lx\n", ctx->mc_quirk); + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ + for (i = 0; i < ctx->codec_info_list_count; i++) + codec_info_list[i].amp_num = 0; + + ret = soc_card_dai_links_create(card); + if (ret < 0) + return ret; + + /* + * the default amp_num is zero for each codec and + * amp_num will only be increased for active amp + * codecs on used platform + */ + for (i = 0; i < ctx->codec_info_list_count; i++) + amp_num += codec_info_list[i].amp_num; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + if (mach->mach_params.dmic_num) { + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:dmic cfg-mics:%d", + card->components, + mach->mach_params.dmic_num); + if (!card->components) + return -ENOMEM; + } + + /* Register the card */ + ret = devm_snd_soc_register_card(card->dev, card); + if (ret) { + dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); + asoc_sdw_mc_dailink_exit_loop(card); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static void mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + asoc_sdw_mc_dailink_exit_loop(card); +} + +static const struct platform_device_id mc_id_table[] = { + { "amd_sdw", }, + {} +}; +MODULE_DEVICE_TABLE(platform, mc_id_table); + +static struct platform_driver soc_sdw_driver = { + .driver = { + .name = "amd_sdw", + .pm = &snd_soc_pm_ops, + }, + .probe = mc_probe, + .remove = mc_remove, + .id_table = mc_id_table, +}; + +module_platform_driver(soc_sdw_driver); + +MODULE_DESCRIPTION("ASoC AMD SoundWire Legacy Generic Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda Vijendar.Mukunda@amd.com"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); +MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH); diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h index eba92cd004d4..b7bae107c13e 100644 --- a/sound/soc/amd/acp/soc_amd_sdw_common.h +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -36,6 +36,8 @@ #define ACP63_SW1_AUDIO0_TX 0 #define ACP63_SW1_AUDIO0_RX 1
+#define ACP_DMIC_BE_ID 4 + struct amd_mc_ctx { unsigned int acp_rev; unsigned int max_sdw_links;
Fixed PCM device numbering is required for defining common alsa ucm changes for generic soundwire machine driver for legacy(No DSP) stack.
Ex: For Headphone playback use case, use PCM device number as 0. For Headset mic Capture use case, PCM device number as 1.
Set the 'use_dai_pcm_id' flag true in soundwire dma driver for acp 6.3 platform. This will fix the pcm device numbering based on dai_link->id.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/ps/ps-sdw-dma.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 3b4b9c6b3171..b602cca92b8b 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -445,6 +445,8 @@ static const struct snd_soc_component_driver acp63_sdw_component = { .trigger = acp63_sdw_dma_trigger, .pointer = acp63_sdw_dma_pointer, .pcm_construct = acp63_sdw_dma_new, + .use_dai_pcm_id = true, + };
static int acp63_sdw_platform_probe(struct platform_device *pdev)
On Wed, 13 Nov 2024 17:22:17 +0530, Vijendar Mukunda wrote:
This patch series add SoundWire machines for RT711, RT714, RT1316 and RT722 codecs for ACP 6.3 platform. Also, it adds a generic SoundWire machine driver code for legacy(No DSP) stack.
Vijendar Mukunda (6): ASoC: amd: acp: add rt722 based soundwire machines ASoC: amd: acp: add RT711, RT714 & RT1316 support for acp 6.3 platform ASoC: amd: ps: add soundwire machines for acp6.3 platform ASoC: amd: acp: move get_acp63_cpu_pin_id() to common file ASoC: amd: acp: add soundwire machine driver for legacy stack ASoC: amd: ps: fix the pcm device numbering for acp 6.3 platform
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/6] ASoC: amd: acp: add rt722 based soundwire machines commit: 804aaa9df6c3bf9744205ae51cad084ee97567bc [2/6] ASoC: amd: acp: add RT711, RT714 & RT1316 support for acp 6.3 platform commit: 7d3fe292efb637d1f748926390a3a4cc90c4c4e9 [3/6] ASoC: amd: ps: add soundwire machines for acp6.3 platform commit: 56d540befd5940dc34b4e22cc9b8ce9bb45946f7 [4/6] ASoC: amd: acp: move get_acp63_cpu_pin_id() to common file commit: 393347cc10ea24c9f93b45e8e2f90fcc48ab1d8e [5/6] ASoC: amd: acp: add soundwire machine driver for legacy stack commit: 2981d9b0789c44b7375e7d599caf71bd843afc9e [6/6] ASoC: amd: ps: fix the pcm device numbering for acp 6.3 platform commit: 76b5a3b2afdce1460dcd06221f7aa8eb2b807b1f
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Vijendar Mukunda