summaryrefslogtreecommitdiff
path: root/sound/soc/amd
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/amd')
-rw-r--r--sound/soc/amd/Kconfig35
-rw-r--r--sound/soc/amd/Makefile14
-rw-r--r--sound/soc/amd/acp-config.c12
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c22
-rw-r--r--sound/soc/amd/acp-es8336.c6
-rw-r--r--sound/soc/amd/acp-pcm-dma.c2
-rw-r--r--sound/soc/amd/acp/Kconfig58
-rw-r--r--sound/soc/amd/acp/Makefile34
-rw-r--r--sound/soc/amd/acp/acp-i2s.c220
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c169
-rw-r--r--sound/soc/amd/acp/acp-legacy-mach.c19
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c75
-rw-r--r--sound/soc/amd/acp/acp-mach.h11
-rw-r--r--sound/soc/amd/acp/acp-pci.c40
-rw-r--r--sound/soc/amd/acp/acp-pdm.c10
-rw-r--r--sound/soc/amd/acp/acp-platform.c145
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c15
-rw-r--r--sound/soc/amd/acp/acp-renoir.c10
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c486
-rw-r--r--sound/soc/amd/acp/acp-sdw-mach-common.c64
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c446
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c43
-rw-r--r--sound/soc/amd/acp/acp63.c15
-rw-r--r--sound/soc/amd/acp/acp70.c87
-rw-r--r--sound/soc/amd/acp/acp_common.h19
-rw-r--r--sound/soc/amd/acp/amd-acp63-acpi-match.c144
-rw-r--r--sound/soc/amd/acp/amd-sdw-acpi.c62
-rw-r--r--sound/soc/amd/acp/amd.h47
-rw-r--r--sound/soc/amd/acp/chip_offset_byte.h85
-rw-r--r--sound/soc/amd/acp/soc_amd_sdw_common.h48
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c8
-rw-r--r--sound/soc/amd/mach-config.h3
-rw-r--r--sound/soc/amd/ps/Makefile10
-rw-r--r--sound/soc/amd/ps/acp63.h93
-rw-r--r--sound/soc/amd/ps/pci-ps.c588
-rw-r--r--sound/soc/amd/ps/ps-mach.c3
-rw-r--r--sound/soc/amd/ps/ps-pdm-dma.c4
-rw-r--r--sound/soc/amd/ps/ps-sdw-dma.c8
-rw-r--r--sound/soc/amd/raven/Makefile6
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c2
-rw-r--r--sound/soc/amd/renoir/Makefile6
-rw-r--r--sound/soc/amd/renoir/acp3x-pdm-dma.c2
-rw-r--r--sound/soc/amd/renoir/acp3x-rn.c1
-rw-r--r--sound/soc/amd/rpl/Makefile2
-rw-r--r--sound/soc/amd/vangogh/Makefile8
-rw-r--r--sound/soc/amd/vangogh/acp5x-mach.c6
-rw-r--r--sound/soc/amd/vangogh/acp5x-pcm-dma.c2
-rw-r--r--sound/soc/amd/yc/Makefile6
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c172
-rw-r--r--sound/soc/amd/yc/acp6x-pdm-dma.c2
-rw-r--r--sound/soc/amd/yc/pci-acp6x.c1
51 files changed, 2613 insertions, 763 deletions
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 273688c05317..803521178279 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -105,7 +105,7 @@ config SND_SOC_AMD_ACP6x
config SND_SOC_AMD_YC_MACH
tristate "AMD YC support for DMIC"
select SND_SOC_DMIC
- depends on SND_SOC_AMD_ACP6x
+ depends on SND_SOC_AMD_ACP6x && ACPI
help
This option enables machine driver for Yellow Carp platform
using dmic. ACP IP has PDM Decoder block with DMA controller.
@@ -132,9 +132,38 @@ config SND_SOC_AMD_RPL_ACP6x
Say m if you have such a device.
If unsure select "N".
+config SND_SOC_AMD_ACP63_TOPLEVEL
+ tristate "support for AMD platforms with ACP version >= 6.3"
+ default SND_AMD_ACP_CONFIG
+ depends on SND_AMD_ACP_CONFIG
+ depends on SOUNDWIRE_AMD || !SOUNDWIRE_AMD
+ depends on X86 || COMPILE_TEST
+ help
+ This adds support for AMD platforms with ACP version >= 6.3.
+ Say Y if you have such a device.
+ If unsure select "N".
+
+if SND_SOC_AMD_ACP63_TOPLEVEL
+
+config SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+ tristate
+ select SND_AMD_SOUNDWIRE_ACPI if ACPI
+
+config SND_SOC_AMD_SOUNDWIRE
+ tristate "Support for SoundWire based AMD platforms"
+ default SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+ depends on SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+ depends on ACPI
+ depends on SOUNDWIRE_AMD
+ help
+ This adds support for SoundWire for AMD platforms.
+ Say Y if you want to enable SoundWire links with SOF.
+ If unsure select "N".
+
config SND_SOC_AMD_PS
tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support"
- select SND_AMD_ACP_CONFIG
+ select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+ select SND_SOC_ACPI_AMD_MATCH
depends on X86 && PCI && ACPI
help
This option enables Audio Coprocessor i.e ACP v6.3 support on
@@ -154,3 +183,5 @@ config SND_SOC_AMD_PS_MACH
DMIC can be connected directly to ACP IP.
Say m if you have such a device.
If unsure select "N".
+
+endif
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index 82e1cf864a40..4f89d962cce2 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
-acp_audio_dma-objs := acp-pcm-dma.o
-snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o
-snd-soc-acp-rt5645-mach-objs := acp-rt5645.o
-snd-soc-acp-es8336-mach-objs := acp-es8336.o
-snd-soc-acp-rt5682-mach-objs := acp3x-rt5682-max9836.o
-snd-acp-config-objs := acp-config.o
+acp_audio_dma-y := acp-pcm-dma.o
+snd-soc-acp-da7219mx98357-mach-y := acp-da7219-max98357a.o
+snd-soc-acp-rt5645-mach-y := acp-rt5645.o
+snd-soc-acp-es8336-mach-y := acp-es8336.o
+snd-soc-acp-rt5682-mach-y := acp3x-rt5682-max9836.o
+snd-acp-config-y := acp-config.o
obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o
obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o
@@ -15,7 +15,7 @@ obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/
-obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
+obj-$(CONFIG_SND_AMD_ACP_CONFIG) += acp/
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o
obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += rpl/
obj-$(CONFIG_SND_SOC_AMD_PS) += ps/
diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c
index 42c2322cd11b..365209ea53f3 100644
--- a/sound/soc/amd/acp-config.c
+++ b/sound/soc/amd/acp-config.c
@@ -321,5 +321,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[] = {
};
EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_machines);
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[] = {
+ {
+ .id = "AMDI1010",
+ .drv_name = "acp70-dsp",
+ .pdata = &acp_quirk_data,
+ .fw_filename = "sof-acp_7_0.ri",
+ .sof_tplg_filename = "sof-acp_7_0.tplg",
+ },
+ {},
+};
+EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sof_machines);
+
MODULE_DESCRIPTION("AMD ACP Machine Configuration Module");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c
index 84f3d65ba52e..02b04f355ca6 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -542,7 +542,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = cz_da7219_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_da7219_play_ops,
SND_SOC_DAILINK_REG(designware1, dlgs, platform),
@@ -552,7 +552,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_da7219_cap_ops,
SND_SOC_DAILINK_REG(designware2, dlgs, platform),
@@ -562,7 +562,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform),
@@ -573,7 +573,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "DMIC0 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform),
@@ -584,7 +584,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "DMIC1 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform),
@@ -598,7 +598,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = cz_rt5682_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_play_ops,
SND_SOC_DAILINK_REG(designware1, rt5682, platform),
@@ -608,7 +608,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_cap_ops,
SND_SOC_DAILINK_REG(designware2, rt5682, platform),
@@ -618,7 +618,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform),
@@ -629,7 +629,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "DMIC0 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform),
@@ -640,7 +640,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "DMIC1 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform),
@@ -733,7 +733,7 @@ static struct regulator_config acp_da7219_cfg = {
.init_data = &acp_da7219_data,
};
-static struct regulator_ops acp_da7219_ops = {
+static const struct regulator_ops acp_da7219_ops = {
};
static const struct regulator_desc acp_da7219_desc = {
diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c
index e079b3218c6f..0193b3eae7a6 100644
--- a/sound/soc/amd/acp-es8336.c
+++ b/sound/soc/amd/acp-es8336.c
@@ -150,8 +150,6 @@ static struct snd_soc_dai_link st_dai_es8336[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
- .dpcm_capture = 1,
- .dpcm_playback = 1,
.init = st_es8336_init,
.ops = &st_es8336_ops,
SND_SOC_DAILINK_REG(designware1, codec, platform),
@@ -203,8 +201,10 @@ static int st_es8336_late_probe(struct snd_soc_card *card)
codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev);
- if (!codec_dev)
+ if (!codec_dev) {
dev_err(card->dev, "can not find codec dev\n");
+ return -ENODEV;
+ }
ret = devm_acpi_dev_add_driver_gpios(codec_dev, acpi_es8336_gpios);
if (ret)
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index b857e2676fe8..897dde630022 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1426,7 +1426,7 @@ static const struct dev_pm_ops acp_pm_ops = {
static struct platform_driver acp_dma_driver = {
.probe = acp_audio_probe,
- .remove_new = acp_audio_remove,
+ .remove = acp_audio_remove,
.driver = {
.name = DRV_NAME,
.pm = &acp_pm_ops,
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 84c963241dc5..03f3fcbba5af 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -13,6 +13,10 @@ config SND_SOC_AMD_ACP_COMMON
This option enables common modules for Audio-Coprocessor i.e. ACP
IP block on AMD platforms.
+config SND_SOC_ACPI_AMD_MATCH
+ tristate
+ select SND_SOC_ACPI if ACPI
+
if SND_SOC_AMD_ACP_COMMON
config SND_SOC_AMD_ACP_PDM
@@ -115,4 +119,58 @@ 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
+ select SND_SOC_RT711_SDCA_SDW
+ select SND_SOC_RT1316_SDW
+ select SND_SOC_RT715_SDW
+ select SND_SOC_RT715_SDCA_SDW
+ help
+ This option enables SOF 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".
+
+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
+ tristate
+ depends on ACPI
+ help
+ This options enables ACPI helper functions for SoundWire
+ interface for AMD platforms.
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index ff5f7893b81e..bb2702036338 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -5,22 +5,27 @@
# Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
#common acp driver
-snd-acp-pcm-objs := acp-platform.o
-snd-acp-i2s-objs := acp-i2s.o
-snd-acp-pdm-objs := acp-pdm.o
-snd-acp-legacy-common-objs := acp-legacy-common.o
-snd-acp-pci-objs := acp-pci.o
+snd-acp-pcm-y := acp-platform.o
+snd-acp-i2s-y := acp-i2s.o
+snd-acp-pdm-y := acp-pdm.o
+snd-acp-legacy-common-y := acp-legacy-common.o
+snd-acp-pci-y := acp-pci.o
+snd-amd-sdw-acpi-y := amd-sdw-acpi.o
#platform specific driver
-snd-acp-renoir-objs := acp-renoir.o
-snd-acp-rembrandt-objs := acp-rembrandt.o
-snd-acp63-objs := acp63.o
-snd-acp70-objs := acp70.o
+snd-acp-renoir-y := acp-renoir.o
+snd-acp-rembrandt-y := acp-rembrandt.o
+snd-acp63-y := acp63.o
+snd-acp70-y := acp70.o
#machine specific driver
-snd-acp-mach-objs := acp-mach-common.o
-snd-acp-legacy-mach-objs := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
-snd-acp-sof-mach-objs := acp-sof-mach.o
+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
+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
@@ -33,6 +38,11 @@ obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
obj-$(CONFIG_SND_AMD_ASOC_ACP63) += snd-acp63.o
obj-$(CONFIG_SND_AMD_ASOC_ACP70) += snd-acp70.o
+obj-$(CONFIG_SND_AMD_SOUNDWIRE_ACPI) += snd-amd-sdw-acpi.o
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
+obj-$(CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH) += snd-acp-sdw-legacy-mach.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 60cbc881be6e..89e99ed4275a 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -59,7 +59,9 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
val |= BIT(1);
switch (chip->acp_rev) {
- case ACP63_DEV:
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div);
val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div);
break;
@@ -95,9 +97,11 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
+ struct acp_chip_info *chip;
struct acp_stream *stream;
int slot_len, no_of_slots;
+ chip = dev_get_platdata(dev);
switch (slot_width) {
case SLOT_WIDTH_8:
slot_len = 8;
@@ -116,15 +120,38 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
return -EINVAL;
}
- switch (slots) {
- case 1 ... 7:
- no_of_slots = slots;
+ switch (chip->acp_rev) {
+ case ACP_RN_PCI_ID:
+ case ACP_RMB_PCI_ID:
+ switch (slots) {
+ case 1 ... 7:
+ no_of_slots = slots;
+ break;
+ case 8:
+ no_of_slots = 0;
+ break;
+ default:
+ dev_err(dev, "Unsupported slots %d\n", slots);
+ return -EINVAL;
+ }
break;
- case 8:
- no_of_slots = 0;
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ switch (slots) {
+ case 1 ... 31:
+ no_of_slots = slots;
+ break;
+ case 32:
+ no_of_slots = 0;
+ break;
+ default:
+ dev_err(dev, "Unsupported slots %d\n", slots);
+ return -EINVAL;
+ }
break;
default:
- dev_err(dev, "Unsupported slots %d\n", slots);
+ dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev);
return -EINVAL;
}
@@ -132,12 +159,31 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
spin_lock_irq(&adata->acp_lock);
list_for_each_entry(stream, &adata->stream_list, list) {
- if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
- adata->tdm_tx_fmt[stream->dai_id - 1] =
+ switch (chip->acp_rev) {
+ case ACP_RN_PCI_ID:
+ case ACP_RMB_PCI_ID:
+ if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ adata->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
- else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
- adata->tdm_rx_fmt[stream->dai_id - 1] =
+ else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
+ adata->tdm_rx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
+ break;
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ adata->tdm_tx_fmt[stream->dai_id - 1] =
+ FRM_LEN | (slots << 13) | (slot_len << 18);
+ else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
+ adata->tdm_rx_fmt[stream->dai_id - 1] =
+ FRM_LEN | (slots << 13) | (slot_len << 18);
+ break;
+ default:
+ dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev);
+ spin_unlock_irq(&adata->acp_lock);
+ return -EINVAL;
+ }
}
spin_unlock_irq(&adata->acp_lock);
return 0;
@@ -296,6 +342,41 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
default:
return -EINVAL;
}
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 16000:
+ case 24000:
+ case 48000:
+ case 96000:
+ case 192000:
+ switch (params_channels(params)) {
+ case 2:
+ break;
+ case 4:
+ bclk_div_val = bclk_div_val >> 1;
+ lrclk_div_val = lrclk_div_val << 1;
+ break;
+ case 8:
+ bclk_div_val = bclk_div_val >> 2;
+ lrclk_div_val = lrclk_div_val << 2;
+ break;
+ case 16:
+ bclk_div_val = bclk_div_val >> 3;
+ lrclk_div_val = lrclk_div_val << 3;
+ break;
+ case 32:
+ bclk_div_val = bclk_div_val >> 4;
+ lrclk_div_val = lrclk_div_val << 4;
+ break;
+ default:
+ dev_err(dev, "Unsupported channels %#x\n",
+ params_channels(params));
+ }
+ break;
+ default:
+ break;
+ }
adata->lrclk_div = lrclk_div_val;
adata->bclk_div = bclk_div_val;
}
@@ -321,16 +402,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
- water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
+ water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(adata);
reg_val = ACP_BTTDM_ITER;
ier_val = ACP_BTTDM_IER;
- buf_reg = ACP_BT_TX_RINGBUFSIZE;
+ buf_reg = ACP_BT_TX_RINGBUFSIZE(adata);
break;
case I2S_SP_INSTANCE:
- water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
+ water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(adata);
reg_val = ACP_I2STDM_ITER;
ier_val = ACP_I2STDM_IER;
- buf_reg = ACP_I2S_TX_RINGBUFSIZE;
+ buf_reg = ACP_I2S_TX_RINGBUFSIZE(adata);
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
@@ -345,16 +426,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
} else {
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
- water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
+ water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(adata);
reg_val = ACP_BTTDM_IRER;
ier_val = ACP_BTTDM_IER;
- buf_reg = ACP_BT_RX_RINGBUFSIZE;
+ buf_reg = ACP_BT_RX_RINGBUFSIZE(adata);
break;
case I2S_SP_INSTANCE:
- water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
+ water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(adata);
reg_val = ACP_I2STDM_IRER;
ier_val = ACP_I2STDM_IER;
- buf_reg = ACP_I2S_RX_RINGBUFSIZE;
+ buf_reg = ACP_I2S_RX_RINGBUFSIZE(adata);
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
@@ -367,14 +448,15 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
return -EINVAL;
}
}
+
writel(period_bytes, adata->acp_base + water_val);
writel(buf_size, adata->acp_base + buf_reg);
+ if (rsrc->soc_mclk)
+ acp_set_i2s_clk(adata, dai->driver->id);
val = readl(adata->acp_base + reg_val);
val = val | BIT(0);
writel(val, adata->acp_base + reg_val);
writel(1, adata->acp_base + ier_val);
- if (rsrc->soc_mclk)
- acp_set_i2s_clk(adata, dai->driver->id);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -436,52 +518,67 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip;
struct acp_resource *rsrc = adata->rsrc;
struct acp_stream *stream = substream->runtime->private_data;
u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
unsigned int dir = substream->stream;
+ chip = dev_get_platdata(dev);
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+ reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
- reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
-
- phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
+ reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
+ reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
+
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
+ writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
} else {
- reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+ reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
- reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
- phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
+ reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
+ reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
+
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
+ writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_BT_TX_DMA_SIZE;
+ reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_TX_FIFOADDR;
- reg_fifo_size = ACP_BT_TX_FIFOSIZE;
-
- phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
+ reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
+ reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
+
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+ writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
} else {
- reg_dma_size = ACP_BT_RX_DMA_SIZE;
+ reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_RX_FIFOADDR;
- reg_fifo_size = ACP_BT_RX_FIFOSIZE;
-
- phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
+ reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
+ reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
+
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
+ writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
}
break;
case I2S_HS_INSTANCE:
@@ -492,7 +589,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_HS_TX_FIFOADDR;
reg_fifo_size = ACP_HS_TX_FIFOSIZE;
- phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_HS_RX_DMA_SIZE;
@@ -501,7 +601,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_HS_RX_FIFOADDR;
reg_fifo_size = ACP_HS_RX_FIFOSIZE;
- phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START;
+ else
+ phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
}
break;
@@ -584,29 +687,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
return 0;
}
-static int acp_i2s_probe(struct snd_soc_dai *dai)
-{
- struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_resource *rsrc = adata->rsrc;
- unsigned int val;
-
- if (!adata->acp_base) {
- dev_err(dev, "I2S base is NULL\n");
- return -EINVAL;
- }
-
- val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
- if (val != rsrc->i2s_mode) {
- dev_err(dev, "I2S Mode not supported val %x\n", val);
- return -EINVAL;
- }
-
- return 0;
-}
-
const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
- .probe = acp_i2s_probe,
.startup = acp_i2s_startup,
.hw_params = acp_i2s_hwparams,
.prepare = acp_i2s_prepare,
@@ -614,7 +695,8 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
.set_fmt = acp_i2s_set_fmt,
.set_tdm_slot = acp_i2s_set_tdm_slot,
};
-EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, "SND_SOC_ACP_COMMON");
+MODULE_DESCRIPTION("AMD ACP Audio I2S controller");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c
index b5aff3f230be..7acc7ed2e8cc 100644
--- a/sound/soc/amd/acp/acp-legacy-common.c
+++ b/sound/soc/amd/acp/acp-legacy-common.c
@@ -31,7 +31,7 @@ void acp_enable_interrupts(struct acp_dev_data *adata)
ext_intr_ctrl |= ACP_ERROR_MASK;
writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
}
-EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON");
void acp_disable_interrupts(struct acp_dev_data *adata)
{
@@ -40,7 +40,7 @@ void acp_disable_interrupts(struct acp_dev_data *adata)
writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
}
-EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON");
static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -97,7 +97,7 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
set_acp_pdm_clk(substream, dai);
}
-EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -113,40 +113,40 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+ reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
- reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
+ reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
+ reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
+ writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
} else {
- reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+ reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
- reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
+ reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
+ reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
+ writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_BT_TX_DMA_SIZE;
+ reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_TX_FIFOADDR;
- reg_fifo_size = ACP_BT_TX_FIFOSIZE;
+ reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
+ reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
+ writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
} else {
- reg_dma_size = ACP_BT_RX_DMA_SIZE;
+ reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_RX_FIFOADDR;
- reg_fifo_size = ACP_BT_RX_FIFOSIZE;
+ reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
+ reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
+ writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
}
break;
case I2S_HS_INSTANCE:
@@ -248,7 +248,7 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
}
return set_acp_i2s_dma_fifo(substream, dai);
}
-EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, "SND_SOC_ACP_COMMON");
static int acp_power_on(struct acp_chip_info *chip)
{
@@ -257,19 +257,20 @@ static int acp_power_on(struct acp_chip_info *chip)
base = chip->base;
switch (chip->acp_rev) {
- case ACP3X_DEV:
+ case ACP_RN_PCI_ID:
acp_pgfsm_stat_reg = ACP_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL;
break;
- case ACP6X_DEV:
+ case ACP_RMB_PCI_ID:
acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
break;
- case ACP63_DEV:
+ case ACP63_PCI_ID:
acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
break;
- case ACP70_DEV:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL;
break;
@@ -321,9 +322,11 @@ int acp_init(struct acp_chip_info *chip)
pr_err("ACP reset failed\n");
return ret;
}
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ writel(0, chip->base + ACP_ZSC_DSP_CTRL);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_init, "SND_SOC_ACP_COMMON");
int acp_deinit(struct acp_chip_info *chip)
{
@@ -334,11 +337,13 @@ int acp_deinit(struct acp_chip_info *chip)
if (ret)
return ret;
- if (chip->acp_rev != ACP70_DEV)
+ if (chip->acp_rev < ACP70_PCI_ID)
writel(0, chip->base + ACP_CONTROL);
+ else
+ writel(0x01, chip->base + ACP_ZSC_DSP_CTRL);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON");
int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
{
@@ -346,7 +351,7 @@ int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
pci_write_config_dword(dev, 0x64, data);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(smn_write, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(smn_write, "SND_SOC_ACP_COMMON");
int smn_read(struct pci_dev *dev, u32 smn_addr)
{
@@ -356,13 +361,27 @@ int smn_read(struct pci_dev *dev, u32 smn_addr)
pci_read_config_dword(dev, 0x64, &data);
return data;
}
-EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(smn_read, "SND_SOC_ACP_COMMON");
-int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip)
+static void check_acp3x_config(struct acp_chip_info *chip)
{
- struct acpi_device *pdm_dev;
- const union acpi_object *obj;
- u32 pdm_addr, val;
+ u32 val;
+
+ val = readl(chip->base + ACP3X_PIN_CONFIG);
+ switch (val) {
+ case ACP_CONFIG_4:
+ chip->is_i2s_config = true;
+ chip->is_pdm_config = true;
+ break;
+ default:
+ chip->is_pdm_config = true;
+ break;
+ }
+}
+
+static void check_acp6x_config(struct acp_chip_info *chip)
+{
+ u32 val;
val = readl(chip->base + ACP_PIN_CONFIG);
switch (val) {
@@ -371,42 +390,96 @@ int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip)
case ACP_CONFIG_6:
case ACP_CONFIG_7:
case ACP_CONFIG_8:
- case ACP_CONFIG_10:
case ACP_CONFIG_11:
+ case ACP_CONFIG_14:
+ chip->is_pdm_config = true;
+ break;
+ case ACP_CONFIG_9:
+ chip->is_i2s_config = true;
+ break;
+ case ACP_CONFIG_10:
case ACP_CONFIG_12:
case ACP_CONFIG_13:
+ chip->is_i2s_config = true;
+ chip->is_pdm_config = true;
+ break;
+ default:
+ break;
+ }
+}
+
+static void check_acp70_config(struct acp_chip_info *chip)
+{
+ u32 val;
+
+ val = readl(chip->base + ACP_PIN_CONFIG);
+ switch (val) {
+ case ACP_CONFIG_4:
+ case ACP_CONFIG_5:
+ case ACP_CONFIG_6:
+ case ACP_CONFIG_7:
+ case ACP_CONFIG_8:
+ case ACP_CONFIG_11:
case ACP_CONFIG_14:
+ case ACP_CONFIG_17:
+ case ACP_CONFIG_18:
+ chip->is_pdm_config = true;
+ break;
+ case ACP_CONFIG_9:
+ chip->is_i2s_config = true;
+ break;
+ case ACP_CONFIG_10:
+ case ACP_CONFIG_12:
+ case ACP_CONFIG_13:
+ case ACP_CONFIG_19:
+ case ACP_CONFIG_20:
+ chip->is_i2s_config = true;
+ chip->is_pdm_config = true;
break;
default:
- return -EINVAL;
+ break;
}
+}
+
+void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
+{
+ struct acpi_device *pdm_dev;
+ const union acpi_object *obj;
+ u32 pdm_addr;
switch (chip->acp_rev) {
- case ACP3X_DEV:
+ case ACP_RN_PCI_ID:
pdm_addr = ACP_RENOIR_PDM_ADDR;
+ check_acp3x_config(chip);
break;
- case ACP6X_DEV:
+ case ACP_RMB_PCI_ID:
pdm_addr = ACP_REMBRANDT_PDM_ADDR;
+ check_acp6x_config(chip);
break;
- case ACP63_DEV:
+ case ACP63_PCI_ID:
pdm_addr = ACP63_PDM_ADDR;
+ check_acp6x_config(chip);
break;
- case ACP70_DEV:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
pdm_addr = ACP70_PDM_ADDR;
+ check_acp70_config(chip);
break;
default:
- return -EINVAL;
+ break;
}
- pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
- if (pdm_dev) {
- if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
- ACPI_TYPE_INTEGER, &obj) &&
- obj->integer.value == pdm_addr)
- return 0;
+ if (chip->is_pdm_config) {
+ pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
+ if (pdm_dev) {
+ if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
+ ACPI_TYPE_INTEGER, &obj) &&
+ obj->integer.value == pdm_addr)
+ chip->is_pdm_dev = true;
+ }
}
- return -ENODEV;
}
-EXPORT_SYMBOL_NS_GPL(check_acp_pdm, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON");
+MODULE_DESCRIPTION("AMD ACP legacy common features");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index 47c3b5f167f5..a7a551366a40 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -57,7 +57,6 @@ static struct acp_card_drvdata es83xx_rn_data = {
.dmic_cpu_id = DMIC,
.hs_codec_id = ES83XX,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
};
static struct acp_card_drvdata max_nau8825_data = {
@@ -68,7 +67,6 @@ static struct acp_card_drvdata max_nau8825_data = {
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.soc_mclk = true,
- .platform = REMBRANDT,
.tdm_mode = false,
};
@@ -80,7 +78,6 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.soc_mclk = true,
- .platform = REMBRANDT,
.tdm_mode = false,
};
@@ -126,6 +123,7 @@ static int acp_asoc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
@@ -171,7 +169,9 @@ static int acp_asoc_probe(struct platform_device *pdev)
goto out;
}
if (!strcmp(pdev->name, "acp-pdm-mach"))
- acp_card_drvdata->platform = *((int *)dev->platform_data);
+ acp_card_drvdata->acp_rev = *((int *)dev->platform_data);
+ else
+ acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev;
dmi_id = dmi_first_match(acp_quirk_table);
if (dmi_id && dmi_id->driver_data)
@@ -227,6 +227,8 @@ static const struct platform_device_id board_ids[] = {
},
{ }
};
+MODULE_DEVICE_TABLE(platform, board_ids);
+
static struct platform_driver acp_asoc_audio = {
.driver = {
.pm = &snd_soc_pm_ops,
@@ -238,13 +240,6 @@ static struct platform_driver acp_asoc_audio = {
module_platform_driver(acp_asoc_audio);
-MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_IMPORT_NS("SND_SOC_AMD_MACH");
MODULE_DESCRIPTION("ACP chrome audio support");
-MODULE_ALIAS("platform:acp3xalc56821019");
-MODULE_ALIAS("platform:acp3xalc5682sm98360");
-MODULE_ALIAS("platform:acp3xalc5682s1019");
-MODULE_ALIAS("platform:acp3x-es83xx");
-MODULE_ALIAS("platform:rmb-nau8825-max");
-MODULE_ALIAS("platform:rmb-rt5682s-rt1019");
-MODULE_ALIAS("platform:acp-pdm-mach");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index 504d1b8c4cbb..f7602c1769bf 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -217,7 +217,7 @@ static void acp_card_shutdown(struct snd_pcm_substream *substream)
static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
@@ -828,8 +828,8 @@ static const struct snd_soc_ops acp_card_maxim_ops = {
};
SND_SOC_DAILINK_DEF(max98388,
- DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ADS8388:00", "max98388-aif1"),
- COMP_CODEC("i2c-ADS8388:01", "max98388-aif1")));
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ADS8388:00", MAX98388_CODEC_DAI),
+ COMP_CODEC("i2c-ADS8388:01", MAX98388_CODEC_DAI)));
static const struct snd_kcontrol_new max98388_controls[] = {
SOC_DAPM_PIN_SWITCH("Left Spk"),
@@ -1280,7 +1280,7 @@ static const struct snd_soc_ops acp_8821_ops = {
SND_SOC_DAILINK_DEF(nau8821,
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00",
- "nau8821-hifi")));
+ NAU8821_CODEC_DAI)));
/* Declare DMIC codec components */
SND_SOC_DAILINK_DEF(dmic_codec,
@@ -1407,8 +1407,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_sp);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) {
@@ -1444,8 +1442,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_hs);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) {
@@ -1471,7 +1467,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
if (drv_data->amp_cpu_id == I2S_SP) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
- if (drv_data->platform == RENOIR) {
+ if (drv_data->acp_rev == ACP_RN_PCI_ID) {
links[i].cpus = sof_sp;
links[i].num_cpus = ARRAY_SIZE(sof_sp);
} else {
@@ -1480,7 +1476,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
}
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) {
@@ -1512,7 +1508,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) {
@@ -1527,7 +1523,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].init = acp_card_maxim_init;
}
if (drv_data->amp_codec_id == MAX98388) {
- links[i].dpcm_capture = 1;
+ links[i].playback_only = 0;
links[i].codecs = max98388;
links[i].num_codecs = ARRAY_SIZE(max98388);
links[i].ops = &acp_max98388_ops;
@@ -1553,8 +1549,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_bt);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->bt_codec_id) {
@@ -1574,7 +1568,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_dmic);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_capture = 1;
+ links[i].capture_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
}
@@ -1585,7 +1579,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
+EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, "SND_SOC_AMD_MACH");
int acp_legacy_dai_links_create(struct snd_soc_card *card)
{
@@ -1613,8 +1607,6 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(i2s_sp);
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1647,18 +1639,21 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].id = HEADSET_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
+
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1686,7 +1681,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(i2s_sp);
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1714,17 +1709,22 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].id = AMP_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
- links[i].dpcm_playback = 1;
+
+ links[i].playback_only = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1749,6 +1749,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
if (drv_data->dmic_cpu_id == DMIC) {
links[i].name = "acp-dmic-codec";
+ links[i].stream_name = "DMIC capture";
links[i].id = DMIC_BE_ID;
if (drv_data->dmic_codec_id == DMIC) {
links[i].codecs = dmic_codec;
@@ -1760,21 +1761,27 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
}
links[i].cpus = pdm_dmic;
links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else if (drv_data->platform == ACP70) {
+ break;
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
links[i].platforms = platform_acp70_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp70_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
links[i].ops = &acp_card_dmic_ops;
- links[i].dpcm_capture = 1;
+ links[i].capture_only = 1;
}
card->dai_link = links;
@@ -1783,7 +1790,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
+EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, "SND_SOC_AMD_MACH");
MODULE_DESCRIPTION("AMD ACP Common Machine driver");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index a48546d8d407..f94c30c20f20 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -18,6 +18,8 @@
#include <linux/module.h>
#include <sound/soc.h>
+#include "acp_common.h"
+
#define TDM_CHANNELS 8
#define ACP_OPS(priv, cb) ((priv)->ops.cb)
@@ -51,13 +53,6 @@ enum codec_endpoints {
ES83XX,
};
-enum platform_end_point {
- RENOIR = 0,
- REMBRANDT,
- ACP63,
- ACP70,
-};
-
struct acp_mach_ops {
int (*probe)(struct snd_soc_card *card);
int (*configure_link)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
@@ -76,7 +71,7 @@ struct acp_card_drvdata {
unsigned int bt_codec_id;
unsigned int dmic_codec_id;
unsigned int dai_fmt;
- unsigned int platform;
+ unsigned int acp_rev;
struct clk *wclk;
struct clk *bclk;
struct acp_mach_ops ops;
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index 8c8b1dcac628..e0fc42d939d3 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -77,30 +77,29 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
res_acp = acp_res;
num_res = ARRAY_SIZE(acp_res);
-
+ chip->acp_rev = pci->revision;
switch (pci->revision) {
case 0x01:
chip->name = "acp_asoc_renoir";
- chip->acp_rev = ACP3X_DEV;
break;
case 0x6f:
chip->name = "acp_asoc_rembrandt";
- chip->acp_rev = ACP6X_DEV;
break;
case 0x63:
chip->name = "acp_asoc_acp63";
- chip->acp_rev = ACP63_DEV;
break;
case 0x70:
chip->name = "acp_asoc_acp70";
- chip->acp_rev = ACP70_DEV;
+ break;
+ case 0x71:
+ chip->name = "acp_asoc_acp70";
break;
default:
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
ret = -EINVAL;
goto release_regions;
}
-
+ chip->flag = flag;
dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(dmic_dev)) {
dev_err(dev, "failed to create DMIC device\n");
@@ -115,7 +114,14 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
goto unregister_dmic_dev;
}
- acp_init(chip);
+ ret = acp_init(chip);
+ if (ret)
+ goto unregister_dmic_dev;
+
+ check_acp_config(pci, chip);
+ if (!chip->is_pdm_dev && !chip->is_i2s_config)
+ goto skip_pdev_creation;
+
res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
if (!res) {
ret = -ENOMEM;
@@ -133,13 +139,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
}
}
- if (flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
- ret = check_acp_pdm(pci, chip);
- if (ret < 0)
- goto skip_pdev_creation;
- }
-
- chip->flag = flag;
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.name = chip->name;
@@ -199,10 +198,12 @@ static int __maybe_unused snd_acp_resume(struct device *dev)
ret = acp_init(chip);
if (ret)
dev_err(dev, "ACP init failed\n");
- child = chip->chip_pdev->dev;
- adata = dev_get_drvdata(&child);
- if (adata)
- acp_enable_interrupts(adata);
+ if (chip->chip_pdev) {
+ child = chip->chip_pdev->dev;
+ adata = dev_get_drvdata(&child);
+ if (adata)
+ acp_enable_interrupts(adata);
+ }
return ret;
}
@@ -247,6 +248,7 @@ static struct pci_driver snd_amd_acp_pci_driver = {
};
module_pci_driver(snd_amd_acp_pci_driver);
+MODULE_DESCRIPTION("AMD ACP common PCI support");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
index f754bf79b5e3..d4855da05b6a 100644
--- a/sound/soc/amd/acp/acp-pdm.c
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -31,9 +31,11 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream,
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip;
u32 physical_addr, size_dmic, period_bytes;
unsigned int dmic_ctrl;
+ chip = dev_get_platdata(dev);
/* Enable default DMIC clk */
writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
@@ -45,7 +47,10 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream,
size_dmic = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
- physical_addr = stream->reg_offset + MEM_WINDOW_START;
+ if (chip->acp_rev >= ACP70_PCI_ID)
+ physical_addr = ACP7x_DMIC_MEM_WINDOW_START;
+ else
+ physical_addr = stream->reg_offset + MEM_WINDOW_START;
/* Init DMIC Ring buffer */
writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
@@ -176,7 +181,8 @@ const struct snd_soc_dai_ops acp_dmic_dai_ops = {
.startup = acp_dmic_dai_startup,
.shutdown = acp_dmic_dai_shutdown,
};
-EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, "SND_SOC_ACP_COMMON");
+MODULE_DESCRIPTION("AMD ACP Audio PDM controller");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index aaac8aa744cb..aa330aeeb301 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -68,13 +68,53 @@ static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
.periods_max = CAPTURE_MAX_NUM_PERIODS,
};
+static const struct snd_pcm_hardware acp6x_pcm_hardware_playback = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 32,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+ .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+ .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+ .periods_min = PLAYBACK_MIN_NUM_PERIODS,
+ .periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 32,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+ .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+ .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+ .periods_min = CAPTURE_MIN_NUM_PERIODS,
+ .periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
int acp_machine_select(struct acp_dev_data *adata)
{
struct snd_soc_acpi_mach *mach;
int size, platform;
if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
- platform = adata->platform;
+ platform = adata->acp_rev;
adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach",
PLATFORM_DEVID_NONE, &platform,
sizeof(platform));
@@ -85,6 +125,7 @@ int acp_machine_select(struct acp_dev_data *adata)
dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
return -EINVAL;
}
+ mach->mach_params.subsystem_rev = adata->acp_rev;
adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
PLATFORM_DEVID_NONE, mach, size);
}
@@ -92,7 +133,7 @@ int acp_machine_select(struct acp_dev_data *adata)
dev_warn(adata->dev, "Unable to register Machine device\n");
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON");
static irqreturn_t i2s_irq_handler(int irq, void *data)
{
@@ -102,9 +143,6 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
u16 i2s_flag = 0;
u32 ext_intr_stat, ext_intr_stat1;
- if (!adata)
- return IRQ_NONE;
-
if (adata->rsrc->no_of_ctrls == 2)
ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
@@ -137,20 +175,23 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
{
struct acp_resource *rsrc = adata->rsrc;
- u32 pte_reg, pte_size, reg_val;
+ u32 reg_val;
- /* Use ATU base Group5 */
- pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
- pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
+ reg_val = rsrc->sram_pte_offset;
stream->reg_offset = 0x02000000;
- /* Group Enable */
- reg_val = rsrc->sram_pte_offset;
- writel(reg_val | BIT(31), adata->acp_base + pte_reg);
- writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + pte_size);
+ writel((reg_val + GRP1_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+ writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+
+ writel((reg_val + GRP2_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
+ writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
+
+ writel(reg_val | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5);
+ writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5);
+
writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
}
-EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON");
void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size)
{
@@ -161,7 +202,40 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
u32 low, high, val;
u16 page_idx;
- val = stream->pte_offset;
+ switch (adata->acp_rev) {
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ switch (stream->dai_id) {
+ case I2S_SP_INSTANCE:
+ if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ val = 0x0;
+ else
+ val = 0x1000;
+ break;
+ case I2S_BT_INSTANCE:
+ if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ val = 0x2000;
+ else
+ val = 0x3000;
+ break;
+ case I2S_HS_INSTANCE:
+ if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ val = 0x4000;
+ else
+ val = 0x5000;
+ break;
+ case DMIC_INSTANCE:
+ val = 0x6000;
+ break;
+ default:
+ dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id);
+ return;
+ }
+ break;
+ default:
+ val = stream->pte_offset;
+ break;
+ }
for (page_idx = 0; page_idx < num_pages; page_idx++) {
/* Load the low address of page int ACP SRAM through SRBM */
@@ -176,13 +250,14 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
addr += PAGE_SIZE;
}
}
-EXPORT_SYMBOL_NS_GPL(config_acp_dma, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(config_acp_dma, "SND_SOC_ACP_COMMON");
static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct device *dev = component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip;
struct acp_stream *stream;
int ret;
@@ -191,11 +266,37 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
return -ENOMEM;
stream->substream = substream;
+ chip = dev_get_platdata(dev);
+ switch (chip->acp_rev) {
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ runtime->hw = acp6x_pcm_hardware_playback;
+ else
+ runtime->hw = acp6x_pcm_hardware_capture;
+ break;
+ default:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ runtime->hw = acp_pcm_hardware_playback;
+ else
+ runtime->hw = acp_pcm_hardware_capture;
+ break;
+ }
+
+ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE);
+ if (ret) {
+ dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n");
+ kfree(stream);
+ return ret;
+ }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- runtime->hw = acp_pcm_hardware_playback;
- else
- runtime->hw = acp_pcm_hardware_capture;
+ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE);
+ if (ret) {
+ dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n");
+ kfree(stream);
+ return ret;
+ }
ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0) {
@@ -313,7 +414,7 @@ int acp_platform_register(struct device *dev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_platform_register, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON");
int acp_platform_unregister(struct device *dev)
{
@@ -323,7 +424,7 @@ int acp_platform_unregister(struct device *dev)
platform_device_unregister(adata->mach_dev);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON");
MODULE_DESCRIPTION("AMD ACP PCM Driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 158f819f8da4..2648256fa129 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -39,8 +39,6 @@ static struct acp_resource rsrc = {
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
@@ -199,7 +197,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP6X_DEV) {
+ if (chip->acp_rev != ACP_RMB_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -229,14 +227,15 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp_rmb_dai;
adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
adata->rsrc = &rsrc;
- adata->platform = REMBRANDT;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
+ adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
- if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+ if (chip->is_i2s_config && rsrc.soc_mclk) {
ret = acp6x_master_clock_generate(dev);
if (ret)
return ret;
@@ -269,7 +268,7 @@ static int __maybe_unused rmb_pcm_resume(struct device *dev)
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+ if (adata->is_i2s_config && adata->rsrc->soc_mclk)
acp6x_master_clock_generate(dev);
spin_lock(&adata->acp_lock);
@@ -296,7 +295,7 @@ static const struct dev_pm_ops rmb_dma_pm_ops = {
static struct platform_driver rembrandt_driver = {
.probe = rembrandt_audio_probe,
- .remove_new = rembrandt_audio_remove,
+ .remove = rembrandt_audio_remove,
.driver = {
.name = "acp_asoc_rembrandt",
.pm = &rmb_dma_pm_ops,
@@ -306,6 +305,6 @@ static struct platform_driver rembrandt_driver = {
module_platform_driver(rembrandt_driver);
MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index b0e181c9a733..ca2b74283d8f 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -32,8 +32,6 @@ static struct acp_resource rsrc = {
.no_of_ctrls = 1,
.irqp_used = 0,
.irq_reg_offset = 0x1800,
- .i2s_pin_cfg_offset = 0x1400,
- .i2s_mode = 0x04,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x02052800,
};
@@ -159,7 +157,7 @@ static int renoir_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP3X_DEV) {
+ if (chip->acp_rev != ACP_RN_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -187,7 +185,7 @@ static int renoir_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp_renoir_dai;
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
adata->rsrc = &rsrc;
- adata->platform = RENOIR;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
adata->machines = snd_soc_acpi_amd_acp_machines;
@@ -246,7 +244,7 @@ static const struct dev_pm_ops rn_dma_pm_ops = {
static struct platform_driver renoir_driver = {
.probe = renoir_audio_probe,
- .remove_new = renoir_audio_remove,
+ .remove = renoir_audio_remove,
.driver = {
.name = "acp_asoc_renoir",
.pm = &rn_dma_pm_ops,
@@ -256,6 +254,6 @@ static struct platform_driver renoir_driver = {
module_platform_driver(renoir_driver);
MODULE_DESCRIPTION("AMD ACP Renoir Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
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..9280cd30d19c
--- /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,
+ &current_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/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c
new file mode 100644
index 000000000000..6f5c39ed1a18
--- /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
new file mode 100644
index 000000000000..c09b1f118a6c
--- /dev/null
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2024 Advanced Micro Devices, Inc.
+
+/*
+ * acp-sdw-sof-mach - ASoC 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 sof_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(sof_sdw_quirk))
+ dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
+ SOC_JACK_JDSRC(sof_sdw_quirk));
+ if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC)
+ dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
+}
+
+static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
+{
+ sof_sdw_quirk = (unsigned long)id->driver_data;
+ return 1;
+}
+
+static const struct dmi_system_id sof_sdw_quirk_table[] = {
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "AMD"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"),
+ },
+ .driver_data = (void *)RT711_JD2,
+ },
+ {}
+};
+
+static struct snd_soc_dai_link_component platform_component[] = {
+ {
+ /* name might be overridden during probe */
+ .name = "0000:04:00.5",
+ }
+};
+
+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 *sof_dai,
+ struct snd_soc_dai_link **dai_links,
+ int *be_id, 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 asoc_sdw_endpoint *sof_end;
+ int cpu_pin_id;
+ int stream;
+ int ret;
+
+ list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
+ if (sof_end->name_prefix) {
+ (*codec_conf)->dlc.name = sof_end->codec_name;
+ (*codec_conf)->name_prefix = sof_end->name_prefix;
+ (*codec_conf)++;
+ }
+
+ if (sof_end->include_sidecar) {
+ ret = sof_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(sof_dai->link_mask[stream]);
+ int num_codecs = sof_dai->num_devs[stream];
+ int playback, capture;
+ int j = 0;
+ char *name;
+
+ if (!sof_dai->num_devs[stream])
+ continue;
+
+ sof_end = list_first_entry(&sof_dai->endpoints,
+ struct asoc_sdw_endpoint, list);
+
+ *be_id = sof_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(sof_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(sof_end->link_mask) - 1,
+ cpu_pin_id,
+ type_strings[sof_end->dai_info->dai_type]);
+ } else {
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ sdw_stream_name[stream],
+ ffs(sof_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(sof_end, &sof_dai->endpoints, list) {
+ if (!sof_end->dai_info->direction[stream])
+ continue;
+
+ int link_num = ffs(sof_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 = sof_end->codec_name;
+ codecs[j].dai_name = sof_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, platform_component,
+ ARRAY_SIZE(platform_component), codecs, num_codecs,
+ 1, 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(sof_end, &sof_dai->endpoints, list) {
+ if (sof_end->dai_info->init)
+ sof_end->dai_info->init(card, *dai_links,
+ sof_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 *sof_dais,
+ struct snd_soc_codec_conf **codec_conf)
+{
+ int ret;
+
+ /* generate DAI links by each sdw link */
+ while (sof_dais->initialised) {
+ int current_be_id;
+
+ ret = create_sdw_dailink(card, sof_dais, dai_links,
+ &current_be_id, codec_conf);
+ 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;
+
+ sof_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;
+ int ret;
+
+ ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
+ 0, 1, // DMIC only supports capture
+ "acp-sof-dmic", platform_component->name,
+ ARRAY_SIZE(platform_component),
+ "dmic-codec", "dmic-hifi", no_pcm,
+ asoc_sdw_dmic_init, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
+
+ return 0;
+}
+
+static int sof_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 *sof_ends __free(kfree) = NULL;
+ struct asoc_sdw_dailink *sof_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 */
+ sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
+ if (!sof_dais)
+ return -ENOMEM;
+
+ /* One per endpoint, ie. each DAI on each codec/amp */
+ sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
+ if (!sof_ends)
+ return -ENOMEM;
+
+ ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
+ if (ret < 0)
+ return ret;
+
+ sdw_be_num = ret;
+
+ /* enable dmic */
+ if (sof_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,
+ sof_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, 1);
+ 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(sof_sdw_quirk_table);
+
+ if (quirk_override != -1) {
+ dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
+ sof_sdw_quirk, quirk_override);
+ sof_sdw_quirk = quirk_override;
+ }
+
+ log_quirks(card->dev);
+
+ ctx->mc_quirk = sof_sdw_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 = sof_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;
+
+ /* 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_sof_sdw", },
+ {}
+};
+MODULE_DEVICE_TABLE(platform, mc_id_table);
+
+static struct platform_driver sof_sdw_driver = {
+ .driver = {
+ .name = "amd_sof_sdw",
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = mc_probe,
+ .remove = mc_remove,
+ .id_table = mc_id_table,
+};
+
+module_platform_driver(sof_sdw_driver);
+
+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/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index 20b94814a046..d7b54f12f406 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -28,7 +28,6 @@ static struct acp_card_drvdata sof_rt5682_rt1019_data = {
.hs_codec_id = RT5682,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682_max_data = {
@@ -38,7 +37,6 @@ static struct acp_card_drvdata sof_rt5682_max_data = {
.hs_codec_id = RT5682,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
@@ -48,8 +46,6 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_max_data = {
@@ -59,8 +55,6 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_nau8825_data = {
@@ -70,9 +64,7 @@ static struct acp_card_drvdata sof_nau8825_data = {
.hs_codec_id = NAU8825,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
- .platform = REMBRANDT,
.soc_mclk = true,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
@@ -82,28 +74,23 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
- .platform = REMBRANDT,
.soc_mclk = true,
- .tdm_mode = false,
};
static struct acp_card_drvdata sof_nau8821_max98388_data = {
.hs_cpu_id = I2S_SP,
.amp_cpu_id = I2S_HS,
.bt_cpu_id = I2S_BT,
- .dmic_cpu_id = NONE,
.hs_codec_id = NAU8821,
.amp_codec_id = MAX98388,
- .bt_codec_id = NONE,
- .dmic_codec_id = NONE,
.soc_mclk = true,
- .tdm_mode = false,
};
static int acp_sof_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
@@ -126,16 +113,15 @@ static int acp_sof_probe(struct platform_device *pdev)
if (dmi_id && dmi_id->driver_data)
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
- acp_sofdsp_dai_links_create(card);
+ acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev;
+ ret = acp_sofdsp_dai_links_create(card);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to create DAI links\n");
ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret) {
- dev_err(&pdev->dev,
- "devm_snd_soc_register_card(%s) failed: %d\n",
- card->name, ret);
- return ret;
- }
-
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to register card(%s)\n", card->name);
return 0;
}
@@ -170,6 +156,8 @@ static const struct platform_device_id board_ids[] = {
},
{ }
};
+MODULE_DEVICE_TABLE(platform, board_ids);
+
static struct platform_driver acp_asoc_audio = {
.driver = {
.name = "sof_mach",
@@ -181,13 +169,6 @@ static struct platform_driver acp_asoc_audio = {
module_platform_driver(acp_asoc_audio);
-MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
-MODULE_DESCRIPTION("ACP chrome SOF audio support");
-MODULE_ALIAS("platform:rt5682-rt1019");
-MODULE_ALIAS("platform:rt5682-max");
-MODULE_ALIAS("platform:rt5682s-max");
-MODULE_ALIAS("platform:rt5682s-rt1019");
-MODULE_ALIAS("platform:nau8825-max");
-MODULE_ALIAS("platform:rt5682s-hs-rt1019");
-MODULE_ALIAS("platform:nau8821-max");
+MODULE_IMPORT_NS("SND_SOC_AMD_MACH");
+MODULE_DESCRIPTION("ACP SOF Machine Driver");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index 4d342441a650..81496e713440 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -55,8 +55,6 @@ static struct acp_resource rsrc = {
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
@@ -209,7 +207,7 @@ static int acp63_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP63_DEV) {
+ if (chip->acp_rev != ACP63_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -239,13 +237,14 @@ static int acp63_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp63_dai;
adata->num_dai = ARRAY_SIZE(acp63_dai);
adata->rsrc = &rsrc;
- adata->platform = ACP63;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
+ adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
- if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+ if (chip->is_i2s_config && rsrc.soc_mclk) {
ret = acp63_i2s_master_clock_generate(adata);
if (ret)
return ret;
@@ -278,7 +277,7 @@ static int __maybe_unused acp63_pcm_resume(struct device *dev)
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+ if (adata->is_i2s_config && adata->rsrc->soc_mclk)
acp63_i2s_master_clock_generate(adata);
spin_lock(&adata->acp_lock);
@@ -305,7 +304,7 @@ static const struct dev_pm_ops acp63_dma_pm_ops = {
static struct platform_driver acp63_driver = {
.probe = acp63_audio_probe,
- .remove_new = acp63_audio_remove,
+ .remove = acp63_audio_remove,
.driver = {
.name = "acp_asoc_acp63",
.pm = &acp63_dma_pm_ops,
@@ -315,6 +314,6 @@ static struct platform_driver acp63_driver = {
module_platform_driver(acp63_driver);
MODULE_DESCRIPTION("AMD ACP acp63 Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 0d7cdd4017e5..9e23729fd1a7 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -25,16 +25,17 @@
#define DRV_NAME "acp_asoc_acp70"
+#define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4
+#define CLK0_DIVIDER 0X19
+
static struct acp_resource rsrc = {
.offset = 0,
.no_of_ctrls = 2,
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
- .scratch_reg_offset = 0x12800,
- .sram_pte_offset = 0x03802800,
+ .scratch_reg_offset = 0x10000,
+ .sram_pte_offset = 0x03800000,
};
static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = {
@@ -51,23 +52,23 @@ static struct snd_soc_dai_driver acp70_dai[] = {
.id = I2S_SP_INSTANCE,
.playback = {
.stream_name = "I2S SP Playback",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "I2S SP Capture",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.ops = &asoc_acp_cpu_dai_ops,
},
@@ -76,23 +77,23 @@ static struct snd_soc_dai_driver acp70_dai[] = {
.id = I2S_BT_INSTANCE,
.playback = {
.stream_name = "I2S BT Playback",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "I2S BT Capture",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.ops = &asoc_acp_cpu_dai_ops,
},
@@ -101,23 +102,23 @@ static struct snd_soc_dai_driver acp70_dai[] = {
.id = I2S_HS_INSTANCE,
.playback = {
.stream_name = "I2S HS Playback",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "I2S HS Capture",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.ops = &asoc_acp_cpu_dai_ops,
},
@@ -136,12 +137,36 @@ static struct snd_soc_dai_driver acp70_dai[] = {
},
};
+static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata)
+{
+ struct pci_dev *smn_dev;
+ u32 device_id;
+
+ if (adata->acp_rev == ACP70_PCI_ID)
+ device_id = 0x1507;
+ else if (adata->acp_rev == ACP71_PCI_ID)
+ device_id = 0x1122;
+ else
+ return -ENODEV;
+
+ smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL);
+
+ if (!smn_dev)
+ return -ENODEV;
+
+ /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/
+ smn_write(smn_dev, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER);
+
+ return 0;
+}
+
static int acp_acp70_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
struct acp_dev_data *adata;
struct resource *res;
+ int ret;
chip = dev_get_platdata(&pdev->dev);
if (!chip || !chip->base) {
@@ -149,7 +174,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP70_DEV) {
+ switch (chip->acp_rev) {
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ break;
+ default:
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -180,11 +209,17 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
adata->num_dai = ARRAY_SIZE(acp70_dai);
adata->rsrc = &rsrc;
adata->machines = snd_soc_acpi_amd_acp70_acp_machines;
- adata->platform = ACP70;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
+
+ ret = acp70_i2s_master_clock_generate(adata);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n");
+ return ret;
+ }
acp_enable_interrupts(adata);
acp_platform_register(dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
@@ -239,7 +274,7 @@ static const struct dev_pm_ops acp70_dma_pm_ops = {
static struct platform_driver acp70_driver = {
.probe = acp_acp70_audio_probe,
- .remove_new = acp_acp70_audio_remove,
+ .remove = acp_acp70_audio_remove,
.driver = {
.name = "acp_asoc_acp70",
.pm = &acp70_dma_pm_ops,
@@ -249,6 +284,6 @@ static struct platform_driver acp70_driver = {
module_platform_driver(acp70_driver);
MODULE_DESCRIPTION("AMD ACP ACP70 Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp_common.h b/sound/soc/amd/acp/acp_common.h
new file mode 100644
index 000000000000..f1ae88013f62
--- /dev/null
+++ b/sound/soc/amd/acp/acp_common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved
+ */
+
+/*
+ * acp_common.h - acp common header file
+ */
+
+#ifndef __ACP_COMMON_H
+#define __ACP_COMMON_H
+
+#define ACP_RN_PCI_ID 0x01
+#define ACP_VANGOGH_PCI_ID 0x50
+#define ACP_RMB_PCI_ID 0x6F
+#define ACP63_PCI_ID 0x63
+#define ACP70_PCI_ID 0x70
+#define ACP71_PCI_ID 0x71
+
+#endif
diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c
new file mode 100644
index 000000000000..9b6a49c051cd
--- /dev/null
+++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * amd-acp63-acpi-match.c - tables and support for ACP 6.3 platform
+ * ACPI enumeration.
+ *
+ * Copyright 2024 Advanced Micro Devices, Inc.
+ */
+
+#include <sound/soc-acpi.h>
+#include "../mach-config.h"
+
+static const struct snd_soc_acpi_endpoint single_endpoint = {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0
+};
+
+static const struct snd_soc_acpi_endpoint spk_l_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1
+};
+
+static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1
+};
+
+static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = {
+ {
+ .adr = 0x000030025D071101ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt711"
+ },
+ {
+ .adr = 0x000030025D131601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "rt1316-1"
+ },
+ {
+ .adr = 0x000032025D131601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "rt1316-2"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt714_adr[] = {
+ {
+ .adr = 0x130025d071401ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt714"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = {
+ { .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_rt1316_group_adr),
+ .adr_d = rt711_rt1316_group_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt714_adr),
+ .adr_d = rt714_adr,
+ },
+ {}
+};
+
+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),
+ .links = acp63_4_in_1_sdca,
+ .drv_name = "amd_sof_sdw",
+ .sof_tplg_filename = "sof-acp_6_3-rt711-l0-rt1316-l0-rt714-l1.tplg",
+ .fw_filename = "sof-acp_6_3.ri",
+ },
+ {},
+};
+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",
+ },
+ {
+ .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);
+
+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/acp/amd-sdw-acpi.c b/sound/soc/amd/acp/amd-sdw-acpi.c
new file mode 100644
index 000000000000..238b584887ee
--- /dev/null
+++ b/sound/soc/amd/acp/amd-sdw-acpi.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2023 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+
+/*
+ * SDW AMD ACPI scan helper function
+ */
+
+#include <linux/acpi.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/fwnode.h>
+#include <linux/module.h>
+#include <linux/soundwire/sdw_amd.h>
+#include <linux/string.h>
+
+int amd_sdw_scan_controller(struct sdw_amd_acpi_info *info)
+{
+ struct acpi_device *adev = acpi_fetch_acpi_dev(info->handle);
+ u32 sdw_bitmap = 0;
+ u8 count = 0;
+ int ret;
+
+ if (!adev)
+ return -EINVAL;
+
+ /* Found controller, find links supported */
+ ret = fwnode_property_read_u32_array(acpi_fwnode_handle(adev),
+ "mipi-sdw-manager-list", &sdw_bitmap, 1);
+ if (ret) {
+ dev_err(&adev->dev,
+ "Failed to read mipi-sdw-manager-list: %d\n", ret);
+ return -EINVAL;
+ }
+ count = hweight32(sdw_bitmap);
+ /* Check count is within bounds */
+ if (count > info->count) {
+ dev_err(&adev->dev, "Manager count %d exceeds max %d\n",
+ count, info->count);
+ return -EINVAL;
+ }
+
+ if (!count) {
+ dev_dbg(&adev->dev, "No SoundWire Managers detected\n");
+ return -EINVAL;
+ }
+ dev_dbg(&adev->dev, "ACPI reports %d SoundWire Manager devices\n", count);
+ info->link_mask = sdw_bitmap;
+ return 0;
+}
+EXPORT_SYMBOL_NS(amd_sdw_scan_controller, "SND_AMD_SOUNDWIRE_ACPI");
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("AMD SoundWire ACPI helpers");
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 5017e868f39b..ee69dfb10cb8 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -16,13 +16,9 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dai.h>
+#include "acp_common.h"
#include "chip_offset_byte.h"
-#define ACP3X_DEV 3
-#define ACP6X_DEV 6
-#define ACP63_DEV 0x63
-#define ACP70_DEV 0x70
-
#define DMIC_INSTANCE 0x00
#define I2S_SP_INSTANCE 0x01
#define I2S_BT_INSTANCE 0x02
@@ -61,6 +57,14 @@
#define I2S_HS_TX_MEM_WINDOW_START 0x40A0000
#define I2S_HS_RX_MEM_WINDOW_START 0x40C0000
+#define ACP7x_I2S_SP_TX_MEM_WINDOW_START 0x4000000
+#define ACP7x_I2S_SP_RX_MEM_WINDOW_START 0x4200000
+#define ACP7x_I2S_BT_TX_MEM_WINDOW_START 0x4400000
+#define ACP7x_I2S_BT_RX_MEM_WINDOW_START 0x4600000
+#define ACP7x_I2S_HS_TX_MEM_WINDOW_START 0x4800000
+#define ACP7x_I2S_HS_RX_MEM_WINDOW_START 0x4A00000
+#define ACP7x_DMIC_MEM_WINDOW_START 0x4C00000
+
#define SP_PB_FIFO_ADDR_OFFSET 0x500
#define SP_CAPT_FIFO_ADDR_OFFSET 0x700
#define BT_PB_FIFO_ADDR_OFFSET 0x900
@@ -103,6 +107,8 @@
#define ACP70_PGFSM_CONTROL ACP6X_PGFSM_CONTROL
#define ACP70_PGFSM_STATUS ACP6X_PGFSM_STATUS
+#define ACP_ZSC_DSP_CTRL 0x0001014
+#define ACP_ZSC_STS 0x0001018
#define ACP_SOFT_RST_DONE_MASK 0x00010001
#define ACP_PGFSM_CNTL_POWER_ON_MASK 0xffffffff
@@ -138,6 +144,9 @@ struct acp_chip_info {
void __iomem *base; /* ACP memory PCI base */
struct platform_device *chip_pdev;
unsigned int flag; /* Distinguish b/w Legacy or Only PDM */
+ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */
+ bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */
+ bool is_i2s_config; /* flag set to true when I2S configuration is selected from BIOS */
};
struct acp_stream {
@@ -159,8 +168,6 @@ struct acp_resource {
int irqp_used;
bool soc_mclk;
u32 irq_reg_offset;
- u32 i2s_pin_cfg_offset;
- int i2s_mode;
u64 scratch_reg_offset;
u64 sram_pte_offset;
};
@@ -170,8 +177,10 @@ struct acp_dev_data {
struct device *dev;
void __iomem *acp_base;
unsigned int i2s_irq;
+ unsigned int acp_rev; /* ACP Revision id */
bool tdm_mode;
+ bool is_i2s_config;
/* SOC specific dais */
struct snd_soc_dai_driver *dai_driver;
int num_dai;
@@ -192,7 +201,6 @@ struct acp_dev_data {
u32 xfer_tx_resolution[3];
u32 xfer_rx_resolution[3];
unsigned int flag;
- unsigned int platform;
};
enum acp_config {
@@ -212,6 +220,11 @@ enum acp_config {
ACP_CONFIG_13,
ACP_CONFIG_14,
ACP_CONFIG_15,
+ ACP_CONFIG_16,
+ ACP_CONFIG_17,
+ ACP_CONFIG_18,
+ ACP_CONFIG_19,
+ ACP_CONFIG_20,
};
extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
@@ -240,7 +253,7 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
int restore_acp_i2s_params(struct snd_pcm_substream *substream,
struct acp_dev_data *adata, struct acp_stream *stream);
-int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip);
+void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip);
static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
{
@@ -249,12 +262,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
switch (dai_id) {
case I2S_BT_INSTANCE:
- high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+ high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata));
+ low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata));
break;
case I2S_SP_INSTANCE:
- high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
+ high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata));
+ low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata));
break;
case I2S_HS_INSTANCE:
high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
@@ -267,12 +280,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
} else {
switch (dai_id) {
case I2S_BT_INSTANCE:
- high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+ high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata));
+ low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata));
break;
case I2S_SP_INSTANCE:
- high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
+ high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata));
+ low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata));
break;
case I2S_HS_INSTANCE:
high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index cfd6c4d07594..117ea63e85c6 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -12,14 +12,22 @@
#define _ACP_IP_OFFSET_HEADER
#define ACPAXI2AXI_ATU_CTRL 0xC40
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0xC00
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0xC04
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0xC08
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0xC0C
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0xC20
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0xC24
+#define GRP1_OFFSET 0x0
+#define GRP2_OFFSET 0x4000
+
#define ACP_PGFSM_CONTROL 0x141C
#define ACP_PGFSM_STATUS 0x1420
#define ACP_SOFT_RESET 0x1000
#define ACP_CONTROL 0x1004
#define ACP_PIN_CONFIG 0x1440
+#define ACP3X_PIN_CONFIG 0x1400
#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
(adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
@@ -31,42 +39,47 @@
/* Registers from ACP_AUDIO_BUFFERS block */
-#define ACP_I2S_RX_RINGBUFADDR 0x2000
-#define ACP_I2S_RX_RINGBUFSIZE 0x2004
-#define ACP_I2S_RX_LINKPOSITIONCNTR 0x2008
-#define ACP_I2S_RX_FIFOADDR 0x200C
-#define ACP_I2S_RX_FIFOSIZE 0x2010
-#define ACP_I2S_RX_DMA_SIZE 0x2014
-#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x2018
-#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x201C
-#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x2020
-#define ACP_I2S_TX_RINGBUFADDR 0x2024
-#define ACP_I2S_TX_RINGBUFSIZE 0x2028
-#define ACP_I2S_TX_LINKPOSITIONCNTR 0x202C
-#define ACP_I2S_TX_FIFOADDR 0x2030
-#define ACP_I2S_TX_FIFOSIZE 0x2034
-#define ACP_I2S_TX_DMA_SIZE 0x2038
-#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x203C
-#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x2040
-#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x2044
-#define ACP_BT_RX_RINGBUFADDR 0x2048
-#define ACP_BT_RX_RINGBUFSIZE 0x204C
-#define ACP_BT_RX_LINKPOSITIONCNTR 0x2050
-#define ACP_BT_RX_FIFOADDR 0x2054
-#define ACP_BT_RX_FIFOSIZE 0x2058
-#define ACP_BT_RX_DMA_SIZE 0x205C
-#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x2060
-#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x2064
-#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x2068
-#define ACP_BT_TX_RINGBUFADDR 0x206C
-#define ACP_BT_TX_RINGBUFSIZE 0x2070
-#define ACP_BT_TX_LINKPOSITIONCNTR 0x2074
-#define ACP_BT_TX_FIFOADDR 0x2078
-#define ACP_BT_TX_FIFOSIZE 0x207C
-#define ACP_BT_TX_DMA_SIZE 0x2080
-#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x2084
-#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x2088
-#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x208C
+#define ACP_I2S_REG_ADDR(acp_adata, addr) \
+ ((addr) + (acp_adata->rsrc->irqp_used * \
+ acp_adata->rsrc->irq_reg_offset))
+
+#define ACP_I2S_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2000)
+#define ACP_I2S_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2004)
+#define ACP_I2S_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2008)
+#define ACP_I2S_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x200C)
+#define ACP_I2S_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2010)
+#define ACP_I2S_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2014)
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2018)
+#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x201C)
+#define ACP_I2S_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2020)
+#define ACP_I2S_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2024)
+#define ACP_I2S_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2028)
+#define ACP_I2S_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x202C)
+#define ACP_I2S_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2030)
+#define ACP_I2S_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2034)
+#define ACP_I2S_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2038)
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x203C)
+#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2040)
+#define ACP_I2S_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2044)
+#define ACP_BT_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2048)
+#define ACP_BT_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x204C)
+#define ACP_BT_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2050)
+#define ACP_BT_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2054)
+#define ACP_BT_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2058)
+#define ACP_BT_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x205C)
+#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2060)
+#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2064)
+#define ACP_BT_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2068)
+#define ACP_BT_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x206C)
+#define ACP_BT_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2070)
+#define ACP_BT_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2074)
+#define ACP_BT_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2078)
+#define ACP_BT_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x207C)
+#define ACP_BT_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2080)
+#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2084)
+#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2088)
+#define ACP_BT_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x208C)
+
#define ACP_HS_RX_RINGBUFADDR 0x3A90
#define ACP_HS_RX_RINGBUFSIZE 0x3A94
#define ACP_HS_RX_LINKPOSITIONCNTR 0x3A98
diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h
new file mode 100644
index 000000000000..b7bae107c13e
--- /dev/null
+++ b/sound/soc/amd/acp/soc_amd_sdw_common.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved
+ */
+
+/*
+ * soc_amd_sdw_common.h - prototypes for common helpers
+ */
+
+#ifndef SOC_AMD_SDW_COMMON_H
+#define SOC_AMD_SDW_COMMON_H
+
+#include <linux/bits.h>
+#include <linux/types.h>
+#include <sound/soc.h>
+#include <sound/soc_sdw_utils.h>
+
+#define ACP63_SDW_MAX_CPU_DAIS 8
+#define ACP63_SDW_MAX_LINKS 2
+
+#define AMD_SDW_MAX_GROUPS 9
+#define ACP63_PCI_REV 0x63
+#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
+#define ASOC_SDW_FOUR_SPK BIT(4)
+#define ASOC_SDW_ACP_DMIC BIT(5)
+
+#define AMD_SDW0 0
+#define AMD_SDW1 1
+#define ACP63_SW0_AUDIO0_TX 0
+#define ACP63_SW0_AUDIO1_TX 1
+#define ACP63_SW0_AUDIO2_TX 2
+
+#define ACP63_SW0_AUDIO0_RX 3
+#define ACP63_SW0_AUDIO1_RX 4
+#define ACP63_SW0_AUDIO2_RX 5
+
+#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;
+};
+
+int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev);
+
+#endif
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index d6cdb6d9fdd6..4ca1978020a9 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -143,7 +143,7 @@ static int rt5682_clk_enable(struct snd_pcm_substream *substream)
static int acp3x_1015_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
int srate, i, ret;
@@ -317,8 +317,6 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = acp3x_5682_init,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp3x_5682_ops,
SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform),
},
@@ -327,7 +325,7 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &acp3x_max_play_ops,
.cpus = acp3x_bt,
.num_cpus = ARRAY_SIZE(acp3x_bt),
@@ -339,7 +337,7 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.stream_name = "Capture DMIC0",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &acp3x_ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h
index 7af0f9cf3921..a86c76f781f9 100644
--- a/sound/soc/amd/mach-config.h
+++ b/sound/soc/amd/mach-config.h
@@ -23,6 +23,9 @@ 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[];
struct config_entry {
u32 flags;
diff --git a/sound/soc/amd/ps/Makefile b/sound/soc/amd/ps/Makefile
index f2a5eaf2fa4d..b5efb1c5382c 100644
--- a/sound/soc/amd/ps/Makefile
+++ b/sound/soc/amd/ps/Makefile
@@ -1,9 +1,9 @@
-# SPDX-License-Identifier: GPL-2.0+
+# SPDX-License-Identifier: GPL-2.0-only
# Pink Sardine platform Support
-snd-pci-ps-objs := pci-ps.o
-snd-ps-pdm-dma-objs := ps-pdm-dma.o
-snd-soc-ps-mach-objs := ps-mach.o
-snd-ps-sdw-dma-objs := ps-sdw-dma.o
+snd-pci-ps-y := pci-ps.o
+snd-ps-pdm-dma-y := ps-pdm-dma.o
+snd-soc-ps-mach-y := ps-mach.o
+snd-ps-sdw-dma-y := ps-sdw-dma.o
obj-$(CONFIG_SND_SOC_AMD_PS) += snd-pci-ps.o
obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-pdm-dma.o
diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h
index 8b853b8d0219..e54eabaa4d3e 100644
--- a/sound/soc/amd/ps/acp63.h
+++ b/sound/soc/amd/ps/acp63.h
@@ -5,12 +5,12 @@
* Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. All rights reserved.
*/
+#include <linux/soundwire/sdw_amd.h>
#include <sound/acp63_chip_offset_byte.h>
#define ACP_DEVICE_ID 0x15E2
#define ACP63_REG_START 0x1240000
-#define ACP63_REG_END 0x1250200
-#define ACP63_DEVS 5
+#define ACP63_REG_END 0x125C000
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
#define ACP_PGFSM_CNTL_POWER_ON_MASK 1
@@ -55,32 +55,6 @@
#define ACP_DMIC_DEV 2
-/* ACP63_PDM_MODE_DEVS corresponds to platform devices count for ACP PDM configuration */
-#define ACP63_PDM_MODE_DEVS 3
-
-/*
- * ACP63_SDW0_MODE_DEVS corresponds to platform devices count for
- * SW0 SoundWire manager instance configuration
- */
-#define ACP63_SDW0_MODE_DEVS 2
-
-/*
- * ACP63_SDW0_SDW1_MODE_DEVS corresponds to platform devices count for SW0 + SW1 SoundWire manager
- * instances configuration
- */
-#define ACP63_SDW0_SDW1_MODE_DEVS 3
-
-/*
- * ACP63_SDW0_PDM_MODE_DEVS corresponds to platform devices count for SW0 manager
- * instance + ACP PDM controller configuration
- */
-#define ACP63_SDW0_PDM_MODE_DEVS 4
-
-/*
- * ACP63_SDW0_SDW1_PDM_MODE_DEVS corresponds to platform devices count for
- * SW0 + SW1 SoundWire manager instances + ACP PDM controller configuration
- */
-#define ACP63_SDW0_SDW1_PDM_MODE_DEVS 5
#define ACP63_DMIC_ADDR 2
#define ACP63_SDW_ADDR 5
#define AMD_SDW_MAX_MANAGERS 2
@@ -88,17 +62,6 @@
/* time in ms for acp timeout */
#define ACP_TIMEOUT 500
-/* ACP63_PDM_DEV_CONFIG corresponds to platform device configuration for ACP PDM controller */
-#define ACP63_PDM_DEV_CONFIG BIT(0)
-
-/* ACP63_SDW_DEV_CONFIG corresponds to platform device configuration for SDW manager instances */
-#define ACP63_SDW_DEV_CONFIG BIT(1)
-
-/*
- * ACP63_SDW_PDM_DEV_CONFIG corresponds to platform device configuration for ACP PDM + SoundWire
- * manager instance combination.
- */
-#define ACP63_SDW_PDM_DEV_CONFIG GENMASK(1, 0)
#define ACP_SDW0_STAT BIT(21)
#define ACP_SDW1_STAT BIT(2)
#define ACP_ERROR_IRQ BIT(29)
@@ -253,38 +216,48 @@ struct sdw_dma_ring_buf_reg {
* struct acp63_dev_data - acp pci driver context
* @acp63_base: acp mmio base
* @res: resource
- * @pdev: array of child platform device node structures
+ * @pdm_dev: ACP PDM controller platform device
+ * @dmic_codec: platform device for DMIC Codec
+ * sdw_dma_dev: platform device for SoundWire DMA controller
+ * @mach_dev: platform device for machine driver to support ACP PDM/SoundWire configuration
* @acp_lock: used to protect acp common registers
- * @sdw_fw_node: SoundWire controller fw node handle
- * @pdev_config: platform device configuration
- * @pdev_count: platform devices count
- * @pdm_dev_index: pdm platform device index
- * @sdw_manager_count: SoundWire manager instance count
- * @sdw0_dev_index: SoundWire Manager-0 platform device index
- * @sdw1_dev_index: SoundWire Manager-1 platform device index
- * @sdw_dma_dev_index: SoundWire DMA controller platform device index
+ * @info: SoundWire AMD information found in ACPI tables
+ * @sdw: SoundWire context for all SoundWire manager instances
+ * @machine: ACPI machines for SoundWire interface
+ * @is_sdw_dev: flag set to true when any SoundWire manager instances are available
+ * @is_pdm_dev: flag set to true when ACP PDM controller exists
+ * @is_pdm_config: flat set to true when PDM configuration is selected from BIOS
+ * @is_sdw_config: flag set to true when SDW configuration is selected from BIOS
+ * @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled
+ * @addr: pci ioremap address
+ * @reg_range: ACP reigister range
+ * @acp_rev: ACP PCI revision id
* @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance
* @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance
- * @acp_reset: flag set to true when bus reset is applied across all
- * the active SoundWire manager instances
*/
struct acp63_dev_data {
void __iomem *acp63_base;
struct resource *res;
- struct platform_device *pdev[ACP63_DEVS];
+ struct platform_device *pdm_dev;
+ struct platform_device *dmic_codec_dev;
+ struct platform_device *sdw_dma_dev;
+ struct platform_device *mach_dev;
struct mutex acp_lock; /* protect shared registers */
- struct fwnode_handle *sdw_fw_node;
- u16 pdev_config;
- u16 pdev_count;
- u16 pdm_dev_index;
- u8 sdw_manager_count;
- u16 sdw0_dev_index;
- u16 sdw1_dev_index;
- u16 sdw_dma_dev_index;
+ struct sdw_amd_acpi_info info;
+ /* sdw context allocated by SoundWire driver */
+ struct sdw_amd_ctx *sdw;
+ struct snd_soc_acpi_mach *machines;
+ bool is_sdw_dev;
+ bool is_pdm_dev;
+ bool is_pdm_config;
+ bool is_sdw_config;
+ bool sdw_en_stat;
+ u32 addr;
+ u32 reg_range;
+ u32 acp_rev;
u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
- bool acp_reset;
};
int snd_amd_acp_find_config(struct pci_dev *pci);
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index 5927eef04170..8b556950b855 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD Pink Sardine ACP PCI Driver
*
@@ -17,6 +17,7 @@
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
#include <linux/soundwire/sdw_amd.h>
+#include "../mach-config.h"
#include "acp63.h"
@@ -82,6 +83,7 @@ static int acp63_init(void __iomem *acp_base, struct device *dev)
return ret;
}
acp63_enable_interrupts(acp_base);
+ writel(0, acp_base + ACP_ZSC_DSP_CTRL);
return 0;
}
@@ -96,6 +98,7 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev)
return ret;
}
writel(0, acp_base + ACP_CONTROL);
+ writel(1, acp_base + ACP_ZSC_DSP_CTRL);
return 0;
}
@@ -104,10 +107,8 @@ static irqreturn_t acp63_irq_thread(int irq, void *context)
struct sdw_dma_dev_data *sdw_dma_data;
struct acp63_dev_data *adata = context;
u32 stream_index;
- u16 pdev_index;
- pdev_index = adata->sdw_dma_dev_index;
- sdw_dma_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ sdw_dma_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
for (stream_index = 0; stream_index < ACP63_SDW0_DMA_MAX_STREAMS; stream_index++) {
if (adata->sdw0_dma_intr_stat[stream_index]) {
@@ -135,7 +136,6 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
u32 stream_id = 0;
u16 irq_flag = 0;
u16 sdw_dma_irq_flag = 0;
- u16 pdev_index;
u16 index;
adata = dev_id;
@@ -149,8 +149,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
ext_intr_stat = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (ext_intr_stat & ACP_SDW0_STAT) {
writel(ACP_SDW0_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
- pdev_index = adata->sdw0_dev_index;
- amd_manager = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
if (amd_manager)
schedule_work(&amd_manager->amd_sdw_irq_thread);
irq_flag = 1;
@@ -159,8 +158,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
if (ext_intr_stat1 & ACP_SDW1_STAT) {
writel(ACP_SDW1_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
- pdev_index = adata->sdw1_dev_index;
- amd_manager = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
if (amd_manager)
schedule_work(&amd_manager->amd_sdw_irq_thread);
irq_flag = 1;
@@ -176,8 +174,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
}
if (ext_intr_stat & BIT(PDM_DMA_STAT)) {
- pdev_index = adata->pdm_dev_index;
- ps_pdm_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
+ ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev);
writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (ps_pdm_data->capture_stream)
snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
@@ -237,122 +234,173 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
-static int sdw_amd_scan_controller(struct device *dev)
+#if IS_ENABLED(CONFIG_SND_SOC_AMD_SOUNDWIRE)
+static int acp_scan_sdw_devices(struct device *dev, u64 addr)
{
+ struct acpi_device *sdw_dev;
struct acp63_dev_data *acp_data;
- struct fwnode_handle *link;
- char name[32];
- u32 sdw_manager_bitmap;
- u8 count = 0;
- u32 acp_sdw_power_mode = 0;
- int index;
+
+ acp_data = dev_get_drvdata(dev);
+ if (!addr)
+ return -ENODEV;
+
+ sdw_dev = acpi_find_child_device(ACPI_COMPANION(dev), addr, 0);
+ if (!sdw_dev)
+ return -ENODEV;
+
+ acp_data->info.handle = sdw_dev->handle;
+ acp_data->info.count = AMD_SDW_MAX_MANAGERS;
+ return amd_sdw_scan_controller(&acp_data->info);
+}
+
+static int amd_sdw_probe(struct device *dev)
+{
+ struct acp63_dev_data *acp_data;
+ struct sdw_amd_res sdw_res;
int ret;
acp_data = dev_get_drvdata(dev);
- /*
- * Current implementation is based on MIPI DisCo 2.0 spec.
- * Found controller, find links supported.
- */
- ret = fwnode_property_read_u32_array((acp_data->sdw_fw_node), "mipi-sdw-manager-list",
- &sdw_manager_bitmap, 1);
+ memset(&sdw_res, 0, sizeof(sdw_res));
+ sdw_res.addr = acp_data->addr;
+ sdw_res.reg_range = acp_data->reg_range;
+ sdw_res.handle = acp_data->info.handle;
+ sdw_res.parent = dev;
+ sdw_res.dev = dev;
+ sdw_res.acp_lock = &acp_data->acp_lock;
+ sdw_res.count = acp_data->info.count;
+ sdw_res.mmio_base = acp_data->acp63_base;
+ sdw_res.acp_rev = acp_data->acp_rev;
+ sdw_res.link_mask = acp_data->info.link_mask;
+ ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
+ if (ret)
+ dev_err(dev, "error: SoundWire probe failed\n");
+ return ret;
+}
- if (ret) {
- dev_dbg(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
- return -EINVAL;
- }
- count = hweight32(sdw_manager_bitmap);
- /* Check count is within bounds */
- if (count > AMD_SDW_MAX_MANAGERS) {
- dev_err(dev, "Manager count %d exceeds max %d\n", count, AMD_SDW_MAX_MANAGERS);
- return -EINVAL;
- }
-
- if (!count) {
- dev_dbg(dev, "No SoundWire Managers detected\n");
- return -EINVAL;
- }
- dev_dbg(dev, "ACPI reports %d SoundWire Manager devices\n", count);
- acp_data->sdw_manager_count = count;
- for (index = 0; index < count; index++) {
- scnprintf(name, sizeof(name), "mipi-sdw-link-%d-subproperties", index);
- link = fwnode_get_named_child_node(acp_data->sdw_fw_node, name);
- if (!link) {
- dev_err(dev, "Manager node %s not found\n", name);
- return -EIO;
+static int amd_sdw_exit(struct acp63_dev_data *acp_data)
+{
+ if (acp_data->sdw)
+ sdw_amd_exit(acp_data->sdw);
+ acp_data->sdw = NULL;
+
+ return 0;
+}
+
+static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
+{
+ struct snd_soc_acpi_mach *mach;
+ const struct snd_soc_acpi_link_adr *link;
+ struct acp63_dev_data *acp_data = dev_get_drvdata(dev);
+ int ret, i;
+
+ if (acp_data->info.count) {
+ ret = sdw_amd_get_slave_info(acp_data->sdw);
+ if (ret) {
+ dev_dbg(dev, "failed to read slave information\n");
+ return NULL;
+ }
+ for (mach = acp_data->machines; mach; mach++) {
+ if (!mach->links)
+ break;
+ link = mach->links;
+ for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
+ if (!snd_soc_acpi_sdw_link_slaves_found(dev, link,
+ acp_data->sdw->peripherals))
+ break;
+ }
+ if (i == acp_data->info.count || !link->num_adr)
+ break;
}
+ if (mach && mach->link_mask) {
+ mach->mach_params.links = mach->links;
+ mach->mach_params.link_mask = mach->link_mask;
+ mach->mach_params.subsystem_rev = acp_data->acp_rev;
+ return mach;
+ }
+ }
+ dev_dbg(dev, "No SoundWire machine driver found\n");
+ return NULL;
+}
+#else
+static int acp_scan_sdw_devices(struct device *dev, u64 addr)
+{
+ return 0;
+}
- ret = fwnode_property_read_u32(link, "amd-sdw-power-mode", &acp_sdw_power_mode);
- if (ret)
- return ret;
- /*
- * when SoundWire configuration is selected from acp pin config,
- * based on manager instances count, acp init/de-init sequence should be
- * executed as part of PM ops only when Bus reset is applied for the active
- * SoundWire manager instances.
- */
- if (acp_sdw_power_mode != AMD_SDW_POWER_OFF_MODE) {
- acp_data->acp_reset = false;
- return 0;
+static int amd_sdw_probe(struct device *dev)
+{
+ return 0;
+}
+
+static int amd_sdw_exit(struct acp63_dev_data *acp_data)
+{
+ return 0;
+}
+
+static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
+{
+ return NULL;
+}
+#endif
+
+static int acp63_machine_register(struct device *dev)
+{
+ struct snd_soc_acpi_mach *mach;
+ struct acp63_dev_data *adata = dev_get_drvdata(dev);
+ int size;
+
+ if (adata->is_sdw_dev && adata->is_sdw_config) {
+ size = sizeof(*adata->machines);
+ mach = acp63_sdw_machine_select(dev);
+ if (mach) {
+ adata->mach_dev = platform_device_register_data(dev, mach->drv_name,
+ PLATFORM_DEVID_NONE, mach,
+ size);
+ if (IS_ERR(adata->mach_dev)) {
+ dev_err(dev,
+ "cannot register Machine device for SoundWire Interface\n");
+ return PTR_ERR(adata->mach_dev);
+ }
+ }
+
+ } else if (adata->is_pdm_dev && !adata->is_sdw_dev && adata->is_pdm_config) {
+ adata->mach_dev = platform_device_register_data(dev, "acp_ps_mach",
+ PLATFORM_DEVID_NONE, NULL, 0);
+ if (IS_ERR(adata->mach_dev)) {
+ dev_err(dev, "cannot register amd_ps_mach device\n");
+ return PTR_ERR(adata->mach_dev);
}
}
return 0;
}
-static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63_dev_data *acp_data)
+static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
{
- struct acpi_device *dmic_dev;
- struct acpi_device *sdw_dev;
+ struct acpi_device *pdm_dev;
const union acpi_object *obj;
+ acpi_handle handle;
+ acpi_integer dmic_status;
+ u32 config;
bool is_dmic_dev = false;
bool is_sdw_dev = false;
+ bool wov_en, dmic_en;
int ret;
- dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
- if (dmic_dev) {
- /* is_dmic_dev flag will be set when ACP PDM controller device exists */
- if (!acpi_dev_get_property(dmic_dev, "acp-audio-device-type",
- ACPI_TYPE_INTEGER, &obj) &&
- obj->integer.value == ACP_DMIC_DEV)
- is_dmic_dev = true;
- }
-
- sdw_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_SDW_ADDR, 0);
- if (sdw_dev) {
- acp_data->sdw_fw_node = acpi_fwnode_handle(sdw_dev);
- ret = sdw_amd_scan_controller(&pci->dev);
- /* is_sdw_dev flag will be set when SoundWire Manager device exists */
- if (!ret)
- is_sdw_dev = true;
- }
- if (!is_dmic_dev && !is_sdw_dev)
- return -ENODEV;
- dev_dbg(&pci->dev, "Audio Mode %d\n", config);
+ /* IF WOV entry not found, enable dmic based on acp-audio-device-type entry*/
+ wov_en = true;
+ dmic_en = false;
+
+ config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
switch (config) {
case ACP_CONFIG_4:
case ACP_CONFIG_5:
case ACP_CONFIG_10:
case ACP_CONFIG_11:
- if (is_dmic_dev) {
- acp_data->pdev_config = ACP63_PDM_DEV_CONFIG;
- acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
- }
+ acp_data->is_pdm_config = true;
break;
case ACP_CONFIG_2:
case ACP_CONFIG_3:
- if (is_sdw_dev) {
- switch (acp_data->sdw_manager_count) {
- case 1:
- acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_MODE_DEVS;
- break;
- case 2:
- acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS;
- break;
- default:
- return -EINVAL;
- }
- }
+ acp_data->is_sdw_config = true;
break;
case ACP_CONFIG_6:
case ACP_CONFIG_7:
@@ -360,40 +408,44 @@ static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63
case ACP_CONFIG_8:
case ACP_CONFIG_13:
case ACP_CONFIG_14:
- if (is_dmic_dev && is_sdw_dev) {
- switch (acp_data->sdw_manager_count) {
- case 1:
- acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_PDM_MODE_DEVS;
- break;
- case 2:
- acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_SDW1_PDM_MODE_DEVS;
- break;
- default:
- return -EINVAL;
- }
- } else if (is_dmic_dev) {
- acp_data->pdev_config = ACP63_PDM_DEV_CONFIG;
- acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
- } else if (is_sdw_dev) {
- switch (acp_data->sdw_manager_count) {
- case 1:
- acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_MODE_DEVS;
- break;
- case 2:
- acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
- acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS;
- break;
- default:
- return -EINVAL;
- }
- }
+ acp_data->is_pdm_config = true;
+ acp_data->is_sdw_config = true;
break;
default:
break;
}
+
+ if (acp_data->is_pdm_config) {
+ pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
+ if (pdm_dev) {
+ /* is_dmic_dev flag will be set when ACP PDM controller device exists */
+ if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
+ ACPI_TYPE_INTEGER, &obj) &&
+ obj->integer.value == ACP_DMIC_DEV)
+ dmic_en = true;
+ }
+
+ handle = ACPI_HANDLE(&pci->dev);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+ if (!ACPI_FAILURE(ret))
+ wov_en = dmic_status;
+ }
+
+ if (dmic_en && wov_en)
+ is_dmic_dev = true;
+
+ if (acp_data->is_sdw_config) {
+ ret = acp_scan_sdw_devices(&pci->dev, ACP63_SDW_ADDR);
+ if (!ret && acp_data->info.link_mask)
+ is_sdw_dev = true;
+ }
+
+ acp_data->is_pdm_dev = is_dmic_dev;
+ acp_data->is_sdw_dev = is_sdw_dev;
+ if (!is_dmic_dev && !is_sdw_dev) {
+ dev_dbg(&pci->dev, "No PDM or SoundWire manager devices found\n");
+ return -ENODEV;
+ }
return 0;
}
@@ -418,17 +470,13 @@ static void acp63_fill_platform_dev_info(struct platform_device_info *pdevinfo,
static int create_acp63_platform_devs(struct pci_dev *pci, struct acp63_dev_data *adata, u32 addr)
{
- struct acp_sdw_pdata *sdw_pdata;
- struct platform_device_info pdevinfo[ACP63_DEVS];
+ struct platform_device_info pdevinfo;
struct device *parent;
- int index;
int ret;
parent = &pci->dev;
- dev_dbg(&pci->dev,
- "%s pdev_config:0x%x pdev_count:0x%x\n", __func__, adata->pdev_config,
- adata->pdev_count);
- if (adata->pdev_config) {
+
+ if (adata->is_sdw_dev || adata->is_pdm_dev) {
adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL);
if (!adata->res) {
ret = -ENOMEM;
@@ -440,130 +488,57 @@ static int create_acp63_platform_devs(struct pci_dev *pci, struct acp63_dev_data
memset(&pdevinfo, 0, sizeof(pdevinfo));
}
- switch (adata->pdev_config) {
- case ACP63_PDM_DEV_CONFIG:
- adata->pdm_dev_index = 0;
- acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma",
+ if (adata->is_pdm_dev && adata->is_pdm_config) {
+ acp63_fill_platform_dev_info(&pdevinfo, parent, NULL, "acp_ps_pdm_dma",
0, adata->res, 1, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[1], parent, NULL, "dmic-codec",
- 0, NULL, 0, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "acp_ps_mach",
- 0, NULL, 0, NULL, 0);
- break;
- case ACP63_SDW_DEV_CONFIG:
- if (adata->pdev_count == ACP63_SDW0_MODE_DEVS) {
- sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata),
- GFP_KERNEL);
- if (!sdw_pdata) {
- ret = -ENOMEM;
- goto de_init;
- }
- sdw_pdata->instance = 0;
- sdw_pdata->acp_sdw_lock = &adata->acp_lock;
- adata->sdw0_dev_index = 0;
- adata->sdw_dma_dev_index = 1;
- acp63_fill_platform_dev_info(&pdevinfo[0], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 0, adata->res, 1,
- sdw_pdata, sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[1], parent, NULL, "amd_ps_sdw_dma",
- 0, adata->res, 1, NULL, 0);
- } else if (adata->pdev_count == ACP63_SDW0_SDW1_MODE_DEVS) {
- sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata) * 2,
- GFP_KERNEL);
- if (!sdw_pdata) {
- ret = -ENOMEM;
- goto de_init;
- }
-
- sdw_pdata[0].instance = 0;
- sdw_pdata[1].instance = 1;
- sdw_pdata[0].acp_sdw_lock = &adata->acp_lock;
- sdw_pdata[1].acp_sdw_lock = &adata->acp_lock;
- sdw_pdata->acp_sdw_lock = &adata->acp_lock;
- adata->sdw0_dev_index = 0;
- adata->sdw1_dev_index = 1;
- adata->sdw_dma_dev_index = 2;
- acp63_fill_platform_dev_info(&pdevinfo[0], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 0, adata->res, 1,
- &sdw_pdata[0], sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 1, adata->res, 1,
- &sdw_pdata[1], sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "amd_ps_sdw_dma",
- 0, adata->res, 1, NULL, 0);
+ adata->pdm_dev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(adata->pdm_dev)) {
+ dev_err(&pci->dev,
+ "cannot register %s device\n", pdevinfo.name);
+ ret = PTR_ERR(adata->pdm_dev);
+ goto de_init;
}
- break;
- case ACP63_SDW_PDM_DEV_CONFIG:
- if (adata->pdev_count == ACP63_SDW0_PDM_MODE_DEVS) {
- sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata),
- GFP_KERNEL);
- if (!sdw_pdata) {
- ret = -ENOMEM;
- goto de_init;
- }
-
- sdw_pdata->instance = 0;
- sdw_pdata->acp_sdw_lock = &adata->acp_lock;
- adata->pdm_dev_index = 0;
- adata->sdw0_dev_index = 1;
- adata->sdw_dma_dev_index = 2;
- acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma",
- 0, adata->res, 1, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 0, adata->res, 1,
- sdw_pdata, sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "amd_ps_sdw_dma",
- 0, adata->res, 1, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[3], parent, NULL, "dmic-codec",
- 0, NULL, 0, NULL, 0);
- } else if (adata->pdev_count == ACP63_SDW0_SDW1_PDM_MODE_DEVS) {
- sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata) * 2,
- GFP_KERNEL);
- if (!sdw_pdata) {
- ret = -ENOMEM;
- goto de_init;
- }
- sdw_pdata[0].instance = 0;
- sdw_pdata[1].instance = 1;
- sdw_pdata[0].acp_sdw_lock = &adata->acp_lock;
- sdw_pdata[1].acp_sdw_lock = &adata->acp_lock;
- adata->pdm_dev_index = 0;
- adata->sdw0_dev_index = 1;
- adata->sdw1_dev_index = 2;
- adata->sdw_dma_dev_index = 3;
- acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma",
- 0, adata->res, 1, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 0, adata->res, 1,
- &sdw_pdata[0], sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[2], parent, adata->sdw_fw_node,
- "amd_sdw_manager", 1, adata->res, 1,
- &sdw_pdata[1], sizeof(struct acp_sdw_pdata));
- acp63_fill_platform_dev_info(&pdevinfo[3], parent, NULL, "amd_ps_sdw_dma",
- 0, adata->res, 1, NULL, 0);
- acp63_fill_platform_dev_info(&pdevinfo[4], parent, NULL, "dmic-codec",
- 0, NULL, 0, NULL, 0);
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ acp63_fill_platform_dev_info(&pdevinfo, parent, NULL, "dmic-codec",
+ 0, NULL, 0, NULL, 0);
+ adata->dmic_codec_dev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(adata->dmic_codec_dev)) {
+ dev_err(&pci->dev,
+ "cannot register %s device\n", pdevinfo.name);
+ ret = PTR_ERR(adata->dmic_codec_dev);
+ goto unregister_pdm_dev;
}
- break;
- default:
- dev_dbg(&pci->dev, "No PDM or SoundWire manager devices found\n");
- return 0;
}
+ if (adata->is_sdw_dev && adata->is_sdw_config) {
+ ret = amd_sdw_probe(&pci->dev);
+ if (ret) {
+ if (adata->is_pdm_dev)
+ goto unregister_dmic_codec_dev;
+ else
+ goto de_init;
+ }
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ acp63_fill_platform_dev_info(&pdevinfo, parent, NULL, "amd_ps_sdw_dma",
+ 0, adata->res, 1, NULL, 0);
- for (index = 0; index < adata->pdev_count; index++) {
- adata->pdev[index] = platform_device_register_full(&pdevinfo[index]);
- if (IS_ERR(adata->pdev[index])) {
+ adata->sdw_dma_dev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(adata->sdw_dma_dev)) {
dev_err(&pci->dev,
- "cannot register %s device\n", pdevinfo[index].name);
- ret = PTR_ERR(adata->pdev[index]);
- goto unregister_devs;
+ "cannot register %s device\n", pdevinfo.name);
+ ret = PTR_ERR(adata->sdw_dma_dev);
+ if (adata->is_pdm_dev)
+ goto unregister_dmic_codec_dev;
+ else
+ goto de_init;
}
}
+
return 0;
-unregister_devs:
- for (--index; index >= 0; index--)
- platform_device_unregister(adata->pdev[index]);
+unregister_dmic_codec_dev:
+ platform_device_unregister(adata->dmic_codec_dev);
+unregister_pdm_dev:
+ platform_device_unregister(adata->pdm_dev);
de_init:
if (acp63_deinit(adata->acp63_base, &pci->dev))
dev_err(&pci->dev, "ACP de-init failed\n");
@@ -576,7 +551,6 @@ static int snd_acp63_probe(struct pci_dev *pci,
struct acp63_dev_data *adata;
u32 addr;
u32 irqflags, flag;
- int val;
int ret;
irqflags = IRQF_SHARED;
@@ -618,13 +592,9 @@ static int snd_acp63_probe(struct pci_dev *pci,
ret = -ENOMEM;
goto release_regions;
}
- /*
- * By default acp_reset flag is set to true. i.e acp_deinit() and acp_init()
- * will be invoked for all ACP configurations during suspend/resume callbacks.
- * This flag should be set to false only when SoundWire manager power mode
- * set to ClockStopMode.
- */
- adata->acp_reset = true;
+ adata->addr = addr;
+ adata->reg_range = ACP63_REG_END - ACP63_REG_START;
+ adata->acp_rev = pci->revision;
pci_set_master(pci);
pci_set_drvdata(pci, adata);
mutex_init(&adata->acp_lock);
@@ -637,8 +607,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
goto de_init;
}
- val = readl(adata->acp63_base + ACP_PIN_CONFIG);
- ret = get_acp63_device_config(val, pci, adata);
+ ret = get_acp63_device_config(pci, adata);
/* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
if (ret) {
dev_dbg(&pci->dev, "get acp device config failed:%d\n", ret);
@@ -649,6 +618,12 @@ 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");
+ goto de_init;
+ }
skip_pdev_creation:
device_set_wakeup_enable(&pci->dev, true);
pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
@@ -667,47 +642,108 @@ disable_pci:
return ret;
}
+static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata)
+{
+ u32 sdw0_en, sdw1_en;
+
+ sdw0_en = readl(adata->acp63_base + ACP_SW0_EN);
+ sdw1_en = readl(adata->acp63_base + ACP_SW1_EN);
+ return (sdw0_en || sdw1_en);
+}
+
+static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata)
+{
+ u32 val;
+
+ val = readl(adata->acp63_base + ACP_SW0_WAKE_EN);
+ if (val && adata->sdw->pdev[0])
+ pm_request_resume(&adata->sdw->pdev[0]->dev);
+
+ val = readl(adata->acp63_base + ACP_SW1_WAKE_EN);
+ if (val && adata->sdw->pdev[1])
+ pm_request_resume(&adata->sdw->pdev[1]->dev);
+}
+
static int __maybe_unused snd_acp63_suspend(struct device *dev)
{
struct acp63_dev_data *adata;
- int ret = 0;
+ int ret;
adata = dev_get_drvdata(dev);
- if (adata->acp_reset) {
- ret = acp63_deinit(adata->acp63_base, dev);
- if (ret)
- dev_err(dev, "ACP de-init failed\n");
+ if (adata->is_sdw_dev) {
+ adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
+ if (adata->sdw_en_stat) {
+ writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
+ return 0;
+ }
}
+ ret = acp63_deinit(adata->acp63_base, dev);
+ if (ret)
+ dev_err(dev, "ACP de-init failed\n");
+
return ret;
}
+static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
+{
+ struct acp63_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ if (adata->sdw_en_stat) {
+ writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
+ return 0;
+ }
+ ret = acp63_init(adata->acp63_base, dev);
+ if (ret) {
+ dev_err(dev, "ACP init failed\n");
+ return ret;
+ }
+
+ if (!adata->sdw_en_stat)
+ handle_acp63_sdw_pme_event(adata);
+ return 0;
+}
+
static int __maybe_unused snd_acp63_resume(struct device *dev)
{
struct acp63_dev_data *adata;
- int ret = 0;
+ int ret;
adata = dev_get_drvdata(dev);
- if (adata->acp_reset) {
- ret = acp63_init(adata->acp63_base, dev);
- if (ret)
- dev_err(dev, "ACP init failed\n");
+ if (adata->sdw_en_stat) {
+ writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
+ return 0;
}
+
+ ret = acp63_init(adata->acp63_base, dev);
+ if (ret)
+ dev_err(dev, "ACP init failed\n");
+
return ret;
}
static const struct dev_pm_ops acp63_pm_ops = {
- SET_RUNTIME_PM_OPS(snd_acp63_suspend, snd_acp63_resume, NULL)
+ SET_RUNTIME_PM_OPS(snd_acp63_suspend, snd_acp63_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(snd_acp63_suspend, snd_acp63_resume)
};
static void snd_acp63_remove(struct pci_dev *pci)
{
struct acp63_dev_data *adata;
- int ret, index;
+ int ret;
adata = pci_get_drvdata(pci);
- for (index = 0; index < adata->pdev_count; index++)
- platform_device_unregister(adata->pdev[index]);
+ if (adata->sdw) {
+ amd_sdw_exit(adata);
+ platform_device_unregister(adata->sdw_dma_dev);
+ }
+ if (adata->is_pdm_dev) {
+ platform_device_unregister(adata->pdm_dev);
+ platform_device_unregister(adata->dmic_codec_dev);
+ }
+ if (adata->mach_dev)
+ platform_device_unregister(adata->mach_dev);
ret = acp63_deinit(adata->acp63_base, &pci->dev);
if (ret)
dev_err(&pci->dev, "ACP de-init failed\n");
@@ -740,4 +776,6 @@ module_pci_driver(ps_acp63_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
+MODULE_IMPORT_NS("SOUNDWIRE_AMD_INIT");
+MODULE_IMPORT_NS("SND_AMD_SOUNDWIRE_ACPI");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/ps/ps-mach.c b/sound/soc/amd/ps/ps-mach.c
index 3ffbe4fdafdf..ff8ad036b077 100644
--- a/sound/soc/amd/ps/ps-mach.c
+++ b/sound/soc/amd/ps/ps-mach.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Machine driver for AMD Pink Sardine platform using DMIC
*
@@ -75,5 +75,6 @@ static struct platform_driver acp63_mach_driver = {
module_platform_driver(acp63_mach_driver);
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
+MODULE_DESCRIPTION("AMD Pink Sardine support for DMIC");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c
index d48f7c5af289..318fc260f293 100644
--- a/sound/soc/amd/ps/ps-pdm-dma.c
+++ b/sound/soc/amd/ps/ps-pdm-dma.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD ALSA SoC Pink Sardine PDM Driver
*
@@ -448,7 +448,7 @@ static const struct dev_pm_ops acp63_pdm_pm_ops = {
static struct platform_driver acp63_pdm_dma_driver = {
.probe = acp63_pdm_audio_probe,
- .remove_new = acp63_pdm_audio_remove,
+ .remove = acp63_pdm_audio_remove,
.driver = {
.name = "acp_ps_pdm_dma",
.pm = &acp63_pdm_pm_ops,
diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c
index 9b59063798f2..b602cca92b8b 100644
--- a/sound/soc/amd/ps/ps-sdw-dma.c
+++ b/sound/soc/amd/ps/ps-sdw-dma.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD ALSA SoC Pink Sardine SoundWire DMA Driver
*
@@ -218,7 +218,7 @@ static int acp63_sdw_dma_open(struct snd_soc_component *component,
struct acp_sdw_dma_stream *stream;
struct snd_soc_dai *cpu_dai;
struct amd_sdw_manager *amd_manager;
- struct snd_soc_pcm_runtime *prtd = substream->private_data;
+ struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream);
int ret;
runtime = substream->runtime;
@@ -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)
@@ -551,7 +553,7 @@ static const struct dev_pm_ops acp63_pm_ops = {
static struct platform_driver acp63_sdw_dma_driver = {
.probe = acp63_sdw_platform_probe,
- .remove_new = acp63_sdw_platform_remove,
+ .remove = acp63_sdw_platform_remove,
.driver = {
.name = "amd_ps_sdw_dma",
.pm = &acp63_pm_ops,
diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile
index 62c22b6ed95a..b2ea030cbf25 100644
--- a/sound/soc/amd/raven/Makefile
+++ b/sound/soc/amd/raven/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0+
# Raven Ridge platform Support
-snd-pci-acp3x-objs := pci-acp3x.o
-snd-acp3x-pcm-dma-objs := acp3x-pcm-dma.o
-snd-acp3x-i2s-objs := acp3x-i2s.o
+snd-pci-acp3x-y := pci-acp3x.o
+snd-acp3x-pcm-dma-y := acp3x-pcm-dma.o
+snd-acp3x-i2s-y := acp3x-i2s.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-pci-acp3x.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-pcm-dma.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-i2s.o
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 3a50558f6751..bb9ed52d744d 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -509,7 +509,7 @@ static const struct dev_pm_ops acp3x_pm_ops = {
static struct platform_driver acp3x_dma_driver = {
.probe = acp3x_audio_probe,
- .remove_new = acp3x_audio_remove,
+ .remove = acp3x_audio_remove,
.driver = {
.name = "acp3x_rv_i2s_dma",
.pm = &acp3x_pm_ops,
diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile
index 4a82690aec16..76b4a9c3e24f 100644
--- a/sound/soc/amd/renoir/Makefile
+++ b/sound/soc/amd/renoir/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0+
# Renoir platform Support
-snd-rn-pci-acp3x-objs := rn-pci-acp3x.o
-snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o
-snd-acp3x-rn-objs := acp3x-rn.o
+snd-rn-pci-acp3x-y := rn-pci-acp3x.o
+snd-acp3x-pdm-dma-y := acp3x-pdm-dma.o
+snd-acp3x-rn-y := acp3x-rn.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH) += snd-acp3x-rn.o
diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c
index c3b47e9bd239..95ac8c680037 100644
--- a/sound/soc/amd/renoir/acp3x-pdm-dma.c
+++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c
@@ -489,7 +489,7 @@ static const struct dev_pm_ops acp_pdm_pm_ops = {
static struct platform_driver acp_pdm_dma_driver = {
.probe = acp_pdm_audio_probe,
- .remove_new = acp_pdm_audio_remove,
+ .remove = acp_pdm_audio_remove,
.driver = {
.name = "acp_rn_pdm_dma",
.pm = &acp_pdm_pm_ops,
diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c
index 5d979a7b77fb..3249f74a0197 100644
--- a/sound/soc/amd/renoir/acp3x-rn.c
+++ b/sound/soc/amd/renoir/acp3x-rn.c
@@ -72,5 +72,6 @@ static struct platform_driver acp_mach_driver = {
module_platform_driver(acp_mach_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD Renoir support for DMIC");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/rpl/Makefile b/sound/soc/amd/rpl/Makefile
index 11a33a05e94b..a3825c5be4e7 100644
--- a/sound/soc/amd/rpl/Makefile
+++ b/sound/soc/amd/rpl/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
# RPL platform Support
-snd-rpl-pci-acp6x-objs := rpl-pci-acp6x.o
+snd-rpl-pci-acp6x-y := rpl-pci-acp6x.o
obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += snd-rpl-pci-acp6x.o
diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile
index c9e53e04e247..7eae82faa392 100644
--- a/sound/soc/amd/vangogh/Makefile
+++ b/sound/soc/amd/vangogh/Makefile
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: GPL-2.0+
# Vangogh platform Support
-snd-pci-acp5x-objs := pci-acp5x.o
-snd-acp5x-i2s-objs := acp5x-i2s.o
-snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o
-snd-soc-acp5x-mach-objs := acp5x-mach.o
+snd-pci-acp5x-y := pci-acp5x.o
+snd-acp5x-i2s-y := acp5x-i2s.o
+snd-acp5x-pcm-dma-y := acp5x-pcm-dma.o
+snd-soc-acp5x-mach-y := acp5x-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-i2s.o
diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c
index 7878e061ecb9..2ca904db82ab 100644
--- a/sound/soc/amd/vangogh/acp5x-mach.c
+++ b/sound/soc/amd/vangogh/acp5x-mach.c
@@ -276,8 +276,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp5x_8821_ops,
.init = acp5x_8821_init,
SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform),
@@ -288,7 +286,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
.playback_only = 1,
.ops = &acp5x_cs35l41_play_ops,
SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform),
@@ -375,8 +372,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp5x_8821_ops,
.init = acp5x_8821_init,
SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform),
@@ -387,7 +382,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
.playback_only = 1,
.ops = &acp5x_max98388_play_ops,
SND_SOC_DAILINK_REG(acp5x_bt, max98388, platform),
diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
index 491b16e52a72..d5965f2b09bc 100644
--- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c
+++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
@@ -499,7 +499,7 @@ static const struct dev_pm_ops acp5x_pm_ops = {
static struct platform_driver acp5x_dma_driver = {
.probe = acp5x_audio_probe,
- .remove_new = acp5x_audio_remove,
+ .remove = acp5x_audio_remove,
.driver = {
.name = "acp5x_i2s_dma",
.pm = &acp5x_pm_ops,
diff --git a/sound/soc/amd/yc/Makefile b/sound/soc/amd/yc/Makefile
index dc2974440388..7a0a3a410b2d 100644
--- a/sound/soc/amd/yc/Makefile
+++ b/sound/soc/amd/yc/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0+
# Yellow Carp platform Support
-snd-pci-acp6x-objs := pci-acp6x.o
-snd-acp6x-pdm-dma-objs := acp6x-pdm-dma.o
-snd-soc-acp6x-mach-objs := acp6x-mach.o
+snd-pci-acp6x-y := pci-acp6x.o
+snd-acp6x-pdm-dma-y := acp6x-pdm-dma.o
+snd-soc-acp6x-mach-y := acp6x-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP6x) += snd-pci-acp6x.o
obj-$(CONFIG_SND_SOC_AMD_ACP6x) += snd-acp6x-pdm-dma.o
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 90360f8b3e81..a7637056972a 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -203,28 +203,63 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21J2"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21J0"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21J0"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21J5"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21J5"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M1"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M3"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M4"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M5"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M6"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21ME"),
}
},
{
@@ -279,6 +314,34 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83L3"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83N6"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83Q2"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"),
}
@@ -290,6 +353,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"),
+ }
+ },
{
.driver_data = &acp6x_card,
.matches = {
@@ -315,12 +385,33 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "E1404FA"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M7600RE"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M3502RA"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"),
}
@@ -335,6 +426,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 17 D7VEK"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
}
@@ -356,6 +454,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Xiaomi Book Pro 14 2022"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Redmi G 2022"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Razer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
}
@@ -399,6 +511,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8A44"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8A22"),
}
},
@@ -413,6 +532,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8A7F"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8B27"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8B2F"),
}
},
@@ -433,6 +566,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "MDC"),
+ DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "System76"),
DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"),
}
@@ -453,8 +593,14 @@ static int acp6x_probe(struct platform_device *pdev)
struct acp6x_pdm *machine = NULL;
struct snd_soc_card *card;
struct acpi_device *adev;
+ acpi_handle handle;
+ acpi_integer dmic_status;
int ret;
+ bool is_dmic_enable, wov_en;
+ /* IF WOV entry not found, enable dmic based on AcpDmicConnected entry*/
+ is_dmic_enable = false;
+ wov_en = true;
/* check the parent device's firmware node has _DSD or not */
adev = ACPI_COMPANION(pdev->dev.parent);
if (adev) {
@@ -462,9 +608,24 @@ static int acp6x_probe(struct platform_device *pdev)
if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == 1)
- platform_set_drvdata(pdev, &acp6x_card);
+ is_dmic_enable = true;
}
+ handle = ACPI_HANDLE(pdev->dev.parent);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+ if (!ACPI_FAILURE(ret)) {
+ wov_en = dmic_status;
+ if (!wov_en)
+ return -ENODEV;
+ } else {
+ /* Incase of ACPI method read failure then jump to check_dmi_entry */
+ goto check_dmi_entry;
+ }
+
+ if (is_dmic_enable)
+ platform_set_drvdata(pdev, &acp6x_card);
+
+check_dmi_entry:
/* check for any DMI overrides */
dmi_id = dmi_first_match(yc_acp_quirk_table);
if (dmi_id)
@@ -497,5 +658,6 @@ static struct platform_driver acp6x_mach_driver = {
module_platform_driver(acp6x_mach_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD Yellow Carp support for DMIC");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/yc/acp6x-pdm-dma.c b/sound/soc/amd/yc/acp6x-pdm-dma.c
index 72c4591e451b..3eb3e82efb10 100644
--- a/sound/soc/amd/yc/acp6x-pdm-dma.c
+++ b/sound/soc/amd/yc/acp6x-pdm-dma.c
@@ -440,7 +440,7 @@ static const struct dev_pm_ops acp6x_pdm_pm_ops = {
static struct platform_driver acp6x_pdm_dma_driver = {
.probe = acp6x_pdm_audio_probe,
- .remove_new = acp6x_pdm_audio_remove,
+ .remove = acp6x_pdm_audio_remove,
.driver = {
.name = "acp_yc_pdm_dma",
.pm = &acp6x_pdm_pm_ops,
diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c
index 694b8e313902..7af6a349b1d4 100644
--- a/sound/soc/amd/yc/pci-acp6x.c
+++ b/sound/soc/amd/yc/pci-acp6x.c
@@ -162,7 +162,6 @@ static int snd_acp6x_probe(struct pci_dev *pci,
/* Yellow Carp device check */
switch (pci->revision) {
case 0x60:
- case 0x63:
case 0x6f:
break;
default: