From 4617721c502b2ddaa4e324e86da4997edf738fa5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 2 Sep 2026 09:55:01 -0400 Subject: ftrace: Synchronize the initialization of ftrace_ops There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt --- sound/soc/amd/Kconfig | 188 ++ sound/soc/amd/Makefile | 21 + sound/soc/amd/acp-config.c | 423 +++++ sound/soc/amd/acp-da7219-max98357a.c | 808 +++++++++ sound/soc/amd/acp-es8336.c | 319 ++++ sound/soc/amd/acp-pcm-dma.c | 1440 ++++++++++++++++ sound/soc/amd/acp-rt5645.c | 198 +++ sound/soc/amd/acp.h | 223 +++ sound/soc/amd/acp/Kconfig | 198 +++ sound/soc/amd/acp/Makefile | 51 + sound/soc/amd/acp/acp-i2s.c | 707 ++++++++ sound/soc/amd/acp/acp-legacy-common.c | 665 ++++++++ sound/soc/amd/acp/acp-legacy-mach.c | 245 +++ sound/soc/amd/acp/acp-mach-common.c | 1824 ++++++++++++++++++++ sound/soc/amd/acp/acp-mach.h | 143 ++ sound/soc/amd/acp/acp-pci.c | 287 ++++ sound/soc/amd/acp/acp-pdm.c | 187 ++ sound/soc/amd/acp/acp-platform.c | 360 ++++ sound/soc/amd/acp/acp-rembrandt.c | 247 +++ sound/soc/amd/acp/acp-renoir.c | 191 +++ sound/soc/amd/acp/acp-sdw-legacy-mach.c | 604 +++++++ sound/soc/amd/acp/acp-sdw-mach-common.c | 98 ++ sound/soc/amd/acp/acp-sdw-sof-mach.c | 462 +++++ sound/soc/amd/acp/acp-sof-mach.c | 174 ++ sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c | 463 +++++ sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h | 12 + sound/soc/amd/acp/acp63.c | 298 ++++ sound/soc/amd/acp/acp70.c | 228 +++ sound/soc/amd/acp/acp_common.h | 20 + sound/soc/amd/acp/amd-acp63-acpi-match.c | 557 ++++++ sound/soc/amd/acp/amd-acp70-acpi-match.c | 880 ++++++++++ sound/soc/amd/acp/amd-acpi-mach.c | 93 + sound/soc/amd/acp/amd-sdw-acpi.c | 62 + sound/soc/amd/acp/amd.h | 365 ++++ sound/soc/amd/acp/chip_offset_byte.h | 146 ++ sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c | 38 + sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.h | 25 + sound/soc/amd/acp/soc_amd_sdw_common.h | 62 + sound/soc/amd/acp3x-rt5682-max9836.c | 560 ++++++ sound/soc/amd/acp7x/Makefile | 5 + sound/soc/amd/acp7x/acp7x-common.c | 125 ++ sound/soc/amd/acp7x/acp7x.h | 110 ++ sound/soc/amd/acp7x/pci-acp7x.c | 168 ++ sound/soc/amd/include/acp_2_2_d.h | 593 +++++++ sound/soc/amd/include/acp_2_2_enum.h | 1052 ++++++++++++ sound/soc/amd/include/acp_2_2_sh_mask.h | 2276 +++++++++++++++++++++++++ sound/soc/amd/mach-config.h | 39 + sound/soc/amd/ps/Makefile | 11 + sound/soc/amd/ps/acp63.h | 448 +++++ sound/soc/amd/ps/pci-ps.c | 785 +++++++++ sound/soc/amd/ps/ps-common.c | 493 ++++++ sound/soc/amd/ps/ps-mach.c | 78 + sound/soc/amd/ps/ps-pdm-dma.c | 464 +++++ sound/soc/amd/ps/ps-sdw-dma.c | 804 +++++++++ sound/soc/amd/raven/Makefile | 8 + sound/soc/amd/raven/acp3x-i2s.c | 337 ++++ sound/soc/amd/raven/acp3x-pcm-dma.c | 526 ++++++ sound/soc/amd/raven/acp3x.h | 162 ++ sound/soc/amd/raven/chip_offset_byte.h | 639 +++++++ sound/soc/amd/raven/pci-acp3x.c | 347 ++++ sound/soc/amd/renoir/Makefile | 8 + sound/soc/amd/renoir/acp3x-pdm-dma.c | 506 ++++++ sound/soc/amd/renoir/acp3x-rn.c | 75 + sound/soc/amd/renoir/rn-pci-acp3x.c | 434 +++++ sound/soc/amd/renoir/rn_acp3x.h | 93 + sound/soc/amd/renoir/rn_chip_offset_byte.h | 349 ++++ sound/soc/amd/vangogh/Makefile | 11 + sound/soc/amd/vangogh/acp5x-i2s.c | 423 +++++ sound/soc/amd/vangogh/acp5x-mach.c | 489 ++++++ sound/soc/amd/vangogh/acp5x-pcm-dma.c | 513 ++++++ sound/soc/amd/vangogh/acp5x.h | 224 +++ sound/soc/amd/vangogh/pci-acp5x.c | 342 ++++ sound/soc/amd/vangogh/vg_chip_offset_byte.h | 337 ++++ sound/soc/amd/yc/Makefile | 9 + sound/soc/amd/yc/acp6x-mach.c | 969 +++++++++++ sound/soc/amd/yc/acp6x-pdm-dma.c | 455 +++++ sound/soc/amd/yc/acp6x.h | 110 ++ sound/soc/amd/yc/acp6x_chip_offset_byte.h | 444 +++++ sound/soc/amd/yc/pci-acp6x.c | 362 ++++ 79 files changed, 29495 insertions(+) create mode 100644 sound/soc/amd/Kconfig create mode 100644 sound/soc/amd/Makefile create mode 100644 sound/soc/amd/acp-config.c create mode 100644 sound/soc/amd/acp-da7219-max98357a.c create mode 100644 sound/soc/amd/acp-es8336.c create mode 100644 sound/soc/amd/acp-pcm-dma.c create mode 100644 sound/soc/amd/acp-rt5645.c create mode 100644 sound/soc/amd/acp.h create mode 100644 sound/soc/amd/acp/Kconfig create mode 100644 sound/soc/amd/acp/Makefile create mode 100644 sound/soc/amd/acp/acp-i2s.c create mode 100644 sound/soc/amd/acp/acp-legacy-common.c create mode 100644 sound/soc/amd/acp/acp-legacy-mach.c create mode 100644 sound/soc/amd/acp/acp-mach-common.c create mode 100644 sound/soc/amd/acp/acp-mach.h create mode 100644 sound/soc/amd/acp/acp-pci.c create mode 100644 sound/soc/amd/acp/acp-pdm.c create mode 100644 sound/soc/amd/acp/acp-platform.c create mode 100644 sound/soc/amd/acp/acp-rembrandt.c create mode 100644 sound/soc/amd/acp/acp-renoir.c create mode 100644 sound/soc/amd/acp/acp-sdw-legacy-mach.c create mode 100644 sound/soc/amd/acp/acp-sdw-mach-common.c create mode 100644 sound/soc/amd/acp/acp-sdw-sof-mach.c create mode 100644 sound/soc/amd/acp/acp-sof-mach.c create mode 100644 sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c create mode 100644 sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h create mode 100644 sound/soc/amd/acp/acp63.c create mode 100644 sound/soc/amd/acp/acp70.c create mode 100644 sound/soc/amd/acp/acp_common.h create mode 100644 sound/soc/amd/acp/amd-acp63-acpi-match.c create mode 100644 sound/soc/amd/acp/amd-acp70-acpi-match.c create mode 100644 sound/soc/amd/acp/amd-acpi-mach.c create mode 100644 sound/soc/amd/acp/amd-sdw-acpi.c create mode 100644 sound/soc/amd/acp/amd.h create mode 100644 sound/soc/amd/acp/chip_offset_byte.h create mode 100644 sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c create mode 100644 sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.h create mode 100644 sound/soc/amd/acp/soc_amd_sdw_common.h create mode 100644 sound/soc/amd/acp3x-rt5682-max9836.c create mode 100644 sound/soc/amd/acp7x/Makefile create mode 100644 sound/soc/amd/acp7x/acp7x-common.c create mode 100644 sound/soc/amd/acp7x/acp7x.h create mode 100644 sound/soc/amd/acp7x/pci-acp7x.c create mode 100644 sound/soc/amd/include/acp_2_2_d.h create mode 100644 sound/soc/amd/include/acp_2_2_enum.h create mode 100644 sound/soc/amd/include/acp_2_2_sh_mask.h create mode 100644 sound/soc/amd/mach-config.h create mode 100644 sound/soc/amd/ps/Makefile create mode 100644 sound/soc/amd/ps/acp63.h create mode 100644 sound/soc/amd/ps/pci-ps.c create mode 100644 sound/soc/amd/ps/ps-common.c create mode 100644 sound/soc/amd/ps/ps-mach.c create mode 100644 sound/soc/amd/ps/ps-pdm-dma.c create mode 100644 sound/soc/amd/ps/ps-sdw-dma.c create mode 100644 sound/soc/amd/raven/Makefile create mode 100644 sound/soc/amd/raven/acp3x-i2s.c create mode 100644 sound/soc/amd/raven/acp3x-pcm-dma.c create mode 100644 sound/soc/amd/raven/acp3x.h create mode 100644 sound/soc/amd/raven/chip_offset_byte.h create mode 100644 sound/soc/amd/raven/pci-acp3x.c create mode 100644 sound/soc/amd/renoir/Makefile create mode 100644 sound/soc/amd/renoir/acp3x-pdm-dma.c create mode 100644 sound/soc/amd/renoir/acp3x-rn.c create mode 100644 sound/soc/amd/renoir/rn-pci-acp3x.c create mode 100644 sound/soc/amd/renoir/rn_acp3x.h create mode 100644 sound/soc/amd/renoir/rn_chip_offset_byte.h create mode 100644 sound/soc/amd/vangogh/Makefile create mode 100644 sound/soc/amd/vangogh/acp5x-i2s.c create mode 100644 sound/soc/amd/vangogh/acp5x-mach.c create mode 100644 sound/soc/amd/vangogh/acp5x-pcm-dma.c create mode 100644 sound/soc/amd/vangogh/acp5x.h create mode 100644 sound/soc/amd/vangogh/pci-acp5x.c create mode 100644 sound/soc/amd/vangogh/vg_chip_offset_byte.h create mode 100644 sound/soc/amd/yc/Makefile create mode 100644 sound/soc/amd/yc/acp6x-mach.c create mode 100644 sound/soc/amd/yc/acp6x-pdm-dma.c create mode 100644 sound/soc/amd/yc/acp6x.h create mode 100644 sound/soc/amd/yc/acp6x_chip_offset_byte.h create mode 100644 sound/soc/amd/yc/pci-acp6x.c (limited to 'sound/soc/amd') diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig new file mode 100644 index 000000000..9f4f1f4ac --- /dev/null +++ b/sound/soc/amd/Kconfig @@ -0,0 +1,188 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "AMD" + +config SND_SOC_AMD_ACP + tristate "AMD Audio Coprocessor support" + help + This option enables ACP DMA support on AMD platform. + +config SND_SOC_AMD_CZ_DA7219MX98357_MACH + tristate "AMD CZ support for DA7219, RT5682 and MAX9835" + select SND_SOC_DA7219 + select SND_SOC_RT5682_I2C + select SND_SOC_MAX98357A + select SND_SOC_ADAU7002 + select REGULATOR + depends on SND_SOC_AMD_ACP && I2C && GPIOLIB && ACPI + help + This option enables machine driver for DA7219, RT5682 and MAX9835. + +config SND_SOC_AMD_CZ_RT5645_MACH + tristate "AMD CZ support for RT5645" + select SND_SOC_RT5645 + depends on SND_SOC_AMD_ACP && I2C + help + This option enables machine driver for rt5645. + +config SND_SOC_AMD_ST_ES8336_MACH + tristate "AMD ST support for ES8336" + select SND_SOC_ACPI if ACPI + select SND_SOC_ES8316 + depends on SND_SOC_AMD_ACP && ACPI + depends on I2C + help + This option enables machine driver for Jadeite platform + using es8336 codec. + Say m if you have such a device. + If unsure select "N". + +config SND_SOC_AMD_ACP3x + tristate "AMD Audio Coprocessor-v3.x support" + depends on X86 && PCI + help + This option enables ACP v3.x I2S support on AMD platform + +config SND_SOC_AMD_RV_RT5682_MACH + tristate "AMD RV support for RT5682" + select SND_SOC_RT5682_I2C + select SND_SOC_MAX98357A + select SND_SOC_CROS_EC_CODEC + select I2C_CROS_EC_TUNNEL + select SND_SOC_RT1015 + select SND_SOC_RT1015P + depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC && GPIOLIB + help + This option enables machine driver for RT5682 and MAX9835. + +config SND_SOC_AMD_RENOIR + tristate "AMD Audio Coprocessor - Renoir support" + select SND_AMD_ACP_CONFIG + depends on X86 && PCI + help + This option enables ACP support for Renoir platform + +config SND_SOC_AMD_RENOIR_MACH + tristate "AMD Renoir support for DMIC" + select SND_SOC_DMIC + depends on SND_SOC_AMD_RENOIR && GPIOLIB + help + This option enables machine driver for DMIC + +config SND_SOC_AMD_ACP5x + tristate "AMD Audio Coprocessor-v5.x I2S support" + depends on X86 && PCI + select SND_AMD_ACP_CONFIG + help + This option enables ACP v5.x support on AMD platform + + By enabling this flag build will trigger for ACP PCI driver, + ACP DMA driver, CPU DAI driver. + +config SND_SOC_AMD_VANGOGH_MACH + tristate "AMD Vangogh support for NAU8821/CS35L41/MAX98388" + select SND_SOC_NAU8821 + select SND_SOC_CS35L41_SPI + select SND_SOC_MAX98388 + select SND_AMD_ACP_CONFIG + depends on SND_SOC_AMD_ACP5x && I2C && SPI_MASTER + help + This option enables machine driver for Vangogh platform + using NAU8821 and either CS35L41 or MAX98388 codecs. + Say m if you have such a device. + If unsure select "N". + +config SND_SOC_AMD_ACP6x + tristate "AMD Audio Coprocessor-v6.x Yellow Carp support" + select SND_AMD_ACP_CONFIG + depends on X86 && PCI + help + This option enables Audio Coprocessor i.e ACP v6.x support on + AMD Yellow Carp platform. By enabling this flag build will be + triggered for ACP PCI driver, ACP PDM DMA driver. + Say m if you have such a device. + If unsure select "N". + +config SND_SOC_AMD_YC_MACH + tristate "AMD YC support for DMIC" + select SND_SOC_DMIC + 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. + DMIC can be connected directly to ACP IP. + Say m if you have such a device. + If unsure select "N". + +config SND_AMD_ACP_CONFIG + tristate "AMD ACP configuration selection" + select SND_SOC_ACPI if ACPI + help + This option adds an auto detection to determine which ACP + driver modules to use + +source "sound/soc/amd/acp/Kconfig" + +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/v7.0/v7.1 support" + 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 ACP6.3/ACP7.0/ACP7.1 + variants support. By enabling this flag build will be triggered + for ACP PCI driver, ACP PDM DMA driver, ACP SoundWire DMA + driver. + Say m if you have such a device. + If unsure select "N". + +config SND_SOC_AMD_PS_MACH + tristate "AMD PINK SARDINE support for DMIC" + select SND_SOC_DMIC + depends on SND_SOC_AMD_PS + help + This option enables machine driver for Pink Sardine platform + using dmic. ACP IP has PDM Decoder block with DMA controller. + DMIC can be connected directly to ACP IP. + Say m if you have such a device. + If unsure select "N". + +config SND_SOC_AMD_ACP7X + tristate "AMD Audio Coprocessor-v7.x support" + depends on X86 && PCI && ACPI + help + This option enables Audio Coprocessor i.e ACP7.x + variants support(ACP7.D/7.E/7.F). By enabling this flag build + will be triggered for ACP PCI driver. + Say m if you have such a device. + If unsure select "N". + +endif +endmenu diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile new file mode 100644 index 000000000..ef2b36d47 --- /dev/null +++ b/sound/soc/amd/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-only +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 +obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o +obj-$(CONFIG_SND_SOC_AMD_ST_ES8336_MACH) += snd-soc-acp-es8336-mach.o +obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/ +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_AMD_ACP_CONFIG) += acp/ +obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o +obj-$(CONFIG_SND_SOC_AMD_PS) += ps/ +obj-$(CONFIG_SND_SOC_AMD_ACP7X) += acp7x/ diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c new file mode 100644 index 000000000..2d50be819 --- /dev/null +++ b/sound/soc/amd/acp-config.c @@ -0,0 +1,423 @@ +// 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) 2021, 2023 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// + +/* ACP machine configuration module */ + +#include +#include +#include +#include +#include + +#include "../sof/amd/acp.h" +#include "mach-config.h" + +#define ACP_7_0_REV 0x70 + +static int acp_quirk_data; + +static const struct dmi_system_id acp70_acpi_flag_override_table[] = { + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "HN7306EA"), + }, + }, + { + /* ASUS Zenbook S16 UM5606GA (Strix Point, ACP 7.0) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "Zenbook S16 UM5606GA"), + }, + }, + { + /* Lenovo Yoga Pro 7 15ASH11 (Strix Halo, ACP 7.0) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83W5"), + }, + }, + { + /* Lenovo Legion 7 15ASH11 (Strix Halo, ACP 7.0) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83V9"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC"), + DMI_MATCH(DMI_PRODUCT_NAME, "FA401EA"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook 18 M1807GA"), + }, + }, + { + /* HP OmniBook X Flip 14-kc0xxx (Strix Point, ACP 7.2) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8EA1"), + }, + }, + { + /* HP OmniBook X Flip 16-cc0xxx */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8EA2"), + }, + }, + {} +}; + +static const struct config_entry config_table[] = { + { + .flags = FLAG_AMD_SOF, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), + DMI_MATCH(DMI_PRODUCT_NAME, "Majolica-CZN"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_SOF, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_MATCH(DMI_PRODUCT_NAME, "Jupiter"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_SOF, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"), + }, + }, + {} + }, + }, + { + .flags = FLAG_AMD_LEGACY, + .device = ACP_PCI_DEV_ID, + .dmi_table = (const struct dmi_system_id []) { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1060"), + }, + }, + {} + }, + }, +}; + +static int snd_amd_acp_acpi_find_config(struct pci_dev *pci) +{ + const union acpi_object *obj; + int acp_flag = FLAG_AMD_LEGACY_ONLY_DMIC; + + if (!acpi_dev_get_property(ACPI_COMPANION(&pci->dev), "acp-audio-config-flag", + ACPI_TYPE_INTEGER, &obj)) + acp_flag = obj->integer.value; + + return acp_flag; +} + +int snd_amd_acp_find_config(struct pci_dev *pci) +{ + const struct config_entry *table = config_table; + u16 device = pci->device; + int i; + + /* Do not enable FLAGS on older platforms with Rev Id zero + * For platforms which has ACP 7.0 or higher, read the acp + * config flag from BIOS ACPI table and for older platforms + * read it from DMI tables. + */ + if (!pci->revision) + return 0; + else if (pci->revision >= ACP_7_0_REV) { + if (dmi_check_system(acp70_acpi_flag_override_table)) + return 0; + return snd_amd_acp_acpi_find_config(pci); + } + + for (i = 0; i < ARRAY_SIZE(config_table); i++, table++) { + if (table->device != device) + continue; + if (table->dmi_table && !dmi_check_system(table->dmi_table)) + continue; + acp_quirk_data = table->flags; + return table->flags; + } + + return 0; +} +EXPORT_SYMBOL(snd_amd_acp_find_config); + +static struct snd_soc_acpi_codecs amp_rt1019 = { + .num_codecs = 1, + .codecs = {"10EC1019"} +}; + +static struct snd_soc_acpi_codecs amp_max = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + +static struct snd_soc_acpi_codecs amp_max98388 = { + .num_codecs = 1, + .codecs = {"ADS8388"} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[] = { + { + .id = "10EC5682", + .drv_name = "rt5682-rt1019", + .pdata = (void *)&acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + .fw_filename = "sof-rn.ri", + .sof_tplg_filename = "sof-rn-rt5682-rt1019.tplg", + }, + { + .id = "10EC5682", + .drv_name = "rt5682-max", + .pdata = (void *)&acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + .fw_filename = "sof-rn.ri", + .sof_tplg_filename = "sof-rn-rt5682-max98360.tplg", + }, + { + .id = "RTL5682", + .drv_name = "rt5682s-max", + .pdata = (void *)&acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + .fw_filename = "sof-rn.ri", + .sof_tplg_filename = "sof-rn-rt5682-max98360.tplg", + }, + { + .id = "RTL5682", + .drv_name = "rt5682s-rt1019", + .pdata = (void *)&acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + .fw_filename = "sof-rn.ri", + .sof_tplg_filename = "sof-rn-rt5682-rt1019.tplg", + }, + { + .id = "AMDI1019", + .drv_name = "renoir-dsp", + .pdata = (void *)&acp_quirk_data, + .fw_filename = "sof-rn.ri", + .sof_tplg_filename = "sof-acp.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_sof_machines); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[] = { + { + .id = "NVTN2020", + .drv_name = "nau8821-max", + .pdata = &acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max98388, + .fw_filename = "sof-vangogh.ri", + .sof_tplg_filename = "sof-vangogh-nau8821-max.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_vangogh_sof_machines); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = { + { + .id = "AMDI1019", + .drv_name = "rmb-dsp", + .pdata = &acp_quirk_data, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-acp-rmb.tplg", + }, + { + .id = "10508825", + .drv_name = "nau8825-max", + .pdata = &acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-rmb-nau8825-max98360.tplg", + }, + { + .id = "RTL5682", + .drv_name = "rt5682s-hs-rt1019", + .pdata = &acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-rmb-rt5682s-rt1019.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[] = { + { + .id = "AMDI1019", + .drv_name = "acp63-dsp", + .pdata = &acp_quirk_data, + .fw_filename = "sof-acp_6_3.ri", + .sof_tplg_filename = "sof-acp_6_3.tplg", + }, + {}, +}; +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); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp7x_sof_machines[] = { + { + .id = "AMDI1010", + .drv_name = "acp7x-dsp", + .pdata = &acp_quirk_data, + .fw_filename = "sof-acp7x.ri", + .sof_tplg_filename = "sof-acp7x.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp7x_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 new file mode 100644 index 000000000..af559653e --- /dev/null +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -0,0 +1,808 @@ +// SPDX-License-Identifier: MIT +// +// Machine driver for AMD ACP Audio engine using DA7219, RT5682 & MAX98357 codec +// +//Copyright 2017-2021 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp.h" +#include "../codecs/da7219.h" +#include "../codecs/rt5682.h" + +#define CZ_PLAT_CLK 48000000 +#define DUAL_CHANNEL 2 +#define RT5682_PLL_FREQ (48000 * 512) + +static struct snd_soc_jack cz_jack; +static struct snd_soc_jack_pin cz_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Line Out", + .mask = SND_JACK_LINEOUT, + }, +}; + +static struct clk *da7219_dai_wclk; +static struct clk *da7219_dai_bclk; +static struct clk *rt5682_dai_wclk; +static struct clk *rt5682_dai_bclk; + +static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, + CZ_PLAT_CLK, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL, + CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec pll: %d\n", ret); + return ret; + } + + da7219_dai_wclk = devm_clk_get(component->dev, "da7219-dai-wclk"); + if (IS_ERR(da7219_dai_wclk)) + return PTR_ERR(da7219_dai_wclk); + + da7219_dai_bclk = devm_clk_get(component->dev, "da7219-dai-bclk"); + if (IS_ERR(da7219_dai_bclk)) + return PTR_ERR(da7219_dai_bclk); + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cz_jack, + cz_jack_pins, + ARRAY_SIZE(cz_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + snd_soc_component_set_jack(component, &cz_jack, NULL); + + return 0; +} + +static int da7219_clk_enable(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + + /* + * Set wclk to 48000 because the rate constraint of this driver is + * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is + * minimum of 64x the LRCLK sample rate." DA7219 is the only clk + * source so for all codecs we have to limit bclk to 64X lrclk. + */ + clk_set_rate(da7219_dai_wclk, 48000); + clk_set_rate(da7219_dai_bclk, 48000 * 64); + ret = clk_prepare_enable(da7219_dai_bclk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable master clock %d\n", ret); + return ret; + } + + return ret; +} + +static void da7219_clk_disable(void) +{ + clk_disable_unprepare(da7219_dai_bclk); +} + +static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + + dev_info(codec_dai->dev, "codec dai name = %s\n", codec_dai->name); + + /* Set codec sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, + "Failed to set rt5682 SYSCLK: %d\n", ret); + return ret; + } + /* set codec PLL */ + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, + CZ_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set rt5682 PLL: %d\n", ret); + return ret; + } + + rt5682_dai_wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); + if (IS_ERR(rt5682_dai_wclk)) + return PTR_ERR(rt5682_dai_wclk); + + rt5682_dai_bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); + if (IS_ERR(rt5682_dai_bclk)) + return PTR_ERR(rt5682_dai_bclk); + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cz_jack, + cz_jack_pins, + ARRAY_SIZE(cz_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + ret = snd_soc_component_set_jack(component, &cz_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + return 0; +} + +static int rt5682_clk_enable(struct snd_pcm_substream *substream) +{ + int ret; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + + /* + * Set wclk to 48000 because the rate constraint of this driver is + * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is + * minimum of 64x the LRCLK sample rate." RT5682 is the only clk + * source so for all codecs we have to limit bclk to 64X lrclk. + */ + ret = clk_set_rate(rt5682_dai_wclk, 48000); + if (ret) { + dev_err(rtd->dev, "Error setting wclk rate: %d\n", ret); + return ret; + } + ret = clk_set_rate(rt5682_dai_bclk, 48000 * 64); + if (ret) { + dev_err(rtd->dev, "Error setting bclk rate: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(rt5682_dai_wclk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable wclk %d\n", ret); + return ret; + } + return ret; +} + +static void rt5682_clk_disable(void) +{ + clk_disable_unprepare(rt5682_dai_wclk); +} + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int cz_da7219_play_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + return da7219_clk_enable(substream); +} + +static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL1; + return da7219_clk_enable(substream); +} + +static int cz_max_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_BT_INSTANCE; + return da7219_clk_enable(substream); +} + +static int cz_dmic0_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + return da7219_clk_enable(substream); +} + +static int cz_dmic1_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL0; + return da7219_clk_enable(substream); +} + +static void cz_da7219_shutdown(struct snd_pcm_substream *substream) +{ + da7219_clk_disable(); +} + +static int cz_rt5682_play_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL1; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_max_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_BT_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_dmic1_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL0; + return rt5682_clk_enable(substream); +} + +static void cz_rt5682_shutdown(struct snd_pcm_substream *substream) +{ + rt5682_clk_disable(); +} + +static const struct snd_soc_ops cz_da7219_play_ops = { + .startup = cz_da7219_play_startup, + .shutdown = cz_da7219_shutdown, +}; + +static const struct snd_soc_ops cz_da7219_cap_ops = { + .startup = cz_da7219_cap_startup, + .shutdown = cz_da7219_shutdown, +}; + +static const struct snd_soc_ops cz_max_play_ops = { + .startup = cz_max_startup, + .shutdown = cz_da7219_shutdown, +}; + +static const struct snd_soc_ops cz_dmic0_cap_ops = { + .startup = cz_dmic0_startup, + .shutdown = cz_da7219_shutdown, +}; + +static const struct snd_soc_ops cz_dmic1_cap_ops = { + .startup = cz_dmic1_startup, + .shutdown = cz_da7219_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_play_ops = { + .startup = cz_rt5682_play_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_cap_ops = { + .startup = cz_rt5682_cap_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_max_play_ops = { + .startup = cz_rt5682_max_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_dmic0_cap_ops = { + .startup = cz_rt5682_dmic0_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_dmic1_cap_ops = { + .startup = cz_rt5682_dmic1_startup, + .shutdown = cz_rt5682_shutdown, +}; + +SND_SOC_DAILINK_DEF(designware1, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1"))); +SND_SOC_DAILINK_DEF(designware2, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2"))); +SND_SOC_DAILINK_DEF(designware3, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3"))); + +SND_SOC_DAILINK_DEF(dlgs, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi"))); +SND_SOC_DAILINK_DEF(rt5682, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); +SND_SOC_DAILINK_DEF(mx, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(adau, + DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0"))); + +static struct snd_soc_dai_link cz_dai_7219_98357[] = { + { + .name = "amd-da7219-play", + .stream_name = "Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .init = cz_da7219_init, + .playback_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_da7219_play_ops, + SND_SOC_DAILINK_REG(designware1, dlgs, platform), + }, + { + .name = "amd-da7219-cap", + .stream_name = "Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_da7219_cap_ops, + SND_SOC_DAILINK_REG(designware2, dlgs, platform), + }, + { + .name = "amd-max98357-play", + .stream_name = "HiFi Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .playback_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_max_play_ops, + SND_SOC_DAILINK_REG(designware3, mx, platform), + }, + { + /* C panel DMIC */ + .name = "dmic0", + .stream_name = "DMIC0 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_dmic0_cap_ops, + SND_SOC_DAILINK_REG(designware3, adau, platform), + }, + { + /* A/B panel DMIC */ + .name = "dmic1", + .stream_name = "DMIC1 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_dmic1_cap_ops, + SND_SOC_DAILINK_REG(designware2, adau, platform), + }, +}; + +static struct snd_soc_dai_link cz_dai_5682_98357[] = { + { + .name = "amd-rt5682-play", + .stream_name = "Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .init = cz_rt5682_init, + .playback_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_rt5682_play_ops, + SND_SOC_DAILINK_REG(designware1, rt5682, platform), + }, + { + .name = "amd-rt5682-cap", + .stream_name = "Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_rt5682_cap_ops, + SND_SOC_DAILINK_REG(designware2, rt5682, platform), + }, + { + .name = "amd-max98357-play", + .stream_name = "HiFi Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .playback_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_rt5682_max_play_ops, + SND_SOC_DAILINK_REG(designware3, mx, platform), + }, + { + /* C panel DMIC */ + .name = "dmic0", + .stream_name = "DMIC0 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_rt5682_dmic0_cap_ops, + SND_SOC_DAILINK_REG(designware3, adau, platform), + }, + { + /* A/B panel DMIC */ + .name = "dmic1", + .stream_name = "DMIC1 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .capture_only = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .ops = &cz_rt5682_dmic1_cap_ops, + SND_SOC_DAILINK_REG(designware2, adau, platform), + }, +}; + +static const struct snd_soc_dapm_widget cz_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), +}; + +static const struct snd_soc_dapm_route cz_audio_route[] = { + {"Headphones", NULL, "HPL"}, + {"Headphones", NULL, "HPR"}, + {"MIC", NULL, "Headset Mic"}, + {"Speakers", NULL, "Speaker"}, + {"PDM_DAT", NULL, "Int Mic"}, +}; + +static const struct snd_soc_dapm_route cz_rt5682_audio_route[] = { + {"Headphones", NULL, "HPOL"}, + {"Headphones", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Speakers", NULL, "Speaker"}, + {"PDM_DAT", NULL, "Int Mic"}, +}; + +static const struct snd_kcontrol_new cz_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Line Out"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static struct snd_soc_card cz_card = { + .name = "acpd7219m98357", + .owner = THIS_MODULE, + .dai_link = cz_dai_7219_98357, + .num_links = ARRAY_SIZE(cz_dai_7219_98357), + .dapm_widgets = cz_widgets, + .num_dapm_widgets = ARRAY_SIZE(cz_widgets), + .dapm_routes = cz_audio_route, + .num_dapm_routes = ARRAY_SIZE(cz_audio_route), + .controls = cz_mc_controls, + .num_controls = ARRAY_SIZE(cz_mc_controls), +}; + +static struct snd_soc_card cz_rt5682_card = { + .name = "acpr5682m98357", + .owner = THIS_MODULE, + .dai_link = cz_dai_5682_98357, + .num_links = ARRAY_SIZE(cz_dai_5682_98357), + .dapm_widgets = cz_widgets, + .num_dapm_widgets = ARRAY_SIZE(cz_widgets), + .dapm_routes = cz_rt5682_audio_route, + .controls = cz_mc_controls, + .num_controls = ARRAY_SIZE(cz_mc_controls), +}; + +static void *acp_soc_is_rltk_max(struct device *dev) +{ + const struct acpi_device_id *match; + + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) + return NULL; + return (void *)match->driver_data; +} + +static struct regulator_consumer_supply acp_da7219_supplies[] = { + REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"), +}; + +static struct regulator_init_data acp_da7219_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies), + .consumer_supplies = acp_da7219_supplies, +}; + +static struct regulator_config acp_da7219_cfg = { + .init_data = &acp_da7219_data, +}; + +static const struct regulator_ops acp_da7219_ops = { +}; + +static const struct regulator_desc acp_da7219_desc = { + .name = "reg-fixed-1.8V", + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &acp_da7219_ops, + .fixed_uV = 1800000, /* 1.8V */ + .n_voltages = 1, +}; + +static int cz_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + struct acp_platform_info *machine; + struct regulator_dev *rdev; + struct device *dev = &pdev->dev; + + card = (struct snd_soc_card *)acp_soc_is_rltk_max(dev); + if (!card) + return -ENODEV; + if (!strcmp(card->name, "acpd7219m98357")) { + acp_da7219_cfg.dev = &pdev->dev; + rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, + &acp_da7219_cfg); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register regulator: %d\n", + (int)PTR_ERR(rdev)); + return -EINVAL; + } + } + + machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), + GFP_KERNEL); + if (!machine) + return -ENOMEM; + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card(%s) failed\n", + card->name); + } + acp_bt_uart_enable = !device_property_read_bool(&pdev->dev, + "bt-pad-enable"); + return 0; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id cz_audio_acpi_match[] = { + { "AMD7219", (unsigned long)&cz_card }, + { "AMDI5682", (unsigned long)&cz_rt5682_card}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif + +static struct platform_driver cz_pcm_driver = { + .driver = { + .name = "cz-da7219-max98357a", + .acpi_match_table = ACPI_PTR(cz_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = cz_probe, +}; + +module_platform_driver(cz_pcm_driver); + +MODULE_AUTHOR("akshu.agrawal@amd.com"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("DA7219, RT5682 & MAX98357A audio support"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c new file mode 100644 index 000000000..9f3f11256 --- /dev/null +++ b/sound/soc/amd/acp-es8336.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Machine driver for AMD Stoney platform using ES8336 Codec + * + * Copyright 2022 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp.h" + +#define DUAL_CHANNEL 2 +#define DRV_NAME "acp2x_mach" +#define ST_JADEITE 1 +#define ES8336_PLL_FREQ (48000 * 256) + +static unsigned long acp2x_machine_id; +static struct snd_soc_jack st_jack; +static struct device *codec_dev; +static struct gpio_desc *gpio_pa; + +static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + gpiod_set_value_cansleep(gpio_pa, true); + else + gpiod_set_value_cansleep(gpio_pa, false); + + return 0; +} + +static struct snd_soc_jack_pin st_es8316_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int st_es8336_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card; + struct snd_soc_component *codec; + + codec = snd_soc_rtd_to_codec(rtd, 0)->component; + card = rtd->card; + + ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, + &st_jack, st_es8316_jack_pins, + ARRAY_SIZE(st_es8316_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + snd_jack_set_key(st_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + ret = snd_soc_component_set_jack(codec, &st_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + return 0; +} + +static const unsigned int st_channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int st_rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list st_constraints_rates = { + .count = ARRAY_SIZE(st_rates), + .list = st_rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list st_constraints_channels = { + .count = ARRAY_SIZE(st_channels), + .list = st_channels, + .mask = 0, +}; + +static int st_es8336_codec_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_card *card; + struct acp_platform_info *machine; + struct snd_soc_dai *codec_dai; + int ret; + + runtime = substream->runtime; + rtd = snd_soc_substream_to_rtd(substream); + card = rtd->card; + machine = snd_soc_card_get_drvdata(card); + codec_dai = snd_soc_rtd_to_codec(rtd, 0); + ret = snd_soc_dai_set_sysclk(codec_dai, 0, ES8336_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &st_constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &st_constraints_rates); + + machine->play_i2s_instance = I2S_MICSP_INSTANCE; + machine->cap_i2s_instance = I2S_MICSP_INSTANCE; + machine->capture_channel = CAP_CHANNEL0; + return 0; +} + +static const struct snd_soc_ops st_es8336_ops = { + .startup = st_es8336_codec_startup, +}; + +SND_SOC_DAILINK_DEF(designware1, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1"))); +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi"))); +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0"))); + +static struct snd_soc_dai_link st_dai_es8336[] = { + { + .name = "amdes8336", + .stream_name = "ES8336 HiFi Play", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, + .init = st_es8336_init, + .ops = &st_es8336_ops, + SND_SOC_DAILINK_REG(designware1, codec, platform), + }, +}; + +static const struct snd_soc_dapm_widget st_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic", NULL), + + SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0, + sof_es8316_speaker_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +}; + +static const struct snd_soc_dapm_route st_audio_route[] = { + {"Speaker", NULL, "HPOL"}, + {"Speaker", NULL, "HPOR"}, + {"Headphone", NULL, "HPOL"}, + {"Headphone", NULL, "HPOR"}, + {"MIC1", NULL, "Headset Mic"}, + {"MIC2", NULL, "Internal Mic"}, + {"Speaker", NULL, "Speaker Power"}, +}; + +static const struct snd_kcontrol_new st_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Internal Mic"), +}; + +static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, false }; +static const struct acpi_gpio_mapping acpi_es8336_gpios[] = { + { "pa-enable-gpios", &pa_enable_gpio, 1 }, + { } +}; + +static int st_es8336_late_probe(struct snd_soc_card *card) +{ + struct acpi_device *adev; + int ret; + + adev = acpi_dev_get_first_match_dev("ESSX8336", NULL, -1); + if (!adev) + return -ENODEV; + + codec_dev = acpi_get_first_physical_node(adev); + acpi_dev_put(adev); + 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) + dev_warn(card->dev, "Failed to add driver gpios\n"); + + gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW); + if (IS_ERR(gpio_pa)) { + ret = dev_err_probe(card->dev, PTR_ERR(gpio_pa), + "could not get pa-enable GPIO\n"); + put_device(codec_dev); + return ret; + } + return 0; +} + +static struct snd_soc_card st_card = { + .name = "acpes8336", + .owner = THIS_MODULE, + .dai_link = st_dai_es8336, + .num_links = ARRAY_SIZE(st_dai_es8336), + .dapm_widgets = st_widgets, + .num_dapm_widgets = ARRAY_SIZE(st_widgets), + .dapm_routes = st_audio_route, + .num_dapm_routes = ARRAY_SIZE(st_audio_route), + .controls = st_mc_controls, + .num_controls = ARRAY_SIZE(st_mc_controls), + .late_probe = st_es8336_late_probe, +}; + +static int st_es8336_quirk_cb(const struct dmi_system_id *id) +{ + acp2x_machine_id = ST_JADEITE; + return 1; +} + +static const struct dmi_system_id st_es8336_quirk_table[] = { + { + .callback = st_es8336_quirk_cb, + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMD"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jadeite"), + }, + }, + { + .callback = st_es8336_quirk_cb, + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "IP3 Technology CO.,Ltd."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN1D"), + }, + }, + { + .callback = st_es8336_quirk_cb, + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Standard"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN10"), + }, + }, + {} +}; + +static int st_es8336_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + struct acp_platform_info *machine; + + machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), GFP_KERNEL); + if (!machine) + return -ENOMEM; + + dmi_check_system(st_es8336_quirk_table); + switch (acp2x_machine_id) { + case ST_JADEITE: + card = &st_card; + st_card.dev = &pdev->dev; + break; + default: + return -ENODEV; + } + + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + ret = devm_snd_soc_register_card(&pdev->dev, &st_card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card(%s) failed\n", + card->name); + } + return 0; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id st_audio_acpi_match[] = { + {"AMDI8336", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, st_audio_acpi_match); +#endif + +static struct platform_driver st_mach_driver = { + .driver = { + .name = "st-es8316", + .acpi_match_table = ACPI_PTR(st_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = st_es8336_probe, +}; + +module_platform_driver(st_mach_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("st-es8316 audio support"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c new file mode 100644 index 000000000..ee7573720 --- /dev/null +++ b/sound/soc/amd/acp-pcm-dma.c @@ -0,0 +1,1440 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ALSA SoC PCM Driver for ACP 2.x + * + * Copyright 2014-2015 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "acp.h" + +#define DRV_NAME "acp_audio_dma" + +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 2 +#define PLAYBACK_MAX_PERIOD_SIZE 16384 +#define PLAYBACK_MIN_PERIOD_SIZE 1024 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 2 +#define CAPTURE_MAX_PERIOD_SIZE 16384 +#define CAPTURE_MIN_PERIOD_SIZE 1024 + +#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER + +#define ST_PLAYBACK_MAX_PERIOD_SIZE 4096 +#define ST_CAPTURE_MAX_PERIOD_SIZE ST_PLAYBACK_MAX_PERIOD_SIZE +#define ST_MAX_BUFFER (ST_PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) +#define ST_MIN_BUFFER ST_MAX_BUFFER + +#define DRV_NAME "acp_audio_dma" +bool acp_bt_uart_enable = true; +EXPORT_SYMBOL(acp_bt_uart_enable); + +static const struct snd_pcm_hardware acp_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_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .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 acp_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_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .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, +}; + +static const struct snd_pcm_hardware acp_st_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_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .buffer_bytes_max = ST_MAX_BUFFER, + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = ST_PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = PLAYBACK_MIN_NUM_PERIODS, + .periods_max = PLAYBACK_MAX_NUM_PERIODS, +}; + +static const struct snd_pcm_hardware acp_st_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_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .buffer_bytes_max = ST_MAX_BUFFER, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = ST_CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, +}; + +static u32 acp_reg_read(void __iomem *acp_mmio, u32 reg) +{ + return readl(acp_mmio + (reg * 4)); +} + +static void acp_reg_write(u32 val, void __iomem *acp_mmio, u32 reg) +{ + writel(val, acp_mmio + (reg * 4)); +} + +/* + * Configure a given dma channel parameters - enable/disable, + * number of descriptors, priority + */ +static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num, + u16 dscr_strt_idx, u16 num_dscrs, + enum acp_dma_priority_level priority_level) +{ + u32 dma_ctrl; + + /* disable the channel run field */ + dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRun_MASK; + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + + /* program a DMA channel with first descriptor to be processed. */ + acp_reg_write((ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx_MASK + & dscr_strt_idx), + acp_mmio, mmACP_DMA_DSCR_STRT_IDX_0 + ch_num); + + /* + * program a DMA channel with the number of descriptors to be + * processed in the transfer + */ + acp_reg_write(ACP_DMA_DSCR_CNT_0__DMAChDscrCnt_MASK & num_dscrs, + acp_mmio, mmACP_DMA_DSCR_CNT_0 + ch_num); + + /* set DMA channel priority */ + acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num); +} + +/* Initialize a dma descriptor in SRAM based on descriptor information passed */ +static void config_dma_descriptor_in_sram(void __iomem *acp_mmio, + u16 descr_idx, + acp_dma_dscr_transfer_t *descr_info) +{ + u32 sram_offset; + + sram_offset = (descr_idx * sizeof(acp_dma_dscr_transfer_t)); + + /* program the source base address. */ + acp_reg_write(sram_offset, acp_mmio, mmACP_SRBM_Targ_Idx_Addr); + acp_reg_write(descr_info->src, acp_mmio, mmACP_SRBM_Targ_Idx_Data); + /* program the destination base address. */ + acp_reg_write(sram_offset + 4, acp_mmio, mmACP_SRBM_Targ_Idx_Addr); + acp_reg_write(descr_info->dest, acp_mmio, mmACP_SRBM_Targ_Idx_Data); + + /* program the number of bytes to be transferred for this descriptor. */ + acp_reg_write(sram_offset + 8, acp_mmio, mmACP_SRBM_Targ_Idx_Addr); + acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data); +} + +static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num) +{ + u32 dma_ctrl; + int ret; + + /* clear the reset bit */ + dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK; + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + /* check the reset bit before programming configuration registers */ + ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4), + dma_ctrl, + !(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK), + 100, ACP_DMA_RESET_TIME); + if (ret < 0) + pr_err("Failed to clear reset of channel : %d\n", ch_num); +} + +/* + * Initialize the DMA descriptor information for transfer between + * system memory <-> ACP SRAM + */ +static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, + u32 size, int direction, + u32 pte_offset, u16 ch, + u32 sram_bank, u16 dma_dscr_idx, + u32 asic_type) +{ + u16 i; + acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL]; + + for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) { + dmadscr[i].xfer_val = 0; + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].dest = sram_bank + (i * (size / 2)); + dmadscr[i].src = ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + + (pte_offset * SZ_4K) + (i * (size / 2)); + switch (asic_type) { + case CHIP_STONEY: + dmadscr[i].xfer_val |= + (ACP_DMA_ATTR_DAGB_GARLIC_TO_SHAREDMEM << 16) | + (size / 2); + break; + default: + dmadscr[i].xfer_val |= + (ACP_DMA_ATTR_DAGB_ONION_TO_SHAREDMEM << 16) | + (size / 2); + } + } else { + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].src = sram_bank + (i * (size / 2)); + dmadscr[i].dest = + ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS + + (pte_offset * SZ_4K) + (i * (size / 2)); + switch (asic_type) { + case CHIP_STONEY: + dmadscr[i].xfer_val |= + (ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) | + (size / 2); + break; + default: + dmadscr[i].xfer_val |= + (ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) | + (size / 2); + } + } + config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, + &dmadscr[i]); + } + pre_config_reset(acp_mmio, ch); + config_acp_dma_channel(acp_mmio, ch, + dma_dscr_idx - 1, + NUM_DSCRS_PER_CHANNEL, + ACP_DMA_PRIORITY_LEVEL_NORMAL); +} + +/* + * Initialize the DMA descriptor information for transfer between + * ACP SRAM <-> I2S + */ +static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size, + int direction, u32 sram_bank, + u16 destination, u16 ch, + u16 dma_dscr_idx, u32 asic_type) +{ + u16 i; + acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL]; + + for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) { + dmadscr[i].xfer_val = 0; + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + dma_dscr_idx = dma_dscr_idx + i; + dmadscr[i].src = sram_bank + (i * (size / 2)); + /* dmadscr[i].dest is unused by hardware. */ + dmadscr[i].dest = 0; + dmadscr[i].xfer_val |= BIT(22) | (destination << 16) | + (size / 2); + } else { + dma_dscr_idx = dma_dscr_idx + i; + /* dmadscr[i].src is unused by hardware. */ + dmadscr[i].src = 0; + dmadscr[i].dest = + sram_bank + (i * (size / 2)); + dmadscr[i].xfer_val |= BIT(22) | + (destination << 16) | (size / 2); + } + config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, + &dmadscr[i]); + } + pre_config_reset(acp_mmio, ch); + /* Configure the DMA channel with the above descriptor */ + config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1, + NUM_DSCRS_PER_CHANNEL, + ACP_DMA_PRIORITY_LEVEL_NORMAL); +} + +/* Create page table entries in ACP SRAM for the allocated memory */ +static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr, + u16 num_of_pages, u32 pte_offset) +{ + u16 page_idx; + u32 low; + u32 high; + u32 offset; + + offset = ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET + (pte_offset * 8); + for (page_idx = 0; page_idx < (num_of_pages); page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + acp_reg_write((offset + (page_idx * 8)), + acp_mmio, mmACP_SRBM_Targ_Idx_Addr); + + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + acp_reg_write(low, acp_mmio, mmACP_SRBM_Targ_Idx_Data); + + /* Load the High address of page int ACP SRAM through SRBM */ + acp_reg_write((offset + (page_idx * 8) + 4), + acp_mmio, mmACP_SRBM_Targ_Idx_Addr); + + /* page enable in ACP */ + high |= BIT(31); + acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data); + + /* Move to next physically contiguous page */ + addr += PAGE_SIZE; + } +} + +static void config_acp_dma(void __iomem *acp_mmio, + struct audio_substream_data *rtd, + u32 asic_type) +{ + u16 ch_acp_sysmem, ch_acp_i2s; + + acp_pte_config(acp_mmio, rtd->dma_addr, rtd->num_of_pages, + rtd->pte_offset); + + if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) { + ch_acp_sysmem = rtd->ch1; + ch_acp_i2s = rtd->ch2; + } else { + ch_acp_i2s = rtd->ch1; + ch_acp_sysmem = rtd->ch2; + } + /* Configure System memory <-> ACP SRAM DMA descriptors */ + set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size, + rtd->direction, rtd->pte_offset, + ch_acp_sysmem, rtd->sram_bank, + rtd->dma_dscr_idx_1, asic_type); + /* Configure ACP SRAM <-> I2S DMA descriptors */ + set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size, + rtd->direction, rtd->sram_bank, + rtd->destination, ch_acp_i2s, + rtd->dma_dscr_idx_2, asic_type); +} + +static void acp_dma_cap_channel_enable(void __iomem *acp_mmio, + u16 cap_channel) +{ + u32 val, ch_reg, imr_reg, res_reg; + + switch (cap_channel) { + case CAP_CHANNEL1: + ch_reg = mmACP_I2SMICSP_RER1; + res_reg = mmACP_I2SMICSP_RCR1; + imr_reg = mmACP_I2SMICSP_IMR1; + break; + case CAP_CHANNEL0: + default: + ch_reg = mmACP_I2SMICSP_RER0; + res_reg = mmACP_I2SMICSP_RCR0; + imr_reg = mmACP_I2SMICSP_IMR0; + break; + } + val = acp_reg_read(acp_mmio, + mmACP_I2S_16BIT_RESOLUTION_EN); + if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) { + acp_reg_write(0x0, acp_mmio, ch_reg); + /* Set 16bit resolution on capture */ + acp_reg_write(0x2, acp_mmio, res_reg); + } + val = acp_reg_read(acp_mmio, imr_reg); + val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK; + val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK; + acp_reg_write(val, acp_mmio, imr_reg); + acp_reg_write(0x1, acp_mmio, ch_reg); +} + +static void acp_dma_cap_channel_disable(void __iomem *acp_mmio, + u16 cap_channel) +{ + u32 val, ch_reg, imr_reg; + + switch (cap_channel) { + case CAP_CHANNEL1: + imr_reg = mmACP_I2SMICSP_IMR1; + ch_reg = mmACP_I2SMICSP_RER1; + break; + case CAP_CHANNEL0: + default: + imr_reg = mmACP_I2SMICSP_IMR0; + ch_reg = mmACP_I2SMICSP_RER0; + break; + } + val = acp_reg_read(acp_mmio, imr_reg); + val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK; + val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK; + acp_reg_write(val, acp_mmio, imr_reg); + acp_reg_write(0x0, acp_mmio, ch_reg); +} + +/* Start a given DMA channel transfer */ +static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular) +{ + u32 dma_ctrl; + + /* read the dma control register and disable the channel run field */ + dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + + /* Invalidating the DAGB cache */ + acp_reg_write(1, acp_mmio, mmACP_DAGB_ATU_CTRL); + + /* + * configure the DMA channel and start the DMA transfer + * set dmachrun bit to start the transfer and enable the + * interrupt on completion of the dma transfer + */ + dma_ctrl |= ACP_DMA_CNTL_0__DMAChRun_MASK; + + switch (ch_num) { + case ACP_TO_I2S_DMA_CH_NUM: + case I2S_TO_ACP_DMA_CH_NUM: + case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM: + case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM: + case ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM: + dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK; + break; + default: + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChIOCEn_MASK; + break; + } + + /* enable for ACP to SRAM DMA channel */ + if (is_circular == true) + dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK; + else + dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK; + + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); +} + +/* Stop a given DMA channel transfer */ +static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num) +{ + u32 dma_ctrl; + u32 dma_ch_sts; + u32 count = ACP_DMA_RESET_TIME; + + dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + + /* + * clear the dma control register fields before writing zero + * in reset bit + */ + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRun_MASK; + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChIOCEn_MASK; + + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS); + + if (dma_ch_sts & BIT(ch_num)) { + /* + * set the reset bit for this channel to stop the dma + * transfer + */ + dma_ctrl |= ACP_DMA_CNTL_0__DMAChRst_MASK; + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); + } + + /* check the channel status bit for some time and return the status */ + while (true) { + dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS); + if (!(dma_ch_sts & BIT(ch_num))) { + /* + * clear the reset flag after successfully stopping + * the dma transfer and break from the loop + */ + dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK; + + acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + + ch_num); + break; + } + if (--count == 0) { + pr_err("Failed to stop ACP DMA channel : %d\n", ch_num); + return -ETIMEDOUT; + } + udelay(100); + } + return 0; +} + +static void acp_set_sram_bank_state(void __iomem *acp_mmio, u16 bank, + bool power_on) +{ + u32 val, req_reg, sts_reg, sts_reg_mask; + u32 loops = 1000; + + if (bank < 32) { + req_reg = mmACP_MEM_SHUT_DOWN_REQ_LO; + sts_reg = mmACP_MEM_SHUT_DOWN_STS_LO; + sts_reg_mask = 0xFFFFFFFF; + + } else { + bank -= 32; + req_reg = mmACP_MEM_SHUT_DOWN_REQ_HI; + sts_reg = mmACP_MEM_SHUT_DOWN_STS_HI; + sts_reg_mask = 0x0000FFFF; + } + + val = acp_reg_read(acp_mmio, req_reg); + if (val & (1 << bank)) { + /* bank is in off state */ + if (power_on == true) + /* request to on */ + val &= ~(1 << bank); + else + /* request to off */ + return; + } else { + /* bank is in on state */ + if (power_on == false) + /* request to off */ + val |= 1 << bank; + else + /* request to on */ + return; + } + acp_reg_write(val, acp_mmio, req_reg); + + while (acp_reg_read(acp_mmio, sts_reg) != sts_reg_mask) { + if (!loops--) { + pr_err("ACP SRAM bank %d state change failed\n", bank); + break; + } + cpu_relax(); + } +} + +/* Initialize and bring ACP hardware to default state. */ +static int acp_init(void __iomem *acp_mmio, u32 asic_type) +{ + u16 bank; + u32 val, count, sram_pte_offset; + + /* Assert Soft reset of ACP */ + val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET); + + val |= ACP_SOFT_RESET__SoftResetAud_MASK; + acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET); + + count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE; + while (true) { + val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET); + if (ACP_SOFT_RESET__SoftResetAudDone_MASK == + (val & ACP_SOFT_RESET__SoftResetAudDone_MASK)) + break; + if (--count == 0) { + pr_err("Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + + /* Enable clock to ACP and wait until the clock is enabled */ + val = acp_reg_read(acp_mmio, mmACP_CONTROL); + val = val | ACP_CONTROL__ClkEn_MASK; + acp_reg_write(val, acp_mmio, mmACP_CONTROL); + + count = ACP_CLOCK_EN_TIME_OUT_VALUE; + + while (true) { + val = acp_reg_read(acp_mmio, mmACP_STATUS); + if (val & (u32)0x1) + break; + if (--count == 0) { + pr_err("Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + + /* Deassert the SOFT RESET flags */ + val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET); + val &= ~ACP_SOFT_RESET__SoftResetAud_MASK; + acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET); + + /* For BT instance change pins from UART to BT */ + if (!acp_bt_uart_enable) { + val = acp_reg_read(acp_mmio, mmACP_BT_UART_PAD_SEL); + val |= ACP_BT_UART_PAD_SELECT_MASK; + acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL); + } + + /* initialize Onion control DAGB register */ + acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio, + mmACP_AXI2DAGB_ONION_CNTL); + + /* initialize Garlic control DAGB registers */ + acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio, + mmACP_AXI2DAGB_GARLIC_CNTL); + + sram_pte_offset = ACP_DAGB_GRP_SRAM_BASE_ADDRESS | + ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel_MASK | + ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel_MASK | + ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable_MASK; + acp_reg_write(sram_pte_offset, acp_mmio, mmACP_DAGB_BASE_ADDR_GRP_1); + acp_reg_write(ACP_PAGE_SIZE_4K_ENABLE, acp_mmio, + mmACP_DAGB_PAGE_SIZE_GRP_1); + + acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio, + mmACP_DMA_DESC_BASE_ADDR); + + /* Num of descriptors in SRAM 0x4, means 256 descriptors;(64 * 4) */ + acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR); + acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK, + acp_mmio, mmACP_EXTERNAL_INTR_CNTL); + + /* + * When ACP_TILE_P1 is turned on, all SRAM banks get turned on. + * Now, turn off all of them. This can't be done in 'poweron' of + * ACP pm domain, as this requires ACP to be initialized. + * For Stoney, Memory gating is disabled,i.e SRAM Banks + * won't be turned off. The default state for SRAM banks is ON. + * Setting SRAM bank state code skipped for STONEY platform. + */ + if (asic_type != CHIP_STONEY) { + for (bank = 1; bank < 48; bank++) + acp_set_sram_bank_state(acp_mmio, bank, false); + } + return 0; +} + +/* Deinitialize ACP */ +static int acp_deinit(void __iomem *acp_mmio) +{ + u32 val; + u32 count; + + /* Assert Soft reset of ACP */ + val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET); + + val |= ACP_SOFT_RESET__SoftResetAud_MASK; + acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET); + + count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE; + while (true) { + val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET); + if (ACP_SOFT_RESET__SoftResetAudDone_MASK == + (val & ACP_SOFT_RESET__SoftResetAudDone_MASK)) + break; + if (--count == 0) { + pr_err("Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + /* Disable ACP clock */ + val = acp_reg_read(acp_mmio, mmACP_CONTROL); + val &= ~ACP_CONTROL__ClkEn_MASK; + acp_reg_write(val, acp_mmio, mmACP_CONTROL); + + count = ACP_CLOCK_EN_TIME_OUT_VALUE; + + while (true) { + val = acp_reg_read(acp_mmio, mmACP_STATUS); + if (!(val & (u32)0x1)) + break; + if (--count == 0) { + pr_err("Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + return 0; +} + +/* ACP DMA irq handler routine for playback, capture usecases */ +static irqreturn_t dma_irq_handler(int irq, void *arg) +{ + u16 dscr_idx; + u32 intr_flag, ext_intr_status; + struct audio_drv_data *irq_data = arg; + void __iomem *acp_mmio; + bool valid_irq = false; + + acp_mmio = irq_data->acp_mmio; + + ext_intr_status = acp_reg_read(acp_mmio, mmACP_EXTERNAL_INTR_STAT); + intr_flag = (((ext_intr_status & + ACP_EXTERNAL_INTR_STAT__DMAIOCStat_MASK) >> + ACP_EXTERNAL_INTR_STAT__DMAIOCStat__SHIFT)); + + if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) { + valid_irq = true; + snd_pcm_period_elapsed(irq_data->play_i2ssp_stream); + acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16, + acp_mmio, mmACP_EXTERNAL_INTR_STAT); + } + + if ((intr_flag & BIT(ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM)) != 0) { + valid_irq = true; + snd_pcm_period_elapsed(irq_data->play_i2s_micsp_stream); + acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM)) << 16, + acp_mmio, mmACP_EXTERNAL_INTR_STAT); + } + + if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) { + valid_irq = true; + snd_pcm_period_elapsed(irq_data->play_i2sbt_stream); + acp_reg_write((intr_flag & + BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16, + acp_mmio, mmACP_EXTERNAL_INTR_STAT); + } + + if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) { + valid_irq = true; + if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) == + CAPTURE_START_DMA_DESCR_CH15) + dscr_idx = CAPTURE_END_DMA_DESCR_CH14; + else + dscr_idx = CAPTURE_START_DMA_DESCR_CH14; + config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx, + 1, 0); + acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false); + + snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream); + acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16, + acp_mmio, mmACP_EXTERNAL_INTR_STAT); + } + + if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) { + valid_irq = true; + if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) == + CAPTURE_START_DMA_DESCR_CH11) + dscr_idx = CAPTURE_END_DMA_DESCR_CH10; + else + dscr_idx = CAPTURE_START_DMA_DESCR_CH10; + config_acp_dma_channel(acp_mmio, + ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM, + dscr_idx, 1, 0); + acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM, + false); + + snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream); + acp_reg_write((intr_flag & + BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16, + acp_mmio, mmACP_EXTERNAL_INTR_STAT); + } + + if (valid_irq) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static int acp_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + u16 bank; + int ret = 0; + struct snd_pcm_runtime *runtime = substream->runtime; + struct audio_drv_data *intr_data = dev_get_drvdata(component->dev); + struct audio_substream_data *adata = + kzalloc_obj(struct audio_substream_data); + if (!adata) + return -ENOMEM; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (intr_data->asic_type) { + case CHIP_STONEY: + runtime->hw = acp_st_pcm_hardware_playback; + break; + default: + runtime->hw = acp_pcm_hardware_playback; + } + } else { + switch (intr_data->asic_type) { + case CHIP_STONEY: + runtime->hw = acp_st_pcm_hardware_capture; + break; + default: + runtime->hw = acp_pcm_hardware_capture; + } + } + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(adata); + return ret; + } + + adata->acp_mmio = intr_data->acp_mmio; + runtime->private_data = adata; + + /* + * Enable ACP irq, when neither playback or capture streams are + * active by the time when a new stream is being opened. + * This enablement is not required for another stream, if current + * stream is not closed + */ + if (!intr_data->play_i2ssp_stream && !intr_data->capture_i2ssp_stream && + !intr_data->play_i2sbt_stream && !intr_data->capture_i2sbt_stream && + !intr_data->play_i2s_micsp_stream) + acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* + * For Stoney, Memory gating is disabled,i.e SRAM Banks + * won't be turned off. The default state for SRAM banks is ON. + * Setting SRAM bank state code skipped for STONEY platform. + */ + if (intr_data->asic_type != CHIP_STONEY) { + for (bank = 1; bank <= 4; bank++) + acp_set_sram_bank_state(intr_data->acp_mmio, + bank, true); + } + } else { + if (intr_data->asic_type != CHIP_STONEY) { + for (bank = 5; bank <= 8; bank++) + acp_set_sram_bank_state(intr_data->acp_mmio, + bank, true); + } + } + + return 0; +} + +static int acp_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + uint64_t size; + u32 val = 0; + struct snd_pcm_runtime *runtime; + struct audio_substream_data *rtd; + struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream); + struct audio_drv_data *adata = dev_get_drvdata(component->dev); + struct snd_soc_card *card = prtd->card; + struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card); + + runtime = substream->runtime; + rtd = runtime->private_data; + + if (WARN_ON(!rtd)) + return -EINVAL; + + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + rtd->i2s_instance = pinfo->play_i2s_instance; + } else { + rtd->i2s_instance = pinfo->cap_i2s_instance; + rtd->capture_channel = pinfo->capture_channel; + } + } + if (adata->asic_type == CHIP_STONEY) { + val = acp_reg_read(adata->acp_mmio, + mmACP_I2S_16BIT_RESOLUTION_EN); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + val |= ACP_I2S_BT_16BIT_RESOLUTION_EN; + break; + case I2S_MICSP_INSTANCE: + val |= ACP_I2S_MICSP_16BIT_RESOLUTION_EN; + break; + case I2S_SP_INSTANCE: + default: + val |= ACP_I2S_SP_16BIT_RESOLUTION_EN; + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + val |= ACP_I2S_BT_16BIT_RESOLUTION_EN; + break; + case I2S_MICSP_INSTANCE: + case I2S_SP_INSTANCE: + default: + val |= ACP_I2S_MIC_16BIT_RESOLUTION_EN; + } + } + acp_reg_write(val, adata->acp_mmio, + mmACP_I2S_16BIT_RESOLUTION_EN); + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + rtd->pte_offset = ACP_ST_BT_PLAYBACK_PTE_OFFSET; + rtd->ch1 = SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM; + rtd->ch2 = ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM; + rtd->sram_bank = ACP_SRAM_BANK_3_ADDRESS; + rtd->destination = TO_BLUETOOTH; + rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH8; + rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH9; + rtd->byte_cnt_high_reg_offset = + mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH; + rtd->byte_cnt_low_reg_offset = + mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW; + adata->play_i2sbt_stream = substream; + break; + case I2S_MICSP_INSTANCE: + switch (adata->asic_type) { + case CHIP_STONEY: + rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET; + break; + default: + rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET; + } + rtd->ch1 = SYSRAM_TO_ACP_MICSP_INSTANCE_CH_NUM; + rtd->ch2 = ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM; + rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS; + rtd->destination = TO_ACP_I2S_2; + rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH4; + rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH5; + rtd->byte_cnt_high_reg_offset = + mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH; + rtd->byte_cnt_low_reg_offset = + mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW; + + adata->play_i2s_micsp_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + switch (adata->asic_type) { + case CHIP_STONEY: + rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET; + break; + default: + rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET; + } + rtd->ch1 = SYSRAM_TO_ACP_CH_NUM; + rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM; + rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS; + rtd->destination = TO_ACP_I2S_1; + rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12; + rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13; + rtd->byte_cnt_high_reg_offset = + mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH; + rtd->byte_cnt_low_reg_offset = + mmACP_I2S_TRANSMIT_BYTE_CNT_LOW; + adata->play_i2ssp_stream = substream; + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET; + rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM; + rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM; + rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS; + rtd->destination = FROM_BLUETOOTH; + rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10; + rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11; + rtd->byte_cnt_high_reg_offset = + mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH; + rtd->byte_cnt_low_reg_offset = + mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW; + rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11; + adata->capture_i2sbt_stream = substream; + break; + case I2S_MICSP_INSTANCE: + case I2S_SP_INSTANCE: + default: + rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET; + rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM; + rtd->ch2 = ACP_TO_SYSRAM_CH_NUM; + switch (adata->asic_type) { + case CHIP_STONEY: + rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET; + rtd->sram_bank = ACP_SRAM_BANK_2_ADDRESS; + break; + default: + rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET; + rtd->sram_bank = ACP_SRAM_BANK_5_ADDRESS; + } + rtd->destination = FROM_ACP_I2S_1; + rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14; + rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15; + rtd->byte_cnt_high_reg_offset = + mmACP_I2S_RECEIVED_BYTE_CNT_HIGH; + rtd->byte_cnt_low_reg_offset = + mmACP_I2S_RECEIVED_BYTE_CNT_LOW; + rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15; + adata->capture_i2ssp_stream = substream; + } + } + + size = params_buffer_bytes(params); + + acp_set_sram_bank_state(rtd->acp_mmio, 0, true); + /* Save for runtime private data */ + rtd->dma_addr = runtime->dma_addr; + rtd->order = get_order(size); + + /* Fill the page table entries in ACP SRAM */ + rtd->size = size; + rtd->num_of_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + rtd->direction = substream->stream; + + config_acp_dma(rtd->acp_mmio, rtd, adata->asic_type); + return 0; +} + +static u64 acp_get_byte_count(struct audio_substream_data *rtd) +{ + union acp_dma_count byte_count; + + byte_count.bcount.high = acp_reg_read(rtd->acp_mmio, + rtd->byte_cnt_high_reg_offset); + byte_count.bcount.low = acp_reg_read(rtd->acp_mmio, + rtd->byte_cnt_low_reg_offset); + return byte_count.bytescount; +} + +static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + u32 buffersize; + u32 pos = 0; + u64 bytescount = 0; + u16 dscr; + u32 period_bytes, delay; + + struct snd_pcm_runtime *runtime = substream->runtime; + struct audio_substream_data *rtd = runtime->private_data; + struct audio_drv_data *adata = dev_get_drvdata(component->dev); + + if (!rtd) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + period_bytes = frames_to_bytes(runtime, runtime->period_size); + bytescount = acp_get_byte_count(rtd); + if (bytescount >= rtd->bytescount) + bytescount -= rtd->bytescount; + if (bytescount < period_bytes) { + pos = 0; + } else { + dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); + if (dscr == rtd->dma_dscr_idx_1) + pos = period_bytes; + else + pos = 0; + } + if (bytescount > 0) { + delay = do_div(bytescount, period_bytes); + adata->delay += bytes_to_frames(runtime, delay); + } + } else { + buffersize = frames_to_bytes(runtime, runtime->buffer_size); + bytescount = acp_get_byte_count(rtd); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + } + return bytes_to_frames(runtime, pos); +} + +static snd_pcm_sframes_t acp_dma_delay(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct audio_drv_data *adata = dev_get_drvdata(component->dev); + snd_pcm_sframes_t delay = adata->delay; + + adata->delay = 0; + + return delay; +} + +static int acp_dma_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct audio_substream_data *rtd = runtime->private_data; + u16 ch_acp_sysmem, ch_acp_i2s; + + if (!rtd) + return -EINVAL; + + if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) { + ch_acp_sysmem = rtd->ch1; + ch_acp_i2s = rtd->ch2; + } else { + ch_acp_i2s = rtd->ch1; + ch_acp_sysmem = rtd->ch2; + } + config_acp_dma_channel(rtd->acp_mmio, + ch_acp_sysmem, + rtd->dma_dscr_idx_1, + NUM_DSCRS_PER_CHANNEL, 0); + config_acp_dma_channel(rtd->acp_mmio, + ch_acp_i2s, + rtd->dma_dscr_idx_2, + NUM_DSCRS_PER_CHANNEL, 0); + return 0; +} + +static int acp_dma_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + int ret; + + struct snd_pcm_runtime *runtime = substream->runtime; + struct audio_substream_data *rtd = runtime->private_data; + + if (!rtd) + return -EINVAL; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + rtd->bytescount = acp_get_byte_count(rtd); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (rtd->capture_channel == CAP_CHANNEL0) { + acp_dma_cap_channel_disable(rtd->acp_mmio, + CAP_CHANNEL1); + acp_dma_cap_channel_enable(rtd->acp_mmio, + CAP_CHANNEL0); + } + if (rtd->capture_channel == CAP_CHANNEL1) { + acp_dma_cap_channel_disable(rtd->acp_mmio, + CAP_CHANNEL0); + acp_dma_cap_channel_enable(rtd->acp_mmio, + CAP_CHANNEL1); + } + acp_dma_start(rtd->acp_mmio, rtd->ch1, true); + } else { + acp_dma_start(rtd->acp_mmio, rtd->ch1, true); + acp_dma_start(rtd->acp_mmio, rtd->ch2, true); + } + ret = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + acp_dma_stop(rtd->acp_mmio, rtd->ch2); + ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1); + break; + default: + ret = -EINVAL; + } + return ret; +} + +static int acp_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct audio_drv_data *adata = dev_get_drvdata(component->dev); + struct device *parent = component->dev->parent; + + switch (adata->asic_type) { + case CHIP_STONEY: + snd_pcm_set_managed_buffer_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV, + parent, + ST_MIN_BUFFER, + ST_MAX_BUFFER); + break; + default: + snd_pcm_set_managed_buffer_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV, + parent, + MIN_BUFFER, + MAX_BUFFER); + break; + } + return 0; +} + +static int acp_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + u16 bank; + struct snd_pcm_runtime *runtime = substream->runtime; + struct audio_substream_data *rtd = runtime->private_data; + struct audio_drv_data *adata = dev_get_drvdata(component->dev); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->play_i2sbt_stream = NULL; + break; + case I2S_MICSP_INSTANCE: + adata->play_i2s_micsp_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->play_i2ssp_stream = NULL; + /* + * For Stoney, Memory gating is disabled,i.e SRAM Banks + * won't be turned off. The default state for SRAM banks + * is ON.Setting SRAM bank state code skipped for STONEY + * platform. Added condition checks for Carrizo platform + * only. + */ + if (adata->asic_type != CHIP_STONEY) { + for (bank = 1; bank <= 4; bank++) + acp_set_sram_bank_state(adata->acp_mmio, + bank, false); + } + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->capture_i2sbt_stream = NULL; + break; + case I2S_MICSP_INSTANCE: + case I2S_SP_INSTANCE: + default: + adata->capture_i2ssp_stream = NULL; + if (adata->asic_type != CHIP_STONEY) { + for (bank = 5; bank <= 8; bank++) + acp_set_sram_bank_state(adata->acp_mmio, + bank, false); + } + } + } + + /* + * Disable ACP irq, when the current stream is being closed and + * another stream is also not active. + */ + if (!adata->play_i2ssp_stream && !adata->capture_i2ssp_stream && + !adata->play_i2sbt_stream && !adata->capture_i2sbt_stream && + !adata->play_i2s_micsp_stream) + acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); + kfree(rtd); + return 0; +} + +static const struct snd_soc_component_driver acp_asoc_platform = { + .name = DRV_NAME, + .open = acp_dma_open, + .close = acp_dma_close, + .hw_params = acp_dma_hw_params, + .trigger = acp_dma_trigger, + .pointer = acp_dma_pointer, + .delay = acp_dma_delay, + .prepare = acp_dma_prepare, + .pcm_new = acp_dma_new, +}; + +static int acp_audio_probe(struct platform_device *pdev) +{ + int status, irq; + struct audio_drv_data *audio_drv_data; + const u32 *pdata = pdev->dev.platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + audio_drv_data = devm_kzalloc(&pdev->dev, sizeof(struct audio_drv_data), + GFP_KERNEL); + if (!audio_drv_data) + return -ENOMEM; + + audio_drv_data->acp_mmio = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(audio_drv_data->acp_mmio)) + return PTR_ERR(audio_drv_data->acp_mmio); + + /* + * The following members gets populated in device 'open' + * function. Till then interrupts are disabled in 'acp_init' + * and device doesn't generate any interrupts. + */ + + audio_drv_data->play_i2ssp_stream = NULL; + audio_drv_data->capture_i2ssp_stream = NULL; + audio_drv_data->play_i2sbt_stream = NULL; + audio_drv_data->capture_i2sbt_stream = NULL; + audio_drv_data->play_i2s_micsp_stream = NULL; + + audio_drv_data->asic_type = *pdata; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + status = devm_request_irq(&pdev->dev, irq, dma_irq_handler, + 0, "ACP_IRQ", audio_drv_data); + if (status) { + dev_err(&pdev->dev, "ACP IRQ request failed\n"); + return status; + } + + dev_set_drvdata(&pdev->dev, audio_drv_data); + + /* Initialize the ACP */ + status = acp_init(audio_drv_data->acp_mmio, audio_drv_data->asic_type); + if (status) { + dev_err(&pdev->dev, "ACP Init failed status:%d\n", status); + return status; + } + + status = devm_snd_soc_register_component(&pdev->dev, + &acp_asoc_platform, NULL, 0); + if (status != 0) { + dev_err(&pdev->dev, "Fail to register ALSA platform device\n"); + return status; + } + + pm_runtime_set_autosuspend_delay(&pdev->dev, 10000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + return status; +} + +static void acp_audio_remove(struct platform_device *pdev) +{ + int status; + struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); + + status = acp_deinit(adata->acp_mmio); + if (status) + dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); + pm_runtime_disable(&pdev->dev); +} + +static int acp_pcm_resume(struct device *dev) +{ + u16 bank; + int status; + struct audio_substream_data *rtd; + struct audio_drv_data *adata = dev_get_drvdata(dev); + + status = acp_init(adata->acp_mmio, adata->asic_type); + if (status) { + dev_err(dev, "ACP Init failed status:%d\n", status); + return status; + } + + if (adata->play_i2ssp_stream && adata->play_i2ssp_stream->runtime) { + /* + * For Stoney, Memory gating is disabled,i.e SRAM Banks + * won't be turned off. The default state for SRAM banks is ON. + * Setting SRAM bank state code skipped for STONEY platform. + */ + if (adata->asic_type != CHIP_STONEY) { + for (bank = 1; bank <= 4; bank++) + acp_set_sram_bank_state(adata->acp_mmio, bank, + true); + } + rtd = adata->play_i2ssp_stream->runtime->private_data; + config_acp_dma(adata->acp_mmio, rtd, adata->asic_type); + } + if (adata->capture_i2ssp_stream && + adata->capture_i2ssp_stream->runtime) { + if (adata->asic_type != CHIP_STONEY) { + for (bank = 5; bank <= 8; bank++) + acp_set_sram_bank_state(adata->acp_mmio, bank, + true); + } + rtd = adata->capture_i2ssp_stream->runtime->private_data; + config_acp_dma(adata->acp_mmio, rtd, adata->asic_type); + } + if (adata->asic_type != CHIP_CARRIZO) { + if (adata->play_i2s_micsp_stream && + adata->play_i2s_micsp_stream->runtime) { + rtd = adata->play_i2s_micsp_stream->runtime->private_data; + config_acp_dma(adata->acp_mmio, rtd, adata->asic_type); + } + if (adata->play_i2sbt_stream && + adata->play_i2sbt_stream->runtime) { + rtd = adata->play_i2sbt_stream->runtime->private_data; + config_acp_dma(adata->acp_mmio, rtd, adata->asic_type); + } + if (adata->capture_i2sbt_stream && + adata->capture_i2sbt_stream->runtime) { + rtd = adata->capture_i2sbt_stream->runtime->private_data; + config_acp_dma(adata->acp_mmio, rtd, adata->asic_type); + } + } + acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int acp_pcm_runtime_suspend(struct device *dev) +{ + int status; + struct audio_drv_data *adata = dev_get_drvdata(dev); + + status = acp_deinit(adata->acp_mmio); + if (status) + dev_err(dev, "ACP Deinit failed status:%d\n", status); + acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int acp_pcm_runtime_resume(struct device *dev) +{ + int status; + struct audio_drv_data *adata = dev_get_drvdata(dev); + + status = acp_init(adata->acp_mmio, adata->asic_type); + if (status) { + dev_err(dev, "ACP Init failed status:%d\n", status); + return status; + } + acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); + return 0; +} + +static const struct dev_pm_ops acp_pm_ops = { + .resume = acp_pcm_resume, + .runtime_suspend = acp_pcm_runtime_suspend, + .runtime_resume = acp_pcm_runtime_resume, +}; + +static struct platform_driver acp_dma_driver = { + .probe = acp_audio_probe, + .remove = acp_audio_remove, + .driver = { + .name = DRV_NAME, + .pm = &acp_pm_ops, + }, +}; + +module_platform_driver(acp_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); +MODULE_DESCRIPTION("AMD ACP PCM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/sound/soc/amd/acp-rt5645.c b/sound/soc/amd/acp-rt5645.c new file mode 100644 index 000000000..5c38fa11d --- /dev/null +++ b/sound/soc/amd/acp-rt5645.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: MIT +/* + * Machine driver for AMD ACP Audio engine using Realtek RT5645 codec + * + * Copyright 2017 Advanced Micro Devices, Inc. + * + * This file is modified from rt288 machine driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../codecs/rt5645.h" + +#define CZ_PLAT_CLK 24000000 + +static struct snd_soc_jack cz_jack; +static struct snd_soc_jack_pin cz_jack_pins[] = { + { + .pin = "Headphones", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int cz_aif1_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, + CZ_PLAT_CLK, params_rate(params) * 512); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec pll: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_PLL1, + params_rate(params) * 512, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + return ret; +} + +static int cz_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card; + struct snd_soc_component *codec; + + codec = snd_soc_rtd_to_codec(rtd, 0)->component; + card = rtd->card; + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cz_jack, + cz_jack_pins, + ARRAY_SIZE(cz_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + rt5645_set_jack_detect(codec, &cz_jack, &cz_jack, &cz_jack); + + return 0; +} + +static const struct snd_soc_ops cz_aif1_ops = { + .hw_params = cz_aif1_hw_params, +}; + +SND_SOC_DAILINK_DEF(designware1, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1"))); +SND_SOC_DAILINK_DEF(designware2, + DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2"))); + +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5650:00", "rt5645-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0"))); + +static struct snd_soc_dai_link cz_dai_rt5650[] = { + { + .name = "amd-rt5645-play", + .stream_name = "RT5645_AIF1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .init = cz_init, + .ops = &cz_aif1_ops, + SND_SOC_DAILINK_REG(designware1, codec, platform), + }, + { + .name = "amd-rt5645-cap", + .stream_name = "RT5645_AIF1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .ops = &cz_aif1_ops, + SND_SOC_DAILINK_REG(designware2, codec, platform), + }, +}; + +static const struct snd_soc_dapm_widget cz_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), +}; + +static const struct snd_soc_dapm_route cz_audio_route[] = { + {"Headphones", NULL, "HPOL"}, + {"Headphones", NULL, "HPOR"}, + {"RECMIXL", NULL, "Headset Mic"}, + {"RECMIXR", NULL, "Headset Mic"}, + {"Speakers", NULL, "SPOL"}, + {"Speakers", NULL, "SPOR"}, + {"DMIC L2", NULL, "Int Mic"}, + {"DMIC R2", NULL, "Int Mic"}, +}; + +static const struct snd_kcontrol_new cz_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static struct snd_soc_card cz_card = { + .name = "acprt5650", + .owner = THIS_MODULE, + .dai_link = cz_dai_rt5650, + .num_links = ARRAY_SIZE(cz_dai_rt5650), + .dapm_widgets = cz_widgets, + .num_dapm_widgets = ARRAY_SIZE(cz_widgets), + .dapm_routes = cz_audio_route, + .num_dapm_routes = ARRAY_SIZE(cz_audio_route), + .controls = cz_mc_controls, + .num_controls = ARRAY_SIZE(cz_mc_controls), +}; + +static int cz_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + + card = &cz_card; + cz_card.dev = &pdev->dev; + platform_set_drvdata(pdev, card); + ret = devm_snd_soc_register_card(&pdev->dev, &cz_card); + if (ret) { + dev_err(&pdev->dev, + "devm_snd_soc_register_card(%s) failed: %d\n", + cz_card.name, ret); + return ret; + } + return 0; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id cz_audio_acpi_match[] = { + { "AMDI1002", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif + +static struct platform_driver cz_pcm_driver = { + .driver = { + .name = "cz-rt5645", + .acpi_match_table = ACPI_PTR(cz_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = cz_probe, +}; + +module_platform_driver(cz_pcm_driver); + +MODULE_AUTHOR("akshu.agrawal@amd.com"); +MODULE_DESCRIPTION("cz-rt5645 audio support"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h new file mode 100644 index 000000000..b29bef90f --- /dev/null +++ b/sound/soc/amd/acp.h @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ACP_HW_H +#define __ACP_HW_H + +#include "include/acp_2_2_d.h" +#include "include/acp_2_2_sh_mask.h" + +#define ACP_PAGE_SIZE_4K_ENABLE 0x02 + +#define ACP_PLAYBACK_PTE_OFFSET 10 +#define ACP_CAPTURE_PTE_OFFSET 0 + +/* Playback and Capture Offset for Stoney */ +#define ACP_ST_PLAYBACK_PTE_OFFSET 0x04 +#define ACP_ST_CAPTURE_PTE_OFFSET 0x00 +#define ACP_ST_BT_PLAYBACK_PTE_OFFSET 0x08 +#define ACP_ST_BT_CAPTURE_PTE_OFFSET 0x0c + +#define ACP_GARLIC_CNTL_DEFAULT 0x00000FB4 +#define ACP_ONION_CNTL_DEFAULT 0x00000FB4 + +#define ACP_PHYSICAL_BASE 0x14000 + +/* + * In case of I2S SP controller instance, Stoney uses SRAM bank 1 for + * playback and SRAM Bank 2 for capture where as in case of BT I2S + * Instance, Stoney uses SRAM Bank 3 for playback & SRAM Bank 4 will + * be used for capture. Carrizo uses I2S SP controller instance. SRAM Banks + * 1, 2, 3, 4 will be used for playback & SRAM Banks 5, 6, 7, 8 will be used + * for capture scenario. + */ +#define ACP_SRAM_BANK_1_ADDRESS 0x4002000 +#define ACP_SRAM_BANK_2_ADDRESS 0x4004000 +#define ACP_SRAM_BANK_3_ADDRESS 0x4006000 +#define ACP_SRAM_BANK_4_ADDRESS 0x4008000 +#define ACP_SRAM_BANK_5_ADDRESS 0x400A000 + +#define ACP_DMA_RESET_TIME 10000 +#define ACP_CLOCK_EN_TIME_OUT_VALUE 0x000000FF +#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF +#define ACP_DMA_COMPLETE_TIME_OUT_VALUE 0x000000FF + +#define ACP_SRAM_BASE_ADDRESS 0x4000000 +#define ACP_DAGB_GRP_SRAM_BASE_ADDRESS 0x4001000 +#define ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET 0x1000 +#define ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS 0x00000000 +#define ACP_INTERNAL_APERTURE_WINDOW_4_ADDRESS 0x01800000 + +#define TO_ACP_I2S_1 0x2 +#define TO_ACP_I2S_2 0x4 +#define TO_BLUETOOTH 0x3 +#define FROM_ACP_I2S_1 0xa +#define FROM_ACP_I2S_2 0xb +#define FROM_BLUETOOTH 0xb + +#define I2S_SP_INSTANCE 0x01 +#define I2S_BT_INSTANCE 0x02 +#define I2S_MICSP_INSTANCE 0x03 +#define CAP_CHANNEL0 0x00 +#define CAP_CHANNEL1 0x01 + +#define ACP_TILE_ON_MASK 0x03 +#define ACP_TILE_OFF_MASK 0x02 +#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f +#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20 + +#define ACP_TILE_P1_MASK 0x3e +#define ACP_TILE_P2_MASK 0x3d +#define ACP_TILE_DSP0_MASK 0x3b +#define ACP_TILE_DSP1_MASK 0x37 + +#define ACP_TILE_DSP2_MASK 0x2f +/* Playback DMA channels */ +#define SYSRAM_TO_ACP_CH_NUM 12 +#define ACP_TO_I2S_DMA_CH_NUM 13 + +/* Capture DMA channels */ +#define I2S_TO_ACP_DMA_CH_NUM 14 +#define ACP_TO_SYSRAM_CH_NUM 15 + +/* Playback DMA Channels for I2S BT instance */ +#define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM 8 +#define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9 + +/* Capture DMA Channels for I2S BT Instance */ +#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10 +#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11 + +/* Playback DMA channels for I2S MICSP instance */ +#define SYSRAM_TO_ACP_MICSP_INSTANCE_CH_NUM 4 +#define ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM 5 + +#define NUM_DSCRS_PER_CHANNEL 2 + +#define PLAYBACK_START_DMA_DESCR_CH12 0 +#define PLAYBACK_END_DMA_DESCR_CH12 1 +#define PLAYBACK_START_DMA_DESCR_CH13 2 +#define PLAYBACK_END_DMA_DESCR_CH13 3 + +#define CAPTURE_START_DMA_DESCR_CH14 4 +#define CAPTURE_END_DMA_DESCR_CH14 5 +#define CAPTURE_START_DMA_DESCR_CH15 6 +#define CAPTURE_END_DMA_DESCR_CH15 7 + +/* I2S BT Instance DMA Descriptors */ +#define PLAYBACK_START_DMA_DESCR_CH8 8 +#define PLAYBACK_END_DMA_DESCR_CH8 9 +#define PLAYBACK_START_DMA_DESCR_CH9 10 +#define PLAYBACK_END_DMA_DESCR_CH9 11 + +#define CAPTURE_START_DMA_DESCR_CH10 12 +#define CAPTURE_END_DMA_DESCR_CH10 13 +#define CAPTURE_START_DMA_DESCR_CH11 14 +#define CAPTURE_END_DMA_DESCR_CH11 15 + +/* I2S MICSP Instance DMA Descriptors */ +#define PLAYBACK_START_DMA_DESCR_CH4 0 +#define PLAYBACK_END_DMA_DESCR_CH4 1 +#define PLAYBACK_START_DMA_DESCR_CH5 2 +#define PLAYBACK_END_DMA_DESCR_CH5 3 + +#define mmACP_I2S_16BIT_RESOLUTION_EN 0x5209 +#define ACP_I2S_MIC_16BIT_RESOLUTION_EN 0x01 +#define ACP_I2S_MICSP_16BIT_RESOLUTION_EN 0x01 +#define ACP_I2S_SP_16BIT_RESOLUTION_EN 0x02 +#define ACP_I2S_BT_16BIT_RESOLUTION_EN 0x04 +#define ACP_BT_UART_PAD_SELECT_MASK 0x1 + +enum acp_dma_priority_level { + /* 0x0 Specifies the DMA channel is given normal priority */ + ACP_DMA_PRIORITY_LEVEL_NORMAL = 0x0, + /* 0x1 Specifies the DMA channel is given high priority */ + ACP_DMA_PRIORITY_LEVEL_HIGH = 0x1, + ACP_DMA_PRIORITY_LEVEL_FORCESIZE = 0xFF +}; + +struct audio_substream_data { + dma_addr_t dma_addr; + unsigned int order; + u16 num_of_pages; + u16 i2s_instance; + u16 capture_channel; + u16 direction; + u16 ch1; + u16 ch2; + u16 destination; + u16 dma_dscr_idx_1; + u16 dma_dscr_idx_2; + u32 pte_offset; + u32 sram_bank; + u32 byte_cnt_high_reg_offset; + u32 byte_cnt_low_reg_offset; + u32 dma_curr_dscr; + uint64_t size; + u64 bytescount; + void __iomem *acp_mmio; +}; + +struct audio_drv_data { + struct snd_pcm_substream *play_i2ssp_stream; + struct snd_pcm_substream *capture_i2ssp_stream; + struct snd_pcm_substream *play_i2sbt_stream; + struct snd_pcm_substream *capture_i2sbt_stream; + struct snd_pcm_substream *play_i2s_micsp_stream; + void __iomem *acp_mmio; + u32 asic_type; + snd_pcm_sframes_t delay; +}; + +/* + * this structure used for platform data transfer between machine driver + * and dma driver + */ +struct acp_platform_info { + u16 play_i2s_instance; + u16 cap_i2s_instance; + u16 capture_channel; +}; + +union acp_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +enum { + ACP_TILE_P1 = 0, + ACP_TILE_P2, + ACP_TILE_DSP0, + ACP_TILE_DSP1, + ACP_TILE_DSP2, +}; + +enum { + ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION = 0x0, + ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC = 0x1, + ACP_DMA_ATTR_DAGB_ONION_TO_SHAREDMEM = 0x8, + ACP_DMA_ATTR_DAGB_GARLIC_TO_SHAREDMEM = 0x9, + ACP_DMA_ATTR_FORCE_SIZE = 0xF +}; + +typedef struct acp_dma_dscr_transfer { + /* Specifies the source memory location for the DMA data transfer. */ + u32 src; + /* + * Specifies the destination memory location to where the data will + * be transferred. + */ + u32 dest; + /* + * Specifies the number of bytes need to be transferred + * from source to destination memory.Transfer direction & IOC enable + */ + u32 xfer_val; + /* Reserved for future use */ + u32 reserved; +} acp_dma_dscr_transfer_t; + +extern bool acp_bt_uart_enable; + +#endif /*__ACP_HW_H */ diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig new file mode 100644 index 000000000..a04c301df --- /dev/null +++ b/sound/soc/amd/acp/Kconfig @@ -0,0 +1,198 @@ +# 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) 2021 Advanced Micro Devices, Inc. All rights reserved. +# + +config SND_SOC_AMD_ACP_COMMON + tristate "AMD Audio ACP Common support" + select SND_AMD_ACP_CONFIG + depends on X86 && PCI + help + 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 + +config SND_SOC_ACPI_AMD_SDCA_QUIRKS + bool "AMD ACPI SDCA quirks" + depends on SND_SOC_ACPI_AMD_MATCH + depends on SND_SOC_SDCA + depends on SND_SOC_ACPI_AMD_MATCH = m || SND_SOC_SDCA = y + default y + help + Enable SDCA quirk support for AMD ACPI match tables. + This is compiled into the snd-soc-acpi-amd-match module. + +if SND_SOC_AMD_ACP_COMMON + +config SND_SOC_AMD_ACP_PDM + tristate + +config SND_SOC_AMD_ACP_LEGACY_COMMON + tristate + +config SND_SOC_AMD_ACP_I2S + tristate + +config SND_SOC_AMD_ACPI_MACH + tristate + +config SND_SOC_AMD_ACP_PCM + tristate + select SND_SOC_ACPI if ACPI + +config SND_SOC_AMD_ACP_PCI + tristate "AMD ACP PCI Driver Support" + depends on X86 && PCI + depends on ACPI + select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH + help + This options enables generic PCI driver for ACP device. + +config SND_AMD_ASOC_RENOIR + tristate "AMD ACP ASOC Renoir Support" + depends on ACPI + select SND_SOC_AMD_ACP_PCM + select SND_SOC_AMD_ACP_I2S + select SND_SOC_AMD_ACP_PDM + select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH + depends on X86 && PCI + help + This option enables Renoir I2S support on AMD platform. + +config SND_AMD_ASOC_REMBRANDT + tristate "AMD ACP ASOC Rembrandt Support" + depends on ACPI + select SND_SOC_AMD_ACP_PCM + select SND_SOC_AMD_ACP_I2S + select SND_SOC_AMD_ACP_PDM + select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH + depends on AMD_NODE + depends on X86 && PCI + help + This option enables Rembrandt I2S support on AMD platform. + Say Y if you want to enable AUDIO on Rembrandt + If unsure select "N". + +config SND_AMD_ASOC_ACP63 + tristate "AMD ACP ASOC ACP6.3 Support" + depends on X86 && PCI + depends on ACPI + depends on AMD_NODE + select SND_SOC_AMD_ACP_PCM + select SND_SOC_AMD_ACP_I2S + select SND_SOC_AMD_ACP_PDM + select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH + help + This option enables Acp6.3 I2S support on AMD platform. + Say Y if you want to enable AUDIO on ACP6.3 + If unsure select "N". + +config SND_AMD_ASOC_ACP70 + tristate "AMD ACP ASOC Acp7.0 Support" + depends on X86 && PCI + depends on ACPI + depends on AMD_NODE + select SND_SOC_AMD_ACP_PCM + select SND_SOC_AMD_ACP_I2S + select SND_SOC_AMD_ACP_PDM + select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH + help + This option enables Acp7.0 PDM support on AMD platform. + Say Y if you want to enable AUDIO on ACP7.0 + If unsure select "N". + +config SND_SOC_AMD_MACH_COMMON + tristate + depends on X86 && PCI && I2C + select SND_SOC_RT5682_I2C + select SND_SOC_DMIC + select SND_SOC_RT1019 + select SND_SOC_MAX98357A + select SND_SOC_RT5682S + select SND_SOC_NAU8825 + select SND_SOC_NAU8821 + select SND_SOC_MAX98388 + help + This option enables common Machine driver module for ACP. + +config SND_SOC_AMD_LEGACY_MACH + tristate "AMD Legacy Machine Driver Support" + depends on X86 && PCI && I2C + select SND_SOC_AMD_MACH_COMMON + help + This option enables legacy sound card support for ACP audio. + +config SND_SOC_AMD_SOF_MACH + tristate "AMD SOF Machine Driver Support" + depends on X86 && PCI && I2C + select SND_SOC_AMD_MACH_COMMON + 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 + select SND_SOC_RT722_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_RT1320_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 new file mode 100644 index 000000000..ab5f9dc87 --- /dev/null +++ b/sound/soc/amd/acp/Makefile @@ -0,0 +1,51 @@ +# 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) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#common acp driver +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 +snd-amd-acpi-mach-y := amd-acpi-mach.o + +#platform specific driver +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-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 amd-acp70-acpi-match.o +snd-soc-acpi-amd-match-$(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) += soc-acpi-amd-sdca-quirks.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 +obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o +obj-$(CONFIG_SND_SOC_AMD_ACP_LEGACY_COMMON) += snd-acp-legacy-common.o +obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o +obj-$(CONFIG_SND_SOC_AMD_ACPI_MACH) += snd-amd-acpi-mach.o + +obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o +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 new file mode 100644 index 000000000..bb58a9d34 --- /dev/null +++ b/sound/soc/amd/acp/acp-i2s.c @@ -0,0 +1,707 @@ +// 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) 2021 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// + +/* + * Generic Hardware interface for ACP Audio I2S controller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "amd.h" + +#define DRV_NAME "acp_i2s_playcap" +#define I2S_MASTER_MODE_ENABLE 1 +#define LRCLK_DIV_FIELD GENMASK(10, 2) +#define BCLK_DIV_FIELD GENMASK(23, 11) +#define ACP63_LRCLK_DIV_FIELD GENMASK(12, 2) +#define ACP63_BCLK_DIV_FIELD GENMASK(23, 13) + +static inline void acp_set_i2s_clk(struct acp_chip_info *chip, int dai_id) +{ + u32 i2s_clk_reg, val; + + switch (dai_id) { + case I2S_SP_INSTANCE: + i2s_clk_reg = ACP_I2STDM0_MSTRCLKGEN; + break; + case I2S_BT_INSTANCE: + i2s_clk_reg = ACP_I2STDM1_MSTRCLKGEN; + break; + case I2S_HS_INSTANCE: + i2s_clk_reg = ACP_I2STDM2_MSTRCLKGEN; + break; + default: + i2s_clk_reg = ACP_I2STDM0_MSTRCLKGEN; + break; + } + + val = I2S_MASTER_MODE_ENABLE; + if (chip->tdm_mode) + val |= BIT(1); + + switch (chip->acp_rev) { + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_PCI_ID: + val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, chip->lrclk_div); + val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, chip->bclk_div); + break; + default: + val |= FIELD_PREP(LRCLK_DIV_FIELD, chip->lrclk_div); + val |= FIELD_PREP(BCLK_DIV_FIELD, chip->bclk_div); + } + writel(val, chip->base + i2s_clk_reg); +} + +static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct device *dev = cpu_dai->component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + int mode; + + mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + switch (mode) { + case SND_SOC_DAIFMT_I2S: + chip->tdm_mode = TDM_DISABLE; + break; + case SND_SOC_DAIFMT_DSP_A: + chip->tdm_mode = TDM_ENABLE; + break; + default: + return -EINVAL; + } + return 0; +} + +static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask, + int slots, int slot_width) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip; + struct acp_stream *stream; + int slot_len, no_of_slots; + + chip = dev_get_drvdata(dev->parent); + switch (slot_width) { + case SLOT_WIDTH_8: + slot_len = 8; + break; + case SLOT_WIDTH_16: + slot_len = 16; + break; + case SLOT_WIDTH_24: + slot_len = 24; + break; + case SLOT_WIDTH_32: + slot_len = 0; + break; + default: + dev_err(dev, "Unsupported bitdepth %d\n", slot_width); + return -EINVAL; + } + + 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 ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_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, "Unknown chip revision %d\n", chip->acp_rev); + return -EINVAL; + } + + slots = no_of_slots; + + spin_lock_irq(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + if (dai->id != stream->dai_id) + continue; + switch (chip->acp_rev) { + case ACP_RN_PCI_ID: + case ACP_RMB_PCI_ID: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + chip->tdm_tx_fmt[stream->dai_id - 1] = + FRM_LEN | (slots << 15) | (slot_len << 18); + else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) + chip->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: + case ACP72_PCI_ID: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + chip->tdm_tx_fmt[stream->dai_id - 1] = + FRM_LEN | (slots << 13) | (slot_len << 18); + else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) + chip->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(&chip->acp_lock); + return -EINVAL; + } + } + spin_unlock_irq(&chip->acp_lock); + return 0; +} + +static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip; + struct acp_resource *rsrc; + u32 val; + u32 xfer_resolution; + u32 reg_val, fmt_reg, tdm_fmt; + u32 lrclk_div_val, bclk_div_val; + + chip = dev_get_drvdata(dev->parent); + rsrc = chip->rsrc; + + /* These values are as per Hardware Spec */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + xfer_resolution = 0x0; + break; + case SNDRV_PCM_FORMAT_S16_LE: + xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + xfer_resolution = 0x05; + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_ITER; + fmt_reg = ACP_BTTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_ITER; + fmt_reg = ACP_I2STDM_TXFRMT; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + fmt_reg = ACP_HSTDM_TXFRMT; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + chip->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution; + } else { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_IRER; + fmt_reg = ACP_BTTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_IRER; + fmt_reg = ACP_I2STDM_RXFRMT; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + fmt_reg = ACP_HSTDM_RXFRMT; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + chip->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution; + } + + val = readl(chip->base + reg_val); + val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK; + val = val | (xfer_resolution << 3); + writel(val, chip->base + reg_val); + + if (chip->tdm_mode) { + val = readl(chip->base + reg_val); + writel(val | BIT(1), chip->base + reg_val); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + tdm_fmt = chip->tdm_tx_fmt[dai->driver->id - 1]; + else + tdm_fmt = chip->tdm_rx_fmt[dai->driver->id - 1]; + writel(tdm_fmt, chip->base + fmt_reg); + } + + if (rsrc->soc_mclk) { + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 768; + break; + case 16000: + bclk_div_val = 384; + break; + case 24000: + bclk_div_val = 256; + break; + case 32000: + bclk_div_val = 192; + break; + case 44100: + case 48000: + bclk_div_val = 128; + break; + case 88200: + case 96000: + bclk_div_val = 64; + break; + case 192000: + bclk_div_val = 32; + break; + default: + return -EINVAL; + } + lrclk_div_val = 32; + break; + case SNDRV_PCM_FORMAT_S32_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 384; + break; + case 16000: + bclk_div_val = 192; + break; + case 24000: + bclk_div_val = 128; + break; + case 32000: + bclk_div_val = 96; + break; + case 44100: + case 48000: + bclk_div_val = 64; + break; + case 88200: + case 96000: + bclk_div_val = 32; + break; + case 192000: + bclk_div_val = 16; + break; + default: + return -EINVAL; + } + lrclk_div_val = 64; + break; + 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; + } + chip->lrclk_div = lrclk_div_val; + chip->bclk_div = bclk_div_val; + } + return 0; +} + +static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + struct acp_stream *stream = substream->runtime->private_data; + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_resource *rsrc = chip->rsrc; + u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg; + + period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); + buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + stream->bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(chip); + reg_val = ACP_BTTDM_ITER; + ier_val = ACP_BTTDM_IER; + buf_reg = ACP_BT_TX_RINGBUFSIZE(chip); + break; + case I2S_SP_INSTANCE: + water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(chip); + reg_val = ACP_I2STDM_ITER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_TX_RINGBUFSIZE(chip); + break; + case I2S_HS_INSTANCE: + water_val = ACP_HS_TX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_ITER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_TX_RINGBUFSIZE; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + } else { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(chip); + reg_val = ACP_BTTDM_IRER; + ier_val = ACP_BTTDM_IER; + buf_reg = ACP_BT_RX_RINGBUFSIZE(chip); + break; + case I2S_SP_INSTANCE: + water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(chip); + reg_val = ACP_I2STDM_IRER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_RX_RINGBUFSIZE(chip); + break; + case I2S_HS_INSTANCE: + water_val = ACP_HS_RX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_IRER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_RX_RINGBUFSIZE; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + } + + writel(period_bytes, chip->base + water_val); + writel(buf_size, chip->base + buf_reg); + if (rsrc->soc_mclk) + acp_set_i2s_clk(chip, dai->driver->id); + val = readl(chip->base + reg_val); + val = val | BIT(0); + writel(val, chip->base + reg_val); + writel(1, chip->base + ier_val); + return 0; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_ITER; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_ITER; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + + } else { + switch (dai->driver->id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_IRER; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_IRER; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + } + val = readl(chip->base + reg_val); + val = val & ~BIT(0); + writel(val, chip->base + reg_val); + + if (!(readl(chip->base + ACP_BTTDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_BTTDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_BTTDM_IER); + if (!(readl(chip->base + ACP_I2STDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_I2STDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_I2STDM_IER); + if (!(readl(chip->base + ACP_HSTDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_HSTDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_HSTDM_IER); + return 0; + default: + return -EINVAL; + } + + return 0; +} + +static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_resource *rsrc = chip->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; + + switch (dai->driver->id) { + case I2S_SP_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + SP_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip); + + 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, chip->base + ACP_I2S_TX_RINGBUFADDR(chip)); + } else { + reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + SP_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip); + + 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, chip->base + ACP_I2S_RX_RINGBUFADDR(chip)); + } + break; + case I2S_BT_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_BT_TX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + BT_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip); + + 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, chip->base + ACP_BT_TX_RINGBUFADDR(chip)); + } else { + reg_dma_size = ACP_BT_RX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + BT_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip); + + 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, chip->base + ACP_BT_RX_RINGBUFADDR(chip)); + } + break; + case I2S_HS_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_HS_TX_DMA_SIZE; + acp_fifo_addr = rsrc->sram_pte_offset + + HS_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_TX_FIFOADDR; + reg_fifo_size = ACP_HS_TX_FIFOSIZE; + + 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, chip->base + ACP_HS_TX_RINGBUFADDR); + } else { + reg_dma_size = ACP_HS_RX_DMA_SIZE; + acp_fifo_addr = rsrc->sram_pte_offset + + HS_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_RX_FIFOADDR; + reg_fifo_size = ACP_HS_RX_FIFOSIZE; + + 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, chip->base + ACP_HS_RX_RINGBUFADDR); + } + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + + writel(DMA_SIZE, chip->base + reg_dma_size); + writel(acp_fifo_addr, chip->base + reg_fifo_addr); + writel(FIFO_SIZE, chip->base + reg_fifo_size); + + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | + BIT(BT_RX_THRESHOLD(rsrc->offset)) | + BIT(I2S_TX_THRESHOLD(rsrc->offset)) | + BIT(BT_TX_THRESHOLD(rsrc->offset)) | + BIT(HS_RX_THRESHOLD(rsrc->offset)) | + BIT(HS_TX_THRESHOLD(rsrc->offset)); + + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + + return 0; +} + +static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct acp_stream *stream = substream->runtime->private_data; + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_resource *rsrc = chip->rsrc; + unsigned int dir = substream->stream; + unsigned int irq_bit = 0; + + switch (dai->driver->id) { + case I2S_SP_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET; + stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET; + } else { + irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET; + stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET; + } + break; + case I2S_BT_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET; + stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET; + } else { + irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET; + stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET; + } + break; + case I2S_HS_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET; + stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET; + } else { + irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset)); + stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET; + stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET; + } + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + + /* Save runtime dai configuration in stream */ + stream->id = dai->driver->id + dir; + stream->dai_id = dai->driver->id; + stream->irq_bit = irq_bit; + stream->dir = substream->stream; + + return 0; +} + +static const u64 acp_i2s_selectable_formats = + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_DSP_A; + +const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { + .startup = acp_i2s_startup, + .hw_params = acp_i2s_hwparams, + .prepare = acp_i2s_prepare, + .trigger = acp_i2s_trigger, + .set_fmt = acp_i2s_set_fmt, + .set_tdm_slot = acp_i2s_set_tdm_slot, + .auto_selectable_formats = &acp_i2s_selectable_formats, + .num_auto_selectable_formats = 1, +}; +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 new file mode 100644 index 000000000..4e477c48d --- /dev/null +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -0,0 +1,665 @@ +// 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. +// +// Authors: Syed Saba Kareem +// + +/* + * Common file to be used by amd platforms + */ + +#include "amd.h" +#include +#include +#include + +#include "../mach-config.h" + +#define ACP_RENOIR_PDM_ADDR 0x02 +#define ACP_REMBRANDT_PDM_ADDR 0x03 +#define ACP63_PDM_ADDR 0x02 +#define ACP70_PDM_ADDR 0x02 + +struct acp_resource rn_rsrc = { + .offset = 20, + .no_of_ctrls = 1, + .irqp_used = 0, + .irq_reg_offset = 0x1800, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x02052800, +}; +EXPORT_SYMBOL_NS_GPL(rn_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource rmb_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; +EXPORT_SYMBOL_NS_GPL(rmb_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource acp63_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; +EXPORT_SYMBOL_NS_GPL(acp63_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource acp70_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, +}; +EXPORT_SYMBOL_NS_GPL(acp70_rsrc, "SND_SOC_ACP_COMMON"); + +static const struct snd_acp_hw_ops acp_common_hw_ops = { + /* ACP hardware initilizations */ + .acp_init = acp_init, + .acp_deinit = acp_deinit, + + /* ACP Interrupts*/ + .irq = acp_irq_handler, + .en_interrupts = acp_enable_interrupts, + .dis_interrupts = acp_disable_interrupts, +}; + +irqreturn_t acp_irq_handler(int irq, void *data) +{ + struct acp_chip_info *chip = data; + struct acp_resource *rsrc = chip->rsrc; + struct acp_stream *stream; + u16 i2s_flag = 0; + u32 ext_intr_stat, ext_intr_stat1; + + if (rsrc->no_of_ctrls == 2) + ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1))); + + ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + if (ext_intr_stat & stream->irq_bit) { + writel(stream->irq_bit, + ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + snd_pcm_period_elapsed(stream->substream); + i2s_flag = 1; + } + if (chip->rsrc->no_of_ctrls == 2) { + if (ext_intr_stat1 & stream->irq_bit) { + writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip, + (rsrc->irqp_used - 1))); + snd_pcm_period_elapsed(stream->substream); + i2s_flag = 1; + } + } + } + spin_unlock(&chip->acp_lock); + if (i2s_flag) + return IRQ_HANDLED; + + return IRQ_NONE; +} + +int acp_enable_interrupts(struct acp_chip_info *chip) +{ + struct acp_resource *rsrc; + u32 ext_intr_ctrl; + + rsrc = chip->rsrc; + writel(0x01, ACP_EXTERNAL_INTR_ENB(chip)); + ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + ext_intr_ctrl |= ACP_ERROR_MASK; + writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON"); + +int acp_disable_interrupts(struct acp_chip_info *chip) +{ + struct acp_resource *rsrc; + + rsrc = chip->rsrc; + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + writel(0x00, ACP_EXTERNAL_INTR_ENB(chip)); + + return 0; +} +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) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct acp_stream *stream = runtime->private_data; + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + + u32 physical_addr, pdm_size, period_bytes; + + period_bytes = frames_to_bytes(runtime, runtime->period_size); + pdm_size = frames_to_bytes(runtime, runtime->buffer_size); + physical_addr = stream->reg_offset + MEM_WINDOW_START; + + /* Init ACP PDM Ring buffer */ + writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR); + writel(pdm_size, chip->base + ACP_WOV_RX_RINGBUFSIZE); + writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); +} + +static void set_acp_pdm_clk(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + unsigned int pdm_ctrl; + + /* Enable default ACP PDM clk */ + writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL); + pdm_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL); + pdm_ctrl |= PDM_MISC_CTRL_MASK; + writel(pdm_ctrl, chip->base + ACP_WOV_MISC_CTRL); + set_acp_pdm_ring_buffer(substream, dai); +} + +void restore_acp_pdm_params(struct snd_pcm_substream *substream, + struct acp_chip_info *chip) +{ + struct snd_soc_dai *dai; + struct snd_soc_pcm_runtime *soc_runtime; + u32 ext_int_ctrl; + + soc_runtime = snd_soc_substream_to_rtd(substream); + dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + + /* Programming channel mask and sampling rate */ + writel(chip->ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS); + writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR); + + /* Enabling ACP Pdm interuppts */ + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); + set_acp_pdm_clk(substream, dai); +} +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) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + struct acp_resource *rsrc = chip->rsrc; + struct acp_stream *stream = substream->runtime->private_data; + u32 reg_dma_size, reg_fifo_size, reg_fifo_addr; + u32 phy_addr, acp_fifo_addr, ext_int_ctrl; + unsigned int dir = substream->stream; + + switch (dai->driver->id) { + case I2S_SP_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + SP_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip); + 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, chip->base + ACP_I2S_TX_RINGBUFADDR(chip)); + } else { + reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + SP_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip); + 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, chip->base + ACP_I2S_RX_RINGBUFADDR(chip)); + } + break; + case I2S_BT_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_BT_TX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + BT_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip); + 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, chip->base + ACP_BT_TX_RINGBUFADDR(chip)); + } else { + reg_dma_size = ACP_BT_RX_DMA_SIZE(chip); + acp_fifo_addr = rsrc->sram_pte_offset + + BT_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip); + if (chip->acp_rev >= ACP70_PCI_ID) + phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START; + else + phy_addr = I2S_BT_RX_MEM_WINDOW_START + stream->reg_offset; + writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip)); + } + break; + case I2S_HS_INSTANCE: + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + reg_dma_size = ACP_HS_TX_DMA_SIZE; + acp_fifo_addr = rsrc->sram_pte_offset + + HS_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_TX_FIFOADDR; + reg_fifo_size = ACP_HS_TX_FIFOSIZE; + 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, chip->base + ACP_HS_TX_RINGBUFADDR); + } else { + reg_dma_size = ACP_HS_RX_DMA_SIZE; + acp_fifo_addr = rsrc->sram_pte_offset + + HS_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_RX_FIFOADDR; + reg_fifo_size = ACP_HS_RX_FIFOSIZE; + 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, chip->base + ACP_HS_RX_RINGBUFADDR); + } + break; + default: + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); + return -EINVAL; + } + + writel(DMA_SIZE, chip->base + reg_dma_size); + writel(acp_fifo_addr, chip->base + reg_fifo_addr); + writel(FIFO_SIZE, chip->base + reg_fifo_size); + + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | + BIT(BT_RX_THRESHOLD(rsrc->offset)) | + BIT(I2S_TX_THRESHOLD(rsrc->offset)) | + BIT(BT_TX_THRESHOLD(rsrc->offset)) | + BIT(HS_RX_THRESHOLD(rsrc->offset)) | + BIT(HS_TX_THRESHOLD(rsrc->offset)); + + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + return 0; +} + +int restore_acp_i2s_params(struct snd_pcm_substream *substream, + struct acp_chip_info *chip, + struct acp_stream *stream) +{ + struct snd_soc_dai *dai; + struct snd_soc_pcm_runtime *soc_runtime; + u32 tdm_fmt, reg_val, fmt_reg, val; + + soc_runtime = snd_soc_substream_to_rtd(substream); + dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + tdm_fmt = chip->tdm_tx_fmt[stream->dai_id - 1]; + switch (stream->dai_id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_ITER; + fmt_reg = ACP_BTTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_ITER; + fmt_reg = ACP_I2STDM_TXFRMT; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + fmt_reg = ACP_HSTDM_TXFRMT; + break; + default: + pr_err("Invalid dai id %x\n", stream->dai_id); + return -EINVAL; + } + val = chip->xfer_tx_resolution[stream->dai_id - 1] << 3; + } else { + tdm_fmt = chip->tdm_rx_fmt[stream->dai_id - 1]; + switch (stream->dai_id) { + case I2S_BT_INSTANCE: + reg_val = ACP_BTTDM_IRER; + fmt_reg = ACP_BTTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + reg_val = ACP_I2STDM_IRER; + fmt_reg = ACP_I2STDM_RXFRMT; + break; + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + fmt_reg = ACP_HSTDM_RXFRMT; + break; + default: + pr_err("Invalid dai id %x\n", stream->dai_id); + return -EINVAL; + } + val = chip->xfer_rx_resolution[stream->dai_id - 1] << 3; + } + writel(val, chip->base + reg_val); + if (chip->tdm_mode == TDM_ENABLE) { + writel(tdm_fmt, chip->base + fmt_reg); + val = readl(chip->base + reg_val); + writel(val | 0x2, chip->base + reg_val); + } + return set_acp_i2s_dma_fifo(substream, dai); +} +EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, "SND_SOC_ACP_COMMON"); + +static int acp_power_on(struct acp_chip_info *chip) +{ + u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg; + void __iomem *base; + + base = chip->base; + switch (chip->acp_rev) { + case ACP_RN_PCI_ID: + acp_pgfsm_stat_reg = ACP_PGFSM_STATUS; + acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL; + break; + case ACP_RMB_PCI_ID: + acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS; + acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL; + break; + case ACP63_PCI_ID: + acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS; + acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL; + break; + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_PCI_ID: + acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS; + acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL; + break; + default: + return -EINVAL; + } + + val = readl(base + acp_pgfsm_stat_reg); + if (val == ACP_POWERED_ON) + return 0; + + if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) + writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg); + + return readl_poll_timeout(base + acp_pgfsm_stat_reg, val, + !val, DELAY_US, ACP_TIMEOUT); +} + +static int acp_reset(void __iomem *base) +{ + u32 val; + int ret; + + writel(1, base + ACP_SOFT_RESET); + ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK, + DELAY_US, ACP_TIMEOUT); + if (ret) + return ret; + + writel(0, base + ACP_SOFT_RESET); + return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); +} + +int acp_init(struct acp_chip_info *chip) +{ + int ret; + + /* power on */ + ret = acp_power_on(chip); + if (ret) { + pr_err("ACP power on failed\n"); + return ret; + } + writel(0x01, chip->base + ACP_CONTROL); + + /* Reset */ + ret = acp_reset(chip->base); + if (ret) { + 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"); + +int acp_deinit(struct acp_chip_info *chip) +{ + int ret; + + /* Reset */ + ret = acp_reset(chip->base); + if (ret) + return ret; + + 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"); +int acp_machine_select(struct acp_chip_info *chip) +{ + struct snd_soc_acpi_mach *mach; + int size, platform; + + if (chip->flag == FLAG_AMD_LEGACY_ONLY_DMIC && chip->is_pdm_dev) { + platform = chip->acp_rev; + chip->mach_dev = platform_device_register_data(chip->dev, "acp-pdm-mach", + PLATFORM_DEVID_NONE, &platform, + sizeof(platform)); + } else { + size = sizeof(*chip->machines); + mach = snd_soc_acpi_find_machine(chip->machines); + if (!mach) { + dev_err(chip->dev, "warning: No matching ASoC machine driver found\n"); + return -EINVAL; + } + mach->mach_params.subsystem_rev = chip->acp_rev; + chip->mach_dev = platform_device_register_data(chip->dev, mach->drv_name, + PLATFORM_DEVID_NONE, mach, size); + } + if (IS_ERR(chip->mach_dev)) + dev_warn(chip->dev, "Unable to register Machine device\n"); + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON"); + +static void check_acp3x_config(struct acp_chip_info *chip) +{ + 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) { + 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: + 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: + break; + } +} + +void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) +{ + struct acpi_device *pdm_dev; + const union acpi_object *obj; + acpi_handle handle; + acpi_integer dmic_status; + u32 pdm_addr, ret; + + switch (chip->acp_rev) { + case ACP_RN_PCI_ID: + pdm_addr = ACP_RENOIR_PDM_ADDR; + check_acp3x_config(chip); + break; + case ACP_RMB_PCI_ID: + pdm_addr = ACP_REMBRANDT_PDM_ADDR; + check_acp6x_config(chip); + break; + case ACP63_PCI_ID: + pdm_addr = ACP63_PDM_ADDR; + check_acp6x_config(chip); + break; + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_PCI_ID: + pdm_addr = ACP70_PDM_ADDR; + check_acp70_config(chip); + break; + default: + break; + } + + 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; + } + + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (!ACPI_FAILURE(ret)) + chip->is_pdm_dev = dmic_status; + } +} +EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp31_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp31_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp31_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp31_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp31_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp31_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp6x_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp6x_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp6x_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp6x_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp6x_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp6x_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp63_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp63_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp63_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp63_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp63_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp63_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp70_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp70_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp70_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp70_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp70_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp70_hw_ops_init, "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 new file mode 100644 index 000000000..235d6cc83 --- /dev/null +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -0,0 +1,245 @@ +// 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) 2021 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// + +/* + * Machine Driver Legacy Support for ACP HW block + */ + +#include +#include +#include +#include +#include +#include + +#include "acp-mach.h" +#include "acp3x-es83xx/acp3x-es83xx.h" + +static struct acp_card_drvdata rt5682_rt1019_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, + .tdm_mode = false, +}; + +static struct acp_card_drvdata rt5682s_max_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, + .tdm_mode = false, +}; + +static struct acp_card_drvdata rt5682s_rt1019_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, + .tdm_mode = false, +}; + +static struct acp_card_drvdata es83xx_rn_data = { + .hs_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = ES83XX, + .dmic_codec_id = DMIC, +}; + +static struct acp_card_drvdata max_nau8825_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = NAU8825, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, + .soc_mclk = true, + .tdm_mode = false, +}; + +static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, + .soc_mclk = true, + .tdm_mode = false, +}; + +static struct acp_card_drvdata acp_dmic_data = { + .dmic_cpu_id = DMIC, + .dmic_codec_id = DMIC, +}; + +static bool acp_asoc_init_ops(struct acp_card_drvdata *priv) +{ + bool has_ops = false; + + if (priv->hs_codec_id == ES83XX) { + has_ops = true; + acp3x_es83xx_init_ops(&priv->ops); + } + return has_ops; +} + +static int acp_asoc_suspend_pre(struct snd_soc_card *card) +{ + int ret; + + ret = acp_ops_suspend_pre(card); + if (ret == 1) + return 0; + else + return ret; +} + +static int acp_asoc_resume_post(struct snd_soc_card *card) +{ + int ret; + + ret = acp_ops_resume_post(card); + if (ret == 1) + return 0; + else + return ret; +} + +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; + + if (!pdev->id_entry) { + ret = -EINVAL; + goto out; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) { + ret = -ENOMEM; + goto out; + } + + card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; + acp_card_drvdata = card->drvdata; + acp_card_drvdata->acpi_mach = (struct snd_soc_acpi_mach *)pdev->dev.platform_data; + card->dev = dev; + card->owner = THIS_MODULE; + card->name = pdev->id_entry->name; + + acp_asoc_init_ops(card->drvdata); + + /* If widgets and controls are not set in specific callback, + * they will be added per-codec in acp-mach-common.c + */ + ret = acp_ops_configure_widgets(card); + if (ret < 0) { + dev_err(&pdev->dev, + "Cannot configure widgets for card (%s): %d\n", + card->name, ret); + goto out; + } + card->suspend_pre = acp_asoc_suspend_pre; + card->resume_post = acp_asoc_resume_post; + + ret = acp_ops_probe(card); + if (ret < 0) { + dev_err(&pdev->dev, + "Cannot probe card (%s): %d\n", + card->name, ret); + goto out; + } + if (!strcmp(pdev->name, "acp-pdm-mach")) + 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 == (void *)QUIRK_TDM_MODE_ENABLE) + acp_card_drvdata->tdm_mode = dmi_id->driver_data; + + ret = acp_legacy_dai_links_create(card); + if (ret) { + dev_err(&pdev->dev, + "Cannot create dai links for card (%s): %d\n", + card->name, ret); + goto out; + } + + 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); + goto out; + } +out: + return ret; +} + +static const struct platform_device_id board_ids[] = { + { + .name = "acp3xalc56821019", + .driver_data = (kernel_ulong_t)&rt5682_rt1019_data, + }, + { + .name = "acp3xalc5682sm98360", + .driver_data = (kernel_ulong_t)&rt5682s_max_data, + }, + { + .name = "acp3xalc5682s1019", + .driver_data = (kernel_ulong_t)&rt5682s_rt1019_data, + }, + { + .name = "acp3x-es83xx", + .driver_data = (kernel_ulong_t)&es83xx_rn_data, + }, + { + .name = "rmb-nau8825-max", + .driver_data = (kernel_ulong_t)&max_nau8825_data, + }, + { + .name = "rmb-rt5682s-rt1019", + .driver_data = (kernel_ulong_t)&rt5682s_rt1019_rmb_data, + }, + { + .name = "acp-pdm-mach", + .driver_data = (kernel_ulong_t)&acp_dmic_data, + }, + { } +}; +MODULE_DEVICE_TABLE(platform, board_ids); + +static struct platform_driver acp_asoc_audio = { + .driver = { + .pm = &snd_soc_pm_ops, + .name = "acp_mach", + }, + .probe = acp_asoc_probe, + .id_table = board_ids, +}; + +module_platform_driver(acp_asoc_audio); + +MODULE_IMPORT_NS("SND_SOC_AMD_MACH"); +MODULE_DESCRIPTION("ACP chrome audio support"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c new file mode 100644 index 000000000..01a0aaa60 --- /dev/null +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -0,0 +1,1824 @@ +// 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) 2021, 2023 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// Vijendar Mukunda +// + +/* + * Machine Driver Interface for ACP HW block + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../codecs/rt5682.h" +#include "../../codecs/rt1019.h" +#include "../../codecs/rt5682s.h" +#include "../../codecs/nau8825.h" +#include "../../codecs/nau8821.h" +#include "acp-mach.h" + +#define PCO_PLAT_CLK 48000000 +#define RT5682_PLL_FREQ (48000 * 512) +#define DUAL_CHANNEL 2 +#define FOUR_CHANNEL 4 +#define NAU8821_CODEC_DAI "nau8821-hifi" +#define NAU8821_BCLK 1536000 +#define NAU8821_FREQ_OUT 12288000 +#define MAX98388_CODEC_DAI "max98388-aif1" + +const struct dmi_system_id acp_quirk_table[] = { + { + /* Google skyrim proto-0 */ + .matches = { + DMI_EXACT_MATCH(DMI_PRODUCT_FAMILY, "Google_Skyrim"), + }, + .driver_data = (void *)QUIRK_TDM_MODE_ENABLE, + }, + { + /* Valve Steam Deck OLED */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"), + }, + .driver_data = (void *)QUIRK_REMAP_DMIC_BT, + }, + {} +}; +EXPORT_SYMBOL_GPL(acp_quirk_table); + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int acp_clk_enable(struct acp_card_drvdata *drvdata, + unsigned int srate, unsigned int bclk_ratio) +{ + clk_set_rate(drvdata->wclk, srate); + clk_set_rate(drvdata->bclk, srate * bclk_ratio); + + return clk_prepare_enable(drvdata->wclk); +} + +/* Declare RT5682 codec components */ +SND_SOC_DAILINK_DEF(rt5682, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); + +static struct snd_soc_jack rt5682_jack; +static struct snd_soc_jack_pin rt5682_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new rt5682_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget rt5682_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt5682_map[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + { "IN1P", NULL, "Headset Mic" }, +}; + +/* Define card ops for RT5682 CODEC */ +static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + int ret; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + if (drvdata->hs_codec_id != RT5682) + return -EINVAL; + + drvdata->wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); + if (IS_ERR(drvdata->wclk)) + return PTR_ERR(drvdata->wclk); + + drvdata->bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); + if (IS_ERR(drvdata->bclk)) + return PTR_ERR(drvdata->bclk); + + ret = snd_soc_dapm_new_controls(dapm, rt5682_widgets, + ARRAY_SIZE(rt5682_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, rt5682_controls, + ARRAY_SIZE(rt5682_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &rt5682_jack, + rt5682_jack_pins, + ARRAY_SIZE(rt5682_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, &rt5682_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, rt5682_map, ARRAY_SIZE(rt5682_map)); +} + +static int acp_card_hs_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + 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); + int ret; + unsigned int fmt; + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + return ret; +} + +static void acp_card_shutdown(struct snd_pcm_substream *substream) +{ + 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; + + if (!drvdata->soc_mclk) + clk_disable_unprepare(drvdata->wclk); +} + +static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + 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); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int ret; + unsigned int fmt, srate, ch, format; + + srate = params_rate(params); + ch = params_channels(params); + format = params_physical_width(params); + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 0 and slot 1 for playback and capture. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16); + if (ret < 0) { + dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, + PCO_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1, + 6144000, 49152000); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL1, + 49152000, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); + return ret; + } + } + + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); + return ret; + } + + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata, srate, ch * format); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_ops acp_card_rt5682_ops = { + .startup = acp_card_hs_startup, + .shutdown = acp_card_shutdown, + .hw_params = acp_card_rt5682_hw_params, +}; + +/* Define RT5682S CODEC component*/ +SND_SOC_DAILINK_DEF(rt5682s, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1"))); + +static struct snd_soc_jack rt5682s_jack; +static struct snd_soc_jack_pin rt5682s_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new rt5682s_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget rt5682s_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt5682s_map[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + { "IN1P", NULL, "Headset Mic" }, +}; + +static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + int ret; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + if (drvdata->hs_codec_id != RT5682S) + return -EINVAL; + + if (!drvdata->soc_mclk) { + drvdata->wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); + if (IS_ERR(drvdata->wclk)) + return PTR_ERR(drvdata->wclk); + + drvdata->bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); + if (IS_ERR(drvdata->bclk)) + return PTR_ERR(drvdata->bclk); + } + + ret = snd_soc_dapm_new_controls(dapm, rt5682s_widgets, + ARRAY_SIZE(rt5682s_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, rt5682s_controls, + ARRAY_SIZE(rt5682s_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &rt5682s_jack, + rt5682s_jack_pins, + ARRAY_SIZE(rt5682s_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, &rt5682s_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map)); +} + +static int acp_card_rt5682s_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_card *card = rtd->card; + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int ret; + unsigned int fmt, srate, ch, format; + + srate = params_rate(params); + ch = params_channels(params); + format = params_physical_width(params); + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 0 and slot 1 for playback and capture. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16); + if (ret < 0) { + dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK, + PCO_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1, + 6144000, 49152000); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL1, + 49152000, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); + return ret; + } + } + + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format); + if (ret < 0) { + dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); + return ret; + } + + clk_set_rate(drvdata->wclk, srate); + clk_set_rate(drvdata->bclk, srate * ch * format); + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata, srate, ch * format); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_ops acp_card_rt5682s_ops = { + .startup = acp_card_hs_startup, + .hw_params = acp_card_rt5682s_hw_params, +}; + +static const unsigned int dmic_channels[] = { + DUAL_CHANNEL, FOUR_CHANNEL, +}; + +static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = { + .count = ARRAY_SIZE(dmic_channels), + .list = dmic_channels, + .mask = 0, +}; + +static int acp_card_dmic_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &dmic_constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + return 0; +} + +static const struct snd_soc_ops acp_card_dmic_ops = { + .startup = acp_card_dmic_startup, +}; + +/* Declare RT1019 codec components */ +SND_SOC_DAILINK_DEF(rt1019, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"), + COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"))); + +static const struct snd_kcontrol_new rt1019_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget rt1019_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route rt1019_map_lr[] = { + { "Left Spk", NULL, "Left SPO" }, + { "Right Spk", NULL, "Right SPO" }, +}; + +static struct snd_soc_codec_conf rt1019_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), + .name_prefix = "Right", + }, +}; + +static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + int ret; + + if (drvdata->amp_codec_id != RT1019) + return -EINVAL; + + ret = snd_soc_dapm_new_controls(dapm, rt1019_widgets, + ARRAY_SIZE(rt1019_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, rt1019_controls, + ARRAY_SIZE(rt1019_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, rt1019_map_lr, + ARRAY_SIZE(rt1019_map_lr)); +} + +static int acp_card_rt1019_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_card *card = rtd->card; + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int i, ret = 0; + unsigned int fmt, srate, ch, format; + + srate = params_rate(params); + ch = params_channels(params); + format = params_physical_width(params); + + if (drvdata->amp_codec_id != RT1019) + return -EINVAL; + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 2 and slot 3 for playback. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + } + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (strcmp(codec_dai->name, "rt1019-aif")) + continue; + + if (drvdata->tdm_mode) + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, + TDM_CHANNELS * format * srate, 256 * srate); + else + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, + ch * format * srate, 256 * srate); + + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL, + 256 * srate, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + if (drvdata->tdm_mode) { + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A + | SND_SOC_DAIFMT_NB_NF); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + /** + * As codec supports slot 2 for left channel playback. + */ + if (!strcmp(codec_dai->component->name, "i2c-10EC1019:00")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x4, 8, 16); + if (ret < 0) + break; + } + + /** + * As codec supports slot 3 for right channel playback. + */ + if (!strcmp(codec_dai->component->name, "i2c-10EC1019:01")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x8, 8, 16); + if (ret < 0) + break; + } + } + } + + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata, srate, ch * format); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int acp_card_amp_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + return 0; +} + +static const struct snd_soc_ops acp_card_rt1019_ops = { + .startup = acp_card_amp_startup, + .shutdown = acp_card_shutdown, + .hw_params = acp_card_rt1019_hw_params, +}; + +/* Declare Maxim codec components */ +SND_SOC_DAILINK_DEF(max98360a, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); + +static const struct snd_kcontrol_new max98360a_controls[] = { + SOC_DAPM_PIN_SWITCH("Spk"), +}; + +static const struct snd_soc_dapm_widget max98360a_widgets[] = { + SND_SOC_DAPM_SPK("Spk", NULL), +}; + +static const struct snd_soc_dapm_route max98360a_map[] = { + {"Spk", NULL, "Speaker"}, +}; + +static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + int ret; + + if (drvdata->amp_codec_id != MAX98360A) + return -EINVAL; + + ret = snd_soc_dapm_new_controls(dapm, max98360a_widgets, + ARRAY_SIZE(max98360a_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, max98360a_controls, + ARRAY_SIZE(max98360a_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, max98360a_map, + ARRAY_SIZE(max98360a_map)); +} + +static int acp_card_maxim_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_card *card = rtd->card; + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + unsigned int fmt, srate, ch, format; + int ret; + + srate = params_rate(params); + ch = params_channels(params); + format = params_physical_width(params); + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 2 and slot 3 for playback. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + } + + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata, srate, ch * format); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); + return ret; + } + } + return 0; +} + +static const struct snd_soc_ops acp_card_maxim_ops = { + .startup = acp_card_amp_startup, + .shutdown = acp_card_shutdown, + .hw_params = acp_card_maxim_hw_params, +}; + +SND_SOC_DAILINK_DEF(max98388, + 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"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget max98388_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route max98388_map[] = { + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + +static struct snd_soc_codec_conf max98388_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-ADS8388:00"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-ADS8388:01"), + .name_prefix = "Right", + }, +}; + +static const unsigned int max98388_format[] = {16}; + +static struct snd_pcm_hw_constraint_list constraints_sample_bits_max = { + .list = max98388_format, + .count = ARRAY_SIZE(max98388_format), +}; + +static int acp_card_max98388_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + &constraints_sample_bits_max); + + return 0; +} + +static int acp_card_max98388_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + int ret; + + if (drvdata->amp_codec_id != MAX98388) + return -EINVAL; + + ret = snd_soc_dapm_new_controls(dapm, max98388_widgets, + ARRAY_SIZE(max98388_widgets)); + + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_add_card_controls(card, max98388_controls, + ARRAY_SIZE(max98388_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, max98388_map, + ARRAY_SIZE(max98388_map)); +} + +static int acp_max98388_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_card *card = rtd->card; + struct snd_soc_dai *codec_dai = + snd_soc_card_get_codec_dai(card, + MAX98388_CODEC_DAI); + + return snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF); +} + +static const struct snd_soc_ops acp_max98388_ops = { + .startup = acp_card_max98388_startup, + .hw_params = acp_max98388_hw_params, +}; + +/* Declare nau8825 codec components */ +SND_SOC_DAILINK_DEF(nau8825, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi"))); + +static struct snd_soc_jack nau8825_jack; +static struct snd_soc_jack_pin nau8825_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new nau8825_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget nau8825_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route nau8825_map[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, +}; + +static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + int ret; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + if (drvdata->hs_codec_id != NAU8825) + return -EINVAL; + + ret = snd_soc_dapm_new_controls(dapm, nau8825_widgets, + ARRAY_SIZE(nau8825_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, nau8825_controls, + ARRAY_SIZE(nau8825_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &nau8825_jack, + nau8825_jack_pins, + ARRAY_SIZE(nau8825_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, &nau8825_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(dapm, nau8825_map, ARRAY_SIZE(nau8825_map)); +} + +static int acp_nau8825_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + 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); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int ret; + unsigned int fmt; + + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS, + (48000 * 256), SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); + + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params), + params_rate(params) * 256); + if (ret < 0) { + dev_err(rtd->dev, "can't set FLL: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + + if (drvdata->soc_mclk) + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 4 and slot 5 for playback and slot 6 for capture. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x30, 0xC0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x40, 0x30, 8, 16); + if (ret < 0) { + dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + } + return ret; +} + +static int acp_nau8825_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = 2; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + return 0; +} + +static const struct snd_soc_ops acp_card_nau8825_ops = { + .startup = acp_nau8825_startup, + .hw_params = acp_nau8825_hw_params, +}; + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); + struct snd_soc_dai *codec_dai; + int ret = 0; + + codec_dai = snd_soc_card_get_codec_dai(card, NAU8821_CODEC_DAI); + if (!codec_dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "set sysclk err = %d\n", ret); + return -EIO; + } + } else { + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(codec_dai->dev, "can't set FS clock %d\n", ret); + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, NAU8821_BCLK, + NAU8821_FREQ_OUT); + if (ret < 0) + dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); + } + return ret; +} + +static struct snd_soc_jack nau8821_jack; +static struct snd_soc_jack_pin nau8821_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new nau8821_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget nau8821_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route nau8821_audio_route[] = { + /* HP jack connectors - unknown if we have jack detection */ + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + { "MICL", NULL, "Headset Mic" }, + { "MICR", NULL, "Headset Mic" }, + { "DMIC", NULL, "Int Mic" }, + { "Headphone Jack", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, + { "Int Mic", NULL, "Platform Clock" }, +}; + +static const unsigned int nau8821_format[] = {16}; + +static struct snd_pcm_hw_constraint_list constraints_sample_bits = { + .list = nau8821_format, + .count = ARRAY_SIZE(nau8821_format), +}; + +static int acp_8821_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + int ret; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + ret = snd_soc_dapm_new_controls(dapm, nau8821_widgets, + ARRAY_SIZE(nau8821_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); + // Don't need to add routes if widget addition failed + return ret; + } + + ret = snd_soc_add_card_controls(card, nau8821_controls, + ARRAY_SIZE(nau8821_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &nau8821_jack, + nau8821_jack_pins, + ARRAY_SIZE(nau8821_jack_pins)); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + nau8821_enable_jack_detect(component, &nau8821_jack); + + return snd_soc_dapm_add_routes(dapm, nau8821_audio_route, + ARRAY_SIZE(nau8821_audio_route)); +} + +static int acp_8821_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + &constraints_sample_bits); + return 0; +} + +static int acp_nau8821_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + 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); + int ret; + unsigned int fmt; + + if (drvdata->soc_mclk) + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(card->dev, "can't set FS clock %d\n", ret); + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params), + params_rate(params) * 256); + if (ret < 0) + dev_err(card->dev, "can't set FLL: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops acp_8821_ops = { + .startup = acp_8821_startup, + .hw_params = acp_nau8821_hw_params, +}; + +SND_SOC_DAILINK_DEF(nau8821, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", + NAU8821_CODEC_DAI))); + +/* Declare DMIC codec components */ +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +/* Declare ACP CPU components */ +static struct snd_soc_dai_link_component platform_component[] = { + { + .name = "acp_asoc_renoir.0", + } +}; + +static struct snd_soc_dai_link_component platform_rmb_component[] = { + { + .name = "acp_asoc_rembrandt.0", + } +}; + +static struct snd_soc_dai_link_component platform_acp63_component[] = { + { + .name = "acp_asoc_acp63.0", + } +}; + +static struct snd_soc_dai_link_component platform_acp70_component[] = { + { + .name = "acp_asoc_acp70.0", + } +}; + +static struct snd_soc_dai_link_component sof_component[] = { + { + .name = "0000:04:00.5", + } +}; + +SND_SOC_DAILINK_DEF(i2s_sp, + DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp"))); +SND_SOC_DAILINK_DEF(i2s_hs, + DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs"))); +SND_SOC_DAILINK_DEF(sof_sp, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp"))); +SND_SOC_DAILINK_DEF(sof_sp_virtual, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp-virtual"))); +SND_SOC_DAILINK_DEF(sof_hs, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs"))); +SND_SOC_DAILINK_DEF(sof_hs_virtual, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs-virtual"))); +SND_SOC_DAILINK_DEF(sof_bt, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-bt"))); +SND_SOC_DAILINK_DEF(sof_dmic, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic"))); +SND_SOC_DAILINK_DEF(pdm_dmic, + DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic"))); + +static int acp_rtk_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); + struct acp_card_drvdata *drvdata = card->drvdata; + int ret = 0; + + if (!component) + return 0; + + if (strncmp(component->name, "i2c-RTL5682", 11) && + strncmp(component->name, "i2c-10EC1019", 12)) + return 0; + + /* + * For Realtek's codec and amplifier components, + * the lrck and bclk must be enabled brfore their all dapms be powered on, + * and must be disabled after their all dapms be powered down + * to avoid any pop. + */ + switch (level) { + case SND_SOC_BIAS_STANDBY: + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) { + + /* Increase bclk's enable_count */ + ret = clk_prepare_enable(drvdata->bclk); + if (ret < 0) + dev_err(component->dev, "Failed to enable bclk %d\n", ret); + } else { + /* + * Decrease bclk's enable_count. + * While the enable_count is 0, the bclk would be closed. + */ + clk_disable_unprepare(drvdata->bclk); + } + break; + default: + break; + } + + return ret; +} + +int acp_sofdsp_dai_links_create(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *links; + struct device *dev = card->dev; + struct acp_card_drvdata *drv_data = card->drvdata; + const struct dmi_system_id *dmi_id = dmi_first_match(acp_quirk_table); + int i = 0, num_links = 0; + + if (drv_data->hs_cpu_id) + num_links++; + if (drv_data->bt_cpu_id) + num_links++; + if (drv_data->amp_cpu_id) + num_links++; + if (drv_data->dmic_cpu_id) + num_links++; + + links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL); + if (!links) + return -ENOMEM; + + if (drv_data->hs_cpu_id == I2S_SP) { + links[i].name = "acp-headset-codec"; + links[i].id = HEADSET_BE_ID; + links[i].cpus = sof_sp; + links[i].num_cpus = ARRAY_SIZE(sof_sp); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->hs_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->hs_codec_id == RT5682) { + links[i].codecs = rt5682; + links[i].num_codecs = ARRAY_SIZE(rt5682); + links[i].init = acp_card_rt5682_init; + links[i].ops = &acp_card_rt5682_ops; + } + if (drv_data->hs_codec_id == RT5682S) { + links[i].codecs = rt5682s; + links[i].num_codecs = ARRAY_SIZE(rt5682s); + links[i].init = acp_card_rt5682s_init; + links[i].ops = &acp_card_rt5682s_ops; + } + if (drv_data->hs_codec_id == NAU8821) { + links[i].codecs = nau8821; + links[i].num_codecs = ARRAY_SIZE(nau8821); + links[i].init = acp_8821_init; + links[i].ops = &acp_8821_ops; + } + i++; + } + + if (drv_data->hs_cpu_id == I2S_HS) { + links[i].name = "acp-headset-codec"; + links[i].id = HEADSET_BE_ID; + links[i].cpus = sof_hs; + links[i].num_cpus = ARRAY_SIZE(sof_hs); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->hs_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->hs_codec_id == NAU8825) { + links[i].codecs = nau8825; + links[i].num_codecs = ARRAY_SIZE(nau8825); + links[i].init = acp_card_nau8825_init; + links[i].ops = &acp_card_nau8825_ops; + } + if (drv_data->hs_codec_id == RT5682S) { + links[i].codecs = rt5682s; + links[i].num_codecs = ARRAY_SIZE(rt5682s); + links[i].init = acp_card_rt5682s_init; + links[i].ops = &acp_card_rt5682s_ops; + } + i++; + } + + if (drv_data->amp_cpu_id == I2S_SP) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; + if (drv_data->acp_rev == ACP_RN_PCI_ID) { + links[i].cpus = sof_sp; + links[i].num_cpus = ARRAY_SIZE(sof_sp); + } else { + links[i].cpus = sof_sp_virtual; + links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual); + } + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].playback_only = 1; + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->amp_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->amp_codec_id == RT1019) { + links[i].codecs = rt1019; + links[i].num_codecs = ARRAY_SIZE(rt1019); + links[i].ops = &acp_card_rt1019_ops; + links[i].init = acp_card_rt1019_init; + card->codec_conf = rt1019_conf; + card->num_configs = ARRAY_SIZE(rt1019_conf); + } + if (drv_data->amp_codec_id == MAX98360A) { + links[i].codecs = max98360a; + links[i].num_codecs = ARRAY_SIZE(max98360a); + links[i].ops = &acp_card_maxim_ops; + links[i].init = acp_card_maxim_init; + } + i++; + } + + if (drv_data->amp_cpu_id == I2S_HS) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; + links[i].cpus = sof_hs_virtual; + links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].playback_only = 1; + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->amp_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->amp_codec_id == MAX98360A) { + links[i].codecs = max98360a; + links[i].num_codecs = ARRAY_SIZE(max98360a); + links[i].ops = &acp_card_maxim_ops; + links[i].init = acp_card_maxim_init; + } + if (drv_data->amp_codec_id == MAX98388) { + links[i].playback_only = 0; + links[i].codecs = max98388; + links[i].num_codecs = ARRAY_SIZE(max98388); + links[i].ops = &acp_max98388_ops; + links[i].init = acp_card_max98388_init; + card->codec_conf = max98388_conf; + card->num_configs = ARRAY_SIZE(max98388_conf); + } + if (drv_data->amp_codec_id == RT1019) { + links[i].codecs = rt1019; + links[i].num_codecs = ARRAY_SIZE(rt1019); + links[i].ops = &acp_card_rt1019_ops; + links[i].init = acp_card_rt1019_init; + card->codec_conf = rt1019_conf; + card->num_configs = ARRAY_SIZE(rt1019_conf); + } + i++; + } + + if (drv_data->bt_cpu_id == I2S_BT) { + links[i].name = "acp-bt-codec"; + links[i].id = BT_BE_ID; + links[i].cpus = sof_bt; + links[i].num_cpus = ARRAY_SIZE(sof_bt); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->bt_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + + if (dmi_id && dmi_id->driver_data == (void *)QUIRK_REMAP_DMIC_BT) + links[i].id = DMIC_BE_ID; + i++; + } + + if (drv_data->dmic_cpu_id == DMIC) { + links[i].name = "acp-dmic-codec"; + links[i].id = DMIC_BE_ID; + links[i].codecs = dmic_codec; + links[i].num_codecs = ARRAY_SIZE(dmic_codec); + links[i].cpus = sof_dmic; + links[i].num_cpus = ARRAY_SIZE(sof_dmic); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].capture_only = 1; + links[i].nonatomic = true; + links[i].no_pcm = 1; + + if (dmi_id && dmi_id->driver_data == (void *)QUIRK_REMAP_DMIC_BT) { + links[i].id = BT_BE_ID; + dev_dbg(dev, "quirk REMAP_DMIC_BT enabled\n"); + } + } + + card->dai_link = links; + card->num_links = num_links; + card->set_bias_level = acp_rtk_set_bias_level; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, "SND_SOC_AMD_MACH"); + +int acp_legacy_dai_links_create(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *links; + struct device *dev = card->dev; + struct acp_card_drvdata *drv_data = card->drvdata; + int i = 0, num_links = 0; + int rc; + + if (drv_data->hs_cpu_id) + num_links++; + if (drv_data->amp_cpu_id) + num_links++; + if (drv_data->dmic_cpu_id) + num_links++; + + links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL); + if (!links) + return -ENOMEM; + + if (drv_data->hs_cpu_id == I2S_SP) { + links[i].name = "acp-headset-codec"; + links[i].id = HEADSET_BE_ID; + links[i].cpus = i2s_sp; + links[i].num_cpus = ARRAY_SIZE(i2s_sp); + links[i].platforms = platform_component; + links[i].num_platforms = ARRAY_SIZE(platform_component); + if (!drv_data->hs_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->hs_codec_id == RT5682) { + links[i].codecs = rt5682; + links[i].num_codecs = ARRAY_SIZE(rt5682); + links[i].init = acp_card_rt5682_init; + links[i].ops = &acp_card_rt5682_ops; + } + if (drv_data->hs_codec_id == RT5682S) { + links[i].codecs = rt5682s; + links[i].num_codecs = ARRAY_SIZE(rt5682s); + links[i].init = acp_card_rt5682s_init; + links[i].ops = &acp_card_rt5682s_ops; + } + if (drv_data->hs_codec_id == ES83XX) { + rc = acp_ops_configure_link(card, &links[i]); + if (rc != 0) { + dev_err(dev, "Failed to configure link for ES83XX: %d\n", rc); + return rc; + } + } + i++; + } + + if (drv_data->hs_cpu_id == I2S_HS) { + links[i].name = "acp-headset-codec"; + links[i].id = HEADSET_BE_ID; + links[i].cpus = i2s_hs; + links[i].num_cpus = ARRAY_SIZE(i2s_hs); + 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); + break; + case ACP63_PCI_ID: + links[i].platforms = platform_acp63_component; + links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); + break; + default: + links[i].platforms = platform_component; + links[i].num_platforms = ARRAY_SIZE(platform_component); + break; + } + + if (!drv_data->hs_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + if (drv_data->hs_codec_id == NAU8825) { + links[i].codecs = nau8825; + links[i].num_codecs = ARRAY_SIZE(nau8825); + links[i].init = acp_card_nau8825_init; + links[i].ops = &acp_card_nau8825_ops; + } + if (drv_data->hs_codec_id == RT5682S) { + links[i].codecs = rt5682s; + links[i].num_codecs = ARRAY_SIZE(rt5682s); + links[i].init = acp_card_rt5682s_init; + links[i].ops = &acp_card_rt5682s_ops; + } + i++; + } + + if (drv_data->amp_cpu_id == I2S_SP) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; + links[i].cpus = i2s_sp; + links[i].num_cpus = ARRAY_SIZE(i2s_sp); + links[i].platforms = platform_component; + links[i].num_platforms = ARRAY_SIZE(platform_component); + 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; + links[i].num_codecs = 1; + } + if (drv_data->amp_codec_id == RT1019) { + links[i].codecs = rt1019; + links[i].num_codecs = ARRAY_SIZE(rt1019); + links[i].ops = &acp_card_rt1019_ops; + links[i].init = acp_card_rt1019_init; + card->codec_conf = rt1019_conf; + card->num_configs = ARRAY_SIZE(rt1019_conf); + } + if (drv_data->amp_codec_id == MAX98360A) { + links[i].codecs = max98360a; + links[i].num_codecs = ARRAY_SIZE(max98360a); + links[i].ops = &acp_card_maxim_ops; + links[i].init = acp_card_maxim_init; + } + i++; + } + + if (drv_data->amp_cpu_id == I2S_HS) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; + links[i].cpus = i2s_hs; + links[i].num_cpus = ARRAY_SIZE(i2s_hs); + 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); + break; + case ACP63_PCI_ID: + links[i].platforms = platform_acp63_component; + links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); + break; + default: + links[i].platforms = platform_component; + links[i].num_platforms = ARRAY_SIZE(platform_component); + break; + } + + 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; + links[i].num_codecs = 1; + } + if (drv_data->amp_codec_id == MAX98360A) { + links[i].codecs = max98360a; + links[i].num_codecs = ARRAY_SIZE(max98360a); + links[i].ops = &acp_card_maxim_ops; + links[i].init = acp_card_maxim_init; + } + if (drv_data->amp_codec_id == RT1019) { + links[i].codecs = rt1019; + links[i].num_codecs = ARRAY_SIZE(rt1019); + links[i].ops = &acp_card_rt1019_ops; + links[i].init = acp_card_rt1019_init; + card->codec_conf = rt1019_conf; + card->num_configs = ARRAY_SIZE(rt1019_conf); + } + i++; + } + + 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; + links[i].num_codecs = ARRAY_SIZE(dmic_codec); + } else { + /* Use dummy codec if codec id not specified */ + links[i].codecs = &snd_soc_dummy_dlc; + links[i].num_codecs = 1; + } + links[i].cpus = pdm_dmic; + links[i].num_cpus = ARRAY_SIZE(pdm_dmic); + 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); + break; + case ACP63_PCI_ID: + links[i].platforms = platform_acp63_component; + links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); + break; + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_PCI_ID: + links[i].platforms = platform_acp70_component; + links[i].num_platforms = ARRAY_SIZE(platform_acp70_component); + 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].capture_only = 1; + } + + card->dai_link = links; + card->num_links = num_links; + card->set_bias_level = acp_rtk_set_bias_level; + + return 0; +} +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 new file mode 100644 index 000000000..7177d3fd9 --- /dev/null +++ b/sound/soc/amd/acp/acp-mach.h @@ -0,0 +1,143 @@ +/* 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) 2021 Advanced Micro Devices, Inc. All rights reserved. + * + * Author: Ajit Kumar Pandey + */ +#ifndef __ACP_MACH_H +#define __ACP_MACH_H + +#include +#include +#include +#include +#include +#include +#include + +#include "acp_common.h" + +#define TDM_CHANNELS 8 + +#define ACP_OPS(priv, cb) ((priv)->ops.cb) + +#define acp_get_drvdata(card) ((struct acp_card_drvdata *)(card)->drvdata) + +/* List of DMI quirks - check acp-mach-common.c for usage. */ +#define QUIRK_TDM_MODE_ENABLE 1 +#define QUIRK_REMAP_DMIC_BT 2 + +enum be_id { + HEADSET_BE_ID = 0, + AMP_BE_ID, + DMIC_BE_ID, + BT_BE_ID, +}; + +enum cpu_endpoints { + NONE = 0, + I2S_HS, + I2S_SP, + I2S_BT, + DMIC, +}; + +enum codec_endpoints { + DUMMY = 0, + RT5682, + RT1019, + MAX98360A, + RT5682S, + NAU8825, + NAU8821, + MAX98388, + ES83XX, +}; + +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); + int (*configure_widgets)(struct snd_soc_card *card); + int (*suspend_pre)(struct snd_soc_card *card); + int (*resume_post)(struct snd_soc_card *card); +}; + +struct acp_card_drvdata { + unsigned int hs_cpu_id; + unsigned int amp_cpu_id; + unsigned int bt_cpu_id; + unsigned int dmic_cpu_id; + unsigned int hs_codec_id; + unsigned int amp_codec_id; + unsigned int bt_codec_id; + unsigned int dmic_codec_id; + unsigned int dai_fmt; + unsigned int acp_rev; + struct clk *wclk; + struct clk *bclk; + struct acp_mach_ops ops; + struct snd_soc_acpi_mach *acpi_mach; + void *mach_priv; + bool soc_mclk; + bool tdm_mode; +}; + +int acp_sofdsp_dai_links_create(struct snd_soc_card *card); +int acp_legacy_dai_links_create(struct snd_soc_card *card); +extern const struct dmi_system_id acp_quirk_table[]; + +static inline int acp_ops_probe(struct snd_soc_card *card) +{ + int ret = 1; + struct acp_card_drvdata *priv = acp_get_drvdata(card); + + if (ACP_OPS(priv, probe)) + ret = ACP_OPS(priv, probe)(card); + return ret; +} + +static inline int acp_ops_configure_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + int ret = 1; + struct acp_card_drvdata *priv = acp_get_drvdata(card); + + if (ACP_OPS(priv, configure_link)) + ret = ACP_OPS(priv, configure_link)(card, dai_link); + return ret; +} + +static inline int acp_ops_configure_widgets(struct snd_soc_card *card) +{ + int ret = 1; + struct acp_card_drvdata *priv = acp_get_drvdata(card); + + if (ACP_OPS(priv, configure_widgets)) + ret = ACP_OPS(priv, configure_widgets)(card); + return ret; +} + +static inline int acp_ops_suspend_pre(struct snd_soc_card *card) +{ + int ret = 1; + struct acp_card_drvdata *priv = acp_get_drvdata(card); + + if (ACP_OPS(priv, suspend_pre)) + ret = ACP_OPS(priv, suspend_pre)(card); + return ret; +} + +static inline int acp_ops_resume_post(struct snd_soc_card *card) +{ + int ret = 1; + struct acp_card_drvdata *priv = acp_get_drvdata(card); + + if (ACP_OPS(priv, resume_post)) + ret = ACP_OPS(priv, resume_post)(card); + return ret; +} + +#endif diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c new file mode 100644 index 000000000..98771323e --- /dev/null +++ b/sound/soc/amd/acp/acp-pci.c @@ -0,0 +1,287 @@ +// 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) 2022 Advanced Micro Devices, Inc. All rights reserved. +// +// Authors: Ajit Kumar Pandey + +/* + * Generic PCI interface for ACP device + */ + +#include +#include +#include +#include +#include +#include + +#include "amd.h" +#include "../mach-config.h" + +#define DRV_NAME "acp_pci" + +#define ACP3x_REG_START 0x1240000 +#define ACP3x_REG_END 0x125C000 + +static irqreturn_t irq_handler(int irq, void *data) +{ + struct acp_chip_info *chip = data; + + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->irq) + return chip->acp_hw_ops->irq(irq, chip); + + return IRQ_NONE; +} +static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo, + struct device *parent, + struct fwnode_handle *fw_node, + char *name, unsigned int id, + const struct resource *res, + unsigned int num_res, + const void *data, + size_t size_data) +{ + pdevinfo->name = name; + pdevinfo->id = id; + pdevinfo->parent = parent; + pdevinfo->num_res = num_res; + pdevinfo->res = res; + pdevinfo->data = data; + pdevinfo->size_data = size_data; + pdevinfo->fwnode = fw_node; +} + +static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *chip, u32 addr) +{ + struct platform_device_info pdevinfo; + struct device *parent; + int ret; + + parent = &pci->dev; + + if (chip->is_i2s_config || chip->is_pdm_dev) { + chip->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL); + if (!chip->res) { + ret = -ENOMEM; + goto err; + } + chip->res->flags = IORESOURCE_MEM; + chip->res->start = addr; + chip->res->end = addr + (ACP3x_REG_END - ACP3x_REG_START); + memset(&pdevinfo, 0, sizeof(pdevinfo)); + } + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + acp_fill_platform_dev_info(&pdevinfo, parent, NULL, chip->name, + 0, chip->res, 1, chip, sizeof(*chip)); + + chip->acp_plat_dev = platform_device_register_full(&pdevinfo); + if (IS_ERR(chip->acp_plat_dev)) { + dev_err(&pci->dev, + "cannot register %s device\n", pdevinfo.name); + ret = PTR_ERR(chip->acp_plat_dev); + goto err; + } + if (chip->is_pdm_dev && chip->is_pdm_config) { + chip->dmic_codec_dev = platform_device_register_data(&pci->dev, + "dmic-codec", + PLATFORM_DEVID_NONE, + NULL, 0); + if (IS_ERR(chip->dmic_codec_dev)) { + dev_err(&pci->dev, "failed to create DMIC device\n"); + ret = PTR_ERR(chip->dmic_codec_dev); + goto unregister_acp_plat_dev; + } + } + return 0; +unregister_acp_plat_dev: + platform_device_unregister(chip->acp_plat_dev); +err: + return ret; +} + +static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) +{ + struct device *dev = &pci->dev; + struct acp_chip_info *chip; + unsigned int flag, addr; + int ret; + + flag = snd_amd_acp_find_config(pci); + if (flag != FLAG_AMD_LEGACY && flag != FLAG_AMD_LEGACY_ONLY_DMIC) + return -ENODEV; + + chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + if (pcim_enable_device(pci)) + return dev_err_probe(&pci->dev, -ENODEV, + "pci_enable_device failed\n"); + + pci_set_master(pci); + + chip->acp_rev = pci->revision; + switch (pci->revision) { + case 0x01: + chip->name = "acp_asoc_renoir"; + chip->rsrc = &rn_rsrc; + chip->acp_hw_ops_init = acp31_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp_machines; + break; + case 0x6f: + chip->name = "acp_asoc_rembrandt"; + chip->rsrc = &rmb_rsrc; + chip->acp_hw_ops_init = acp6x_hw_ops_init; + chip->machines = snd_soc_acpi_amd_rmb_acp_machines; + break; + case 0x63: + chip->name = "acp_asoc_acp63"; + chip->rsrc = &acp63_rsrc; + chip->acp_hw_ops_init = acp63_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp63_acp_machines; + break; + case 0x70: + case 0x71: + case 0x72: + chip->name = "acp_asoc_acp70"; + chip->rsrc = &acp70_rsrc; + chip->acp_hw_ops_init = acp70_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp70_acp_machines; + break; + default: + dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); + return -EINVAL; + } + chip->flag = flag; + + addr = pci_resource_start(pci, 0); + chip->base = pcim_iomap_region(pci, 0, "AMD ACP3x audio"); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + chip->addr = addr; + + chip->acp_hw_ops_init(chip); + ret = acp_hw_init(chip); + if (ret) + goto de_init; + + ret = devm_request_irq(dev, pci->irq, irq_handler, + IRQF_SHARED, "ACP_I2S_IRQ", chip); + if (ret) { + dev_err(&pci->dev, "ACP I2S IRQ request failed %d\n", ret); + goto de_init; + } + + check_acp_config(pci, chip); + if (!chip->is_pdm_dev && !chip->is_i2s_config) + goto skip_pdev_creation; + + ret = create_acp_platform_devs(pci, chip, addr); + if (ret < 0) { + dev_err(&pci->dev, "ACP platform devices creation failed\n"); + goto de_init; + } + + chip->chip_pdev = chip->acp_plat_dev; + chip->dev = &chip->acp_plat_dev->dev; + + acp_machine_select(chip); + + INIT_LIST_HEAD(&chip->stream_list); + spin_lock_init(&chip->acp_lock); +skip_pdev_creation: + dev_set_drvdata(&pci->dev, chip); + pm_runtime_set_autosuspend_delay(&pci->dev, 2000); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return ret; + +de_init: + acp_hw_deinit(chip); + + return ret; +}; + +static int snd_acp_suspend(struct device *dev) +{ + struct acp_chip_info *chip; + int ret; + + chip = dev_get_drvdata(dev); + ret = acp_hw_deinit(chip); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + return ret; +} + +static int snd_acp_resume(struct device *dev) +{ + struct acp_chip_info *chip; + int ret; + + chip = dev_get_drvdata(dev); + ret = acp_hw_init(chip); + if (ret) + dev_err(dev, "ACP init failed\n"); + + ret = acp_hw_en_interrupts(chip); + if (ret) + dev_err(dev, "ACP en-interrupts failed\n"); + + return ret; +} + +static const struct dev_pm_ops acp_pm_ops = { + RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) +}; + +static void acp_pci_remove(struct pci_dev *pci) +{ + struct acp_chip_info *chip; + int ret; + + chip = pci_get_drvdata(pci); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + if (chip->dmic_codec_dev) + platform_device_unregister(chip->dmic_codec_dev); + if (chip->acp_plat_dev) + platform_device_unregister(chip->acp_plat_dev); + if (chip->mach_dev) + platform_device_unregister(chip->mach_dev); + + ret = acp_hw_deinit(chip); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); +} + +/* PCI IDs */ +static const struct pci_device_id acp_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID)}, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, acp_pci_ids); + +/* pci_driver definition */ +static struct pci_driver snd_amd_acp_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = acp_pci_ids, + .probe = acp_pci_probe, + .remove = acp_pci_remove, + .driver = { + .pm = pm_ptr(&acp_pm_ops), + }, +}; +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_ALIAS(DRV_NAME); diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c new file mode 100644 index 000000000..1bfc34c2a --- /dev/null +++ b/sound/soc/amd/acp/acp-pdm.c @@ -0,0 +1,187 @@ +// 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) 2022 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// Vijendar Mukunda +// + +/* + * Generic Hardware interface for ACP Audio PDM controller + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "amd.h" + +#define DRV_NAME "acp-pdm" + +static int acp_dmic_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct acp_stream *stream = substream->runtime->private_data; + struct device *dev = dai->component->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, chip->base + ACP_WOV_CLK_CTRL); + dmic_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL); + dmic_ctrl |= PDM_MISC_CTRL_MASK; + writel(dmic_ctrl, chip->base + ACP_WOV_MISC_CTRL); + + period_bytes = frames_to_bytes(substream->runtime, + substream->runtime->period_size); + size_dmic = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + + 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, chip->base + ACP_WOV_RX_RINGBUFADDR); + writel(size_dmic, chip->base + ACP_WOV_RX_RINGBUFSIZE); + writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); + + return 0; +} + +static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + unsigned int dma_enable; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE); + if (!(dma_enable & DMA_EN_MASK)) { + writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_ENABLE); + writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE); + } + + ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE, + dma_enable, (dma_enable & DMA_EN_MASK), + DELAY_US, PDM_TIMEOUT); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE); + if ((dma_enable & DMA_EN_MASK)) { + writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_ENABLE); + writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE); + + } + + ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE, + dma_enable, !(dma_enable & DMA_EN_MASK), + DELAY_US, PDM_TIMEOUT); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int acp_dmic_hwparams(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + unsigned int channels, ch_mask; + + channels = params_channels(hwparams); + switch (channels) { + case 2: + ch_mask = 0; + break; + case 4: + ch_mask = 1; + break; + case 6: + ch_mask = 2; + break; + default: + dev_err(dev, "Invalid channels %d\n", channels); + return -EINVAL; + } + + chip->ch_mask = ch_mask; + if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) { + dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams)); + return -EINVAL; + } + + writel(ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS); + writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR); + + return 0; +} + +static int acp_dmic_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct acp_stream *stream = substream->runtime->private_data; + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + u32 ext_int_ctrl; + + stream->dai_id = DMIC_INSTANCE; + stream->irq_bit = BIT(PDM_DMA_STAT); + stream->pte_offset = ACP_SRAM_PDM_PTE_OFFSET; + stream->reg_offset = ACP_REGION2_OFFSET; + + /* Enable DMIC Interrupts */ + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); + + return 0; +} + +static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + u32 ext_int_ctrl; + + /* Disable DMIC interrupts */ + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); + ext_int_ctrl &= ~PDM_DMA_INTR_MASK; + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); +} + +const struct snd_soc_dai_ops acp_dmic_dai_ops = { + .prepare = acp_dmic_prepare, + .hw_params = acp_dmic_hwparams, + .trigger = acp_dmic_dai_trigger, + .startup = acp_dmic_dai_startup, + .shutdown = acp_dmic_dai_shutdown, +}; +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 new file mode 100644 index 000000000..6b1e18b31 --- /dev/null +++ b/sound/soc/amd/acp/acp-platform.c @@ -0,0 +1,360 @@ +// 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) 2021 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey + +/* + * Generic interface for ACP audio blck PCM component + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "amd.h" +#include "acp-mach.h" + +#define DRV_NAME "acp_i2s_dma" + +static const struct snd_pcm_hardware acp_pcm_hardware_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH | + 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 = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .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 acp_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH | + 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 = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .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, +}; + +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, +}; + +void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream) +{ + struct acp_resource *rsrc = chip->rsrc; + u32 reg_val; + + reg_val = rsrc->sram_pte_offset; + stream->reg_offset = 0x02000000; + + writel((reg_val + GRP1_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + writel((reg_val + GRP2_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); + + writel(reg_val | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5); + + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); +} +EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON"); + +void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size) +{ + struct snd_pcm_substream *substream = stream->substream; + struct acp_resource *rsrc = chip->rsrc; + dma_addr_t addr = substream->dma_buffer.addr; + int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + u32 low, high, val; + u16 page_idx; + + switch (chip->acp_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_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(chip->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 */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + writel(low, chip->base + rsrc->scratch_reg_offset + val); + high |= BIT(31); + writel(high, chip->base + rsrc->scratch_reg_offset + val + 4); + + /* Move to next physically contiguous page */ + val += 8; + addr += PAGE_SIZE; + } +} +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_chip_info *chip; + struct acp_stream *stream; + int ret; + + stream = kzalloc_obj(*stream); + if (!stream) + return -ENOMEM; + + stream->substream = substream; + chip = dev_get_drvdata(dev->parent); + switch (chip->acp_rev) { + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_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; + } + + 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) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(stream); + return ret; + } + runtime->private_data = stream; + + writel(1, ACP_EXTERNAL_INTR_ENB(chip)); + + spin_lock_irq(&chip->acp_lock); + list_add_tail(&stream->list, &chip->stream_list); + spin_unlock_irq(&chip->acp_lock); + + return ret; +} + +static int acp_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct device *dev = component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream = substream->runtime->private_data; + u64 size = params_buffer_bytes(params); + + /* Configure ACP DMA block with params */ + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, size); + + return 0; +} + +static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct device *dev = component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream = substream->runtime->private_data; + u32 pos, buffersize; + u64 bytescount; + + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + + bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); + + if (bytescount > stream->bytescount) + bytescount -= stream->bytescount; + + pos = do_div(bytescount, buffersize); + + return bytes_to_frames(substream->runtime, pos); +} + +static int acp_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct device *dev = component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream = substream->runtime->private_data; + + /* Remove entry from list */ + spin_lock_irq(&chip->acp_lock); + list_del(&stream->list); + spin_unlock_irq(&chip->acp_lock); + kfree(stream); + + return 0; +} + +static const struct snd_soc_component_driver acp_pcm_component = { + .name = DRV_NAME, + .open = acp_dma_open, + .close = acp_dma_close, + .hw_params = acp_dma_hw_params, + .pointer = acp_dma_pointer, + .pcm_new = acp_dma_new, + .legacy_dai_naming = 1, +}; + +int acp_platform_register(struct device *dev) +{ + struct acp_chip_info *chip; + struct snd_soc_dai_driver; + unsigned int status; + + chip = dev_get_platdata(dev); + if (!chip || !chip->base) { + dev_err(dev, "ACP chip data is NULL\n"); + return -ENODEV; + } + + status = devm_snd_soc_register_component(dev, &acp_pcm_component, + chip->dai_driver, + chip->num_dai); + if (status) { + dev_err(dev, "Fail to register acp i2s component\n"); + return status; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON"); + +int acp_platform_unregister(struct device *dev) +{ + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON"); + +MODULE_DESCRIPTION("AMD ACP PCM Driver"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS(DRV_NAME); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c new file mode 100644 index 000000000..7e9c07488 --- /dev/null +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -0,0 +1,247 @@ +// 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) 2022 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// V sujith kumar Reddy +/* + * Hardware interface for Renoir ACP block + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "amd.h" +#include "../mach-config.h" +#include "acp-mach.h" + +#define DRV_NAME "acp_asoc_rembrandt" + +#define MP1_C2PMSG_69 0x3B10A14 +#define MP1_C2PMSG_85 0x3B10A54 +#define MP1_C2PMSG_93 0x3B10A74 + +static struct snd_soc_dai_driver acp_rmb_dai[] = { +{ + .name = "acp-i2s-sp", + .id = I2S_SP_INSTANCE, + .playback = { + .stream_name = "I2S SP Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S SP Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-bt", + .id = I2S_BT_INSTANCE, + .playback = { + .stream_name = "I2S BT Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S BT Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-hs", + .id = I2S_HS_INSTANCE, + .playback = { + .stream_name = "I2S HS Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S HS Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-pdm-dmic", + .id = DMIC_INSTANCE, + .capture = { + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &acp_dmic_dai_ops, +}, +}; + +static int acp6x_master_clock_generate(struct device *dev) +{ + int data, rc; + + rc = amd_smn_write(0, MP1_C2PMSG_93, 0); + if (rc) + return rc; + rc = amd_smn_write(0, MP1_C2PMSG_85, 0xC4); + if (rc) + return rc; + rc = amd_smn_write(0, MP1_C2PMSG_69, 0x4); + if (rc) + return rc; + + return read_poll_timeout(smn_read_register, data, data > 0, DELAY_US, + ACP_TIMEOUT, false, MP1_C2PMSG_93); +} + +static int rembrandt_audio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip; + int ret; + + chip = dev_get_platdata(&pdev->dev); + if (!chip || !chip->base) { + dev_err(&pdev->dev, "ACP chip data is NULL\n"); + return -ENODEV; + } + + if (chip->acp_rev != ACP_RMB_PCI_ID) { + dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); + return -ENODEV; + } + + chip->dev = dev; + chip->dai_driver = acp_rmb_dai; + chip->num_dai = ARRAY_SIZE(acp_rmb_dai); + + if (chip->is_i2s_config && chip->rsrc->soc_mclk) { + ret = acp6x_master_clock_generate(dev); + if (ret) + return ret; + } + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } + acp_platform_register(dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void rembrandt_audio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); + + acp_platform_unregister(dev); + pm_runtime_disable(&pdev->dev); +} + +static int rmb_pcm_resume(struct device *dev) +{ + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream; + struct snd_pcm_substream *substream; + snd_pcm_uframes_t buf_in_frames; + u64 buf_size; + + if (chip->is_i2s_config && chip->rsrc->soc_mclk) + acp6x_master_clock_generate(dev); + + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + substream = stream->substream; + if (substream && substream->runtime) { + buf_in_frames = (substream->runtime->buffer_size); + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); + if (stream->dai_id) + restore_acp_i2s_params(substream, chip, stream); + else + restore_acp_pdm_params(substream, chip); + } + } + spin_unlock(&chip->acp_lock); + return 0; +} + +static const struct dev_pm_ops rmb_dma_pm_ops = { + SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume) +}; + +static struct platform_driver rembrandt_driver = { + .probe = rembrandt_audio_probe, + .remove = rembrandt_audio_remove, + .driver = { + .name = "acp_asoc_rembrandt", + .pm = pm_ptr(&rmb_dma_pm_ops), + }, +}; + +module_platform_driver(rembrandt_driver); + +MODULE_DESCRIPTION("AMD ACP Rembrandt Driver"); +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 new file mode 100644 index 000000000..04f6d70b6 --- /dev/null +++ b/sound/soc/amd/acp/acp-renoir.c @@ -0,0 +1,191 @@ +// 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) 2021 Advanced Micro Devices, Inc. +// +// Authors: Ajit Kumar Pandey +// + +/* + * Hardware interface for Renoir ACP block + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "amd.h" +#include "acp-mach.h" + +#define DRV_NAME "acp_asoc_renoir" + +static struct snd_soc_dai_driver acp_renoir_dai[] = { +{ + .name = "acp-i2s-sp", + .id = I2S_SP_INSTANCE, + .playback = { + .stream_name = "I2S SP Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S SP Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-bt", + .id = I2S_BT_INSTANCE, + .playback = { + .stream_name = "I2S BT Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S BT Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-pdm-dmic", + .id = DMIC_INSTANCE, + .capture = { + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &acp_dmic_dai_ops, +}, +}; + + +static int renoir_audio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip; + int ret; + + chip = dev_get_platdata(&pdev->dev); + if (!chip || !chip->base) { + dev_err(&pdev->dev, "ACP chip data is NULL\n"); + return -ENODEV; + } + + if (chip->acp_rev != ACP_RN_PCI_ID) { + dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); + return -ENODEV; + } + + chip->dev = dev; + chip->dai_driver = acp_renoir_dai; + chip->num_dai = ARRAY_SIZE(acp_renoir_dai); + + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } + + acp_platform_register(dev); + + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void renoir_audio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); + + acp_platform_unregister(dev); +} + +static int rn_pcm_resume(struct device *dev) +{ + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream; + struct snd_pcm_substream *substream; + snd_pcm_uframes_t buf_in_frames; + u64 buf_size; + + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + substream = stream->substream; + if (substream && substream->runtime) { + buf_in_frames = (substream->runtime->buffer_size); + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); + if (stream->dai_id) + restore_acp_i2s_params(substream, chip, stream); + else + restore_acp_pdm_params(substream, chip); + } + } + spin_unlock(&chip->acp_lock); + return 0; +} + +static const struct dev_pm_ops rn_dma_pm_ops = { + SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume) +}; + +static struct platform_driver renoir_driver = { + .probe = renoir_audio_probe, + .remove = renoir_audio_remove, + .driver = { + .name = "acp_asoc_renoir", + .pm = pm_ptr(&rn_dma_pm_ops), + }, +}; + +module_platform_driver(renoir_driver); + +MODULE_DESCRIPTION("AMD ACP Renoir Driver"); +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 000000000..6eac42bac --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -0,0 +1,604 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#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"); + if (soc_sdw_quirk & ASOC_SDW_CODEC_SPKR) + dev_dbg(dev, "quirk ASOC_SDW_CODEC_SPKR 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, + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D80"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D81"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D82"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D83"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0DD3"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0DD4"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21YW"), + }, + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21YX"), + }, + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { /* Lenovo P16s G5 AMD */ + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21XG"), + }, + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { /* Lenovo P16s G5 AMD */ + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21XH"), + }, + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "HN7306EA"), + }, + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), + }, + {} +}; + +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; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + ret = get_acp70_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); + if (!cpus->dai_name) + return -ENOMEM; + dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); + + 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, int num_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 i; + 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: + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + sdw_platform_component->name = "amd_ps_sdw_dma.0"; + break; + default: + return -EINVAL; + } + + /* generate DAI links by each sdw link */ + for (i = 0; i < num_dais && soc_dais->initialised; i++) { + int current_be_id = 0; + + ret = create_sdw_dailink(card, soc_dais, dai_links, + ¤t_be_id, codec_conf, sdw_platform_component); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + soc_dais++; + } + + return 0; +} + +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct snd_soc_dai_link_component *pdm_cpu; + struct snd_soc_dai_link_component *pdm_platform; + int ret; + + pdm_cpu = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_cpu) + return -ENOMEM; + + pdm_platform = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_platform) + return -ENOMEM; + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_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, + "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; + int sdw_be_num = 0, dmic_num = 0; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_aux_dev *soc_aux; + struct snd_soc_codec_conf *codec_conf; + struct snd_soc_dai_link *dai_links; + int num_devs = 0; + int num_ends = 0; + int num_aux = 0; + int num_confs; + int num_links; + int be_id = 0; + int ret; + + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends, &num_aux); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + num_confs = num_ends; + + /* One per DAI link, worst case is a DAI link for every endpoint */ + struct asoc_sdw_dailink *soc_dais __free(kfree) = + kzalloc_objs(*soc_dais, num_ends); + if (!soc_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + struct asoc_sdw_endpoint *soc_ends __free(kfree) = + kzalloc_objs(*soc_ends, num_ends); + if (!soc_ends) + return -ENOMEM; + + soc_aux = devm_kcalloc(dev, num_aux, sizeof(*soc_aux), GFP_KERNEL); + if (!soc_aux) + return -ENOMEM; + + ret = asoc_sdw_parse_sdw_endpoints(dev, ctx, soc_aux, soc_dais, soc_ends, &num_confs); + if (ret < 0) + return ret; + + sdw_be_num = ret; + + /* enable dmic */ + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) + dmic_num = 1; + + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); + + codec_conf = devm_kcalloc(dev, num_confs, 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_confs; + card->dai_link = dai_links; + card->num_links = num_links; + card->aux_dev = soc_aux; + card->num_aux_devs = num_aux; + + /* SDW */ + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, + soc_dais, num_ends, &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); + if (mach->mach_params.subsystem_id_set) + snd_soc_card_set_pci_ssid(card, + mach->mach_params.subsystem_vendor, + mach->mach_params.subsystem_device); + + dmi_check_system(soc_sdw_quirk_table); + + if (quirk_override != -1) { + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + soc_sdw_quirk, quirk_override); + soc_sdw_quirk = quirk_override; + } + + log_quirks(&pdev->dev); + + ctx->mc_quirk = soc_sdw_quirk; + dev_dbg(&pdev->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(&pdev->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) { + card->components = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%s mic:acp-dmic cfg-mics:%d", + card->components, + 1); + if (!card->components) + return -ENOMEM; + } + + /* Register the card */ + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err_probe(&pdev->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[] = { + { .name = "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 "); +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 000000000..e5f394dc2 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-mach-common.c @@ -0,0 +1,98 @@ +// 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 +#include +#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"); + +int get_acp70_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + dev_dbg(dev, "sdw_link_id:%d, be_id:%d, cpu_pin_id:%d\n", sdw_link_id, be_id, *cpu_pin_id); + return 0; +} +EXPORT_SYMBOL_NS_GPL(get_acp70_cpu_pin_id, "SND_SOC_AMD_SDW_MACH"); + +MODULE_DESCRIPTION("AMD SoundWire Common Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda "); +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 000000000..a9cd1f335 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -0,0 +1,462 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#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; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + ret = get_acp70_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); + if (!cpus->dai_name) + return -ENOMEM; + dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); + + 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, int num_dais, + struct snd_soc_codec_conf **codec_conf) +{ + int i; + int ret; + + /* generate DAI links by each sdw link */ + for (i = 0; i < num_dais && sof_dais->initialised; i++) { + int current_be_id = 0; + + ret = create_sdw_dailink(card, sof_dais, dai_links, + ¤t_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, + "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 snd_soc_aux_dev *sof_aux; + struct snd_soc_codec_conf *codec_conf; + struct snd_soc_dai_link *dai_links; + int num_devs = 0; + int num_ends = 0; + int num_aux = 0; + int num_links; + int be_id = 0; + int ret; + + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends, &num_aux); + 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 */ + struct asoc_sdw_dailink *sof_dais __free(kfree) = + kzalloc_objs(*sof_dais, num_ends); + if (!sof_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + struct asoc_sdw_endpoint *sof_ends __free(kfree) = + kzalloc_objs(*sof_ends, num_ends); + if (!sof_ends) + return -ENOMEM; + + sof_aux = devm_kcalloc(dev, num_aux, sizeof(*sof_aux), GFP_KERNEL); + if (!sof_aux) + return -ENOMEM; + + ret = asoc_sdw_parse_sdw_endpoints(dev, ctx, sof_aux, 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; + card->aux_dev = sof_aux; + card->num_aux_devs = num_aux; + + /* SDW */ + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, + sof_dais, num_ends, &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(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + sof_sdw_quirk, quirk_override); + sof_sdw_quirk = quirk_override; + } + + log_quirks(&pdev->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(&pdev->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + + /* Register the card */ + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err_probe(&pdev->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[] = { + { .name = "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 +// + +/* + * SOF Machine Driver Support for ACP HW block + */ + +#include +#include +#include +#include +#include +#include + +#include "acp-mach.h" + +static struct acp_card_drvdata sof_rt5682_rt1019_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, +}; + +static struct acp_card_drvdata sof_rt5682_max_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, +}; + +static struct acp_card_drvdata sof_rt5682s_rt1019_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, +}; + +static struct acp_card_drvdata sof_rt5682s_max_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_SP, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, +}; + +static struct acp_card_drvdata sof_nau8825_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = NAU8825, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, + .soc_mclk = true, +}; + +static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, + .soc_mclk = true, +}; + +static struct acp_card_drvdata sof_nau8821_max98388_data = { + .hs_cpu_id = I2S_SP, + .amp_cpu_id = I2S_HS, + .bt_cpu_id = I2S_BT, + .hs_codec_id = NAU8821, + .amp_codec_id = MAX98388, + .soc_mclk = true, +}; + +static int acp_sof_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card; + 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; + + if (!pdev->id_entry) + return -EINVAL; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->dev = dev; + card->owner = THIS_MODULE; + card->name = pdev->id_entry->name; + card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; + /* Widgets and controls added per-codec in acp-mach-common.c */ + + acp_card_drvdata = card->drvdata; + dmi_id = dmi_first_match(acp_quirk_table); + if (dmi_id && dmi_id->driver_data == (void *)QUIRK_TDM_MODE_ENABLE) + acp_card_drvdata->tdm_mode = dmi_id->driver_data; + + 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) + return dev_err_probe(&pdev->dev, ret, + "Failed to register card(%s)\n", card->name); + return 0; +} + +static const struct platform_device_id board_ids[] = { + { + .name = "rt5682-rt1019", + .driver_data = (kernel_ulong_t)&sof_rt5682_rt1019_data, + }, + { + .name = "rt5682-max", + .driver_data = (kernel_ulong_t)&sof_rt5682_max_data, + }, + { + .name = "rt5682s-max", + .driver_data = (kernel_ulong_t)&sof_rt5682s_max_data, + }, + { + .name = "rt5682s-rt1019", + .driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data, + }, + { + .name = "nau8825-max", + .driver_data = (kernel_ulong_t)&sof_nau8825_data, + }, + { + .name = "rt5682s-hs-rt1019", + .driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data, + }, + { + .name = "nau8821-max", + .driver_data = (kernel_ulong_t)&sof_nau8821_max98388_data, + }, + { } +}; +MODULE_DEVICE_TABLE(platform, board_ids); + +static struct platform_driver acp_asoc_audio = { + .driver = { + .name = "sof_mach", + .pm = &snd_soc_pm_ops, + }, + .probe = acp_sof_probe, + .id_table = board_ids, +}; + +module_platform_driver(acp_asoc_audio); + +MODULE_IMPORT_NS("SND_SOC_AMD_MACH"); +MODULE_DESCRIPTION("ACP SOF Machine Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c new file mode 100644 index 000000000..3a640e652 --- /dev/null +++ b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Machine driver for AMD ACP Audio engine using ES8336 codec. +// +// Copyright 2023 Marian Postevca +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../acp-mach.h" +#include "acp3x-es83xx.h" + +#define get_mach_priv(card) ((struct acp3x_es83xx_private *)((acp_get_drvdata(card))->mach_priv)) + +#define DUAL_CHANNEL 2 + +#define ES83XX_ENABLE_DMIC BIT(4) +#define ES83XX_48_MHZ_MCLK BIT(5) + +struct acp3x_es83xx_private { + bool speaker_on; + bool headphone_on; + unsigned long quirk; + struct snd_soc_component *codec; + struct device *codec_dev; + struct gpio_desc *gpio_speakers, *gpio_headphone; + struct acpi_gpio_params enable_spk_gpio, enable_hp_gpio; + struct acpi_gpio_mapping gpio_mapping[3]; + struct snd_soc_dapm_route mic_map[2]; +}; + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +#define ES83xx_12288_KHZ_MCLK_FREQ (48000 * 256) +#define ES83xx_48_MHZ_MCLK_FREQ (48000 * 1000) + +static int acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +static int acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); + +static int acp3x_es83xx_codec_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *codec_dai; + struct acp3x_es83xx_private *priv; + unsigned int freq; + int ret; + + runtime = substream->runtime; + rtd = snd_soc_substream_to_rtd(substream); + codec_dai = snd_soc_rtd_to_codec(rtd, 0); + priv = get_mach_priv(rtd->card); + + if (priv->quirk & ES83XX_48_MHZ_MCLK) { + dev_dbg(priv->codec_dev, "using a 48Mhz MCLK\n"); + freq = ES83xx_48_MHZ_MCLK_FREQ; + } else { + dev_dbg(priv->codec_dev, "using a 12.288Mhz MCLK\n"); + freq = ES83xx_12288_KHZ_MCLK_FREQ; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + return 0; +} + +static struct snd_soc_jack es83xx_jack; + +static struct snd_soc_jack_pin es83xx_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_soc_dapm_widget acp3x_es83xx_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic", NULL), + + SND_SOC_DAPM_SUPPLY("Headphone Power", SND_SOC_NOPM, 0, 0, + acp3x_es83xx_headphone_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0, + acp3x_es83xx_speaker_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +}; + +static const struct snd_soc_dapm_route acp3x_es83xx_audio_map[] = { + {"Headphone", NULL, "HPOL"}, + {"Headphone", NULL, "HPOR"}, + {"Headphone", NULL, "Headphone Power"}, + + /* + * There is no separate speaker output instead the speakers are muxed to + * the HP outputs. The mux is controlled Speaker and/or headphone switch. + */ + {"Speaker", NULL, "HPOL"}, + {"Speaker", NULL, "HPOR"}, + {"Speaker", NULL, "Speaker Power"}, +}; + + +static const struct snd_kcontrol_new acp3x_es83xx_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Internal Mic"), +}; + +static int acp3x_es83xx_configure_widgets(struct snd_soc_card *card) +{ + card->dapm_widgets = acp3x_es83xx_widgets; + card->num_dapm_widgets = ARRAY_SIZE(acp3x_es83xx_widgets); + card->controls = acp3x_es83xx_controls; + card->num_controls = ARRAY_SIZE(acp3x_es83xx_controls); + card->dapm_routes = acp3x_es83xx_audio_map; + card->num_dapm_routes = ARRAY_SIZE(acp3x_es83xx_audio_map); + + return 0; +} + +static int acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); + struct acp3x_es83xx_private *priv = get_mach_priv(card); + + dev_dbg(priv->codec_dev, "headphone power event = %d\n", event); + if (SND_SOC_DAPM_EVENT_ON(event)) + priv->headphone_on = true; + else + priv->headphone_on = false; + + gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_on); + gpiod_set_value_cansleep(priv->gpio_headphone, priv->headphone_on); + + return 0; +} + +static int acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); + struct acp3x_es83xx_private *priv = get_mach_priv(card); + + dev_dbg(priv->codec_dev, "speaker power event: %d\n", event); + if (SND_SOC_DAPM_EVENT_ON(event)) + priv->speaker_on = true; + else + priv->speaker_on = false; + + gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_on); + gpiod_set_value_cansleep(priv->gpio_headphone, priv->headphone_on); + + return 0; +} + +static int acp3x_es83xx_suspend_pre(struct snd_soc_card *card) +{ + struct acp3x_es83xx_private *priv = get_mach_priv(card); + + /* We need to disable the jack in the machine driver suspend + * callback so that the CODEC suspend callback actually gets + * called. Without doing it, the CODEC suspend/resume + * callbacks do not get called if headphones are plugged in. + * This is because plugging in headphones keeps some supplies + * active, this in turn means that the lowest bias level + * that the CODEC can go to is SND_SOC_BIAS_STANDBY. + * If components do not set idle_bias_on to true then + * their suspend/resume callbacks do not get called. + */ + dev_dbg(priv->codec_dev, "card suspend\n"); + snd_soc_component_set_jack(priv->codec, NULL, NULL); + return 0; +} + +static int acp3x_es83xx_resume_post(struct snd_soc_card *card) +{ + struct acp3x_es83xx_private *priv = get_mach_priv(card); + + /* We disabled jack detection in suspend callback, + * enable it back. + */ + dev_dbg(priv->codec_dev, "card resume\n"); + snd_soc_component_set_jack(priv->codec, &es83xx_jack, NULL); + return 0; +} + +static int acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private *priv) +{ + + priv->enable_spk_gpio.crs_entry_index = 0; + priv->enable_hp_gpio.crs_entry_index = 1; + + priv->enable_spk_gpio.active_low = false; + priv->enable_hp_gpio.active_low = false; + + priv->gpio_mapping[0].name = "speakers-enable-gpios"; + priv->gpio_mapping[0].data = &priv->enable_spk_gpio; + priv->gpio_mapping[0].size = 1; + priv->gpio_mapping[0].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO; + + priv->gpio_mapping[1].name = "headphone-enable-gpios"; + priv->gpio_mapping[1].data = &priv->enable_hp_gpio; + priv->gpio_mapping[1].size = 1; + priv->gpio_mapping[1].quirks = ACPI_GPIO_QUIRK_ONLY_GPIOIO; + + dev_info(priv->codec_dev, "speaker gpio %d active %s, headphone gpio %d active %s\n", + priv->enable_spk_gpio.crs_entry_index, + str_low_high(priv->enable_spk_gpio.active_low), + priv->enable_hp_gpio.crs_entry_index, + str_low_high(priv->enable_hp_gpio.active_low)); + return 0; +} + +static int acp3x_es83xx_configure_mics(struct acp3x_es83xx_private *priv) +{ + int num_routes = 0; + int i; + + if (!(priv->quirk & ES83XX_ENABLE_DMIC)) { + priv->mic_map[num_routes].sink = "MIC1"; + priv->mic_map[num_routes].source = "Internal Mic"; + num_routes++; + } + + priv->mic_map[num_routes].sink = "MIC2"; + priv->mic_map[num_routes].source = "Headset Mic"; + num_routes++; + + for (i = 0; i < num_routes; i++) + dev_info(priv->codec_dev, "%s is %s\n", + priv->mic_map[i].source, priv->mic_map[i].sink); + + return num_routes; +} + +static int acp3x_es83xx_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_card *card = runtime->card; + struct acp3x_es83xx_private *priv = get_mach_priv(card); + int ret = 0; + int num_routes; + + ret = snd_soc_card_jack_new_pins(card, "Headset", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &es83xx_jack, es83xx_jack_pins, + ARRAY_SIZE(es83xx_jack_pins)); + if (ret) { + dev_err(card->dev, "jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(es83xx_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + + snd_soc_component_set_jack(codec, &es83xx_jack, NULL); + + priv->codec = codec; + acp3x_es83xx_configure_gpios(priv); + + ret = devm_acpi_dev_add_driver_gpios(priv->codec_dev, priv->gpio_mapping); + if (ret) + dev_warn(priv->codec_dev, "failed to add speaker gpio\n"); + + priv->gpio_speakers = gpiod_get_optional(priv->codec_dev, "speakers-enable", + priv->enable_spk_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_speakers)) { + dev_err(priv->codec_dev, "could not get speakers-enable GPIO\n"); + return PTR_ERR(priv->gpio_speakers); + } + + priv->gpio_headphone = gpiod_get_optional(priv->codec_dev, "headphone-enable", + priv->enable_hp_gpio.active_low ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_headphone)) { + dev_err(priv->codec_dev, "could not get headphone-enable GPIO\n"); + return PTR_ERR(priv->gpio_headphone); + } + + num_routes = acp3x_es83xx_configure_mics(priv); + if (num_routes > 0) { + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + + ret = snd_soc_dapm_add_routes(dapm, priv->mic_map, num_routes); + if (ret != 0) + device_remove_software_node(priv->codec_dev); + } + + return ret; +} + +static const struct snd_soc_ops acp3x_es83xx_ops = { + .startup = acp3x_es83xx_codec_startup, +}; + + +SND_SOC_DAILINK_DEF(codec, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi"))); + +static const struct dmi_system_id acp3x_es83xx_dmi_table[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC|ES83XX_48_MHZ_MCLK), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1060"), + }, + .driver_data = (void *)(ES83XX_ENABLE_DMIC), + }, + {} +}; + +static int acp3x_es83xx_configure_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) +{ + link->codecs = codec; + link->num_codecs = ARRAY_SIZE(codec); + link->init = acp3x_es83xx_init; + link->ops = &acp3x_es83xx_ops; + link->dai_fmt = SND_SOC_DAIFMT_I2S + | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + return 0; +} + +static int acp3x_es83xx_probe(struct snd_soc_card *card) +{ + int ret = 0; + struct device *dev = card->dev; + const struct dmi_system_id *dmi_id; + + dmi_id = dmi_first_match(acp3x_es83xx_dmi_table); + if (dmi_id && dmi_id->driver_data) { + struct acp3x_es83xx_private *priv; + struct acp_card_drvdata *acp_drvdata; + struct acpi_device *adev; + struct device *codec_dev; + + acp_drvdata = (struct acp_card_drvdata *)card->drvdata; + + dev_info(dev, "matched DMI table with this system, trying to register sound card\n"); + + adev = acpi_dev_get_first_match_dev(acp_drvdata->acpi_mach->id, NULL, -1); + if (!adev) { + dev_err(dev, "Error cannot find '%s' dev\n", acp_drvdata->acpi_mach->id); + return -ENXIO; + } + + codec_dev = acpi_get_first_physical_node(adev); + acpi_dev_put(adev); + if (!codec_dev) { + dev_warn(dev, "Error cannot find codec device, will defer probe\n"); + return -EPROBE_DEFER; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + put_device(codec_dev); + return -ENOMEM; + } + + priv->codec_dev = codec_dev; + priv->quirk = (unsigned long)dmi_id->driver_data; + acp_drvdata->mach_priv = priv; + dev_info(dev, "successfully probed the sound card\n"); + } else { + ret = -ENODEV; + dev_warn(dev, "this system has a ES83xx codec defined in ACPI, but the driver doesn't have this system registered in DMI table\n"); + } + return ret; +} + + +void acp3x_es83xx_init_ops(struct acp_mach_ops *ops) +{ + ops->probe = acp3x_es83xx_probe; + ops->configure_widgets = acp3x_es83xx_configure_widgets; + ops->configure_link = acp3x_es83xx_configure_link; + ops->suspend_pre = acp3x_es83xx_suspend_pre; + ops->resume_post = acp3x_es83xx_resume_post; +} diff --git a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h new file mode 100644 index 000000000..03551ffdd --- /dev/null +++ b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2023 Marian Postevca + */ + +#ifndef __ACP3X_ES83XX_H +#define __ACP3X_ES83XX_H + +void acp3x_es83xx_init_ops(struct acp_mach_ops *ops); + +#endif + diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c new file mode 100644 index 000000000..10fb416b9 --- /dev/null +++ b/sound/soc/amd/acp/acp63.c @@ -0,0 +1,298 @@ +// 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. +// +// Authors: Syed Saba kareem +/* + * Hardware interface for ACP6.3 block + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "amd.h" +#include "acp-mach.h" +#include "../mach-config.h" + +#define DRV_NAME "acp_asoc_acp63" + +#define CLK_PLL_PWR_REQ_N0 0X0006C2C0 +#define CLK_SPLL_FIELD_2_N0 0X0006C114 +#define CLK_PLL_REQ_N0 0X0006C0DC +#define CLK_DFSBYPASS_CONTR 0X0006C2C8 +#define CLK_DFS_CNTL_N0 0X0006C1A4 + +#define PLL_AUTO_STOP_REQ BIT(4) +#define PLL_AUTO_START_REQ BIT(0) +#define PLL_FRANCE_EN BIT(4) +#define EXIT_DPF_BYPASS_0 BIT(16) +#define EXIT_DPF_BYPASS_1 BIT(17) +#define CLK0_DIVIDER 0X30 + +union clk_pll_req_no { + struct { + u32 fb_mult_int : 9; + u32 reserved : 3; + u32 pll_spine_div : 4; + u32 gb_mult_frac : 16; + } bitfields, bits; + u32 clk_pll_req_no_reg; +}; + +static struct snd_soc_dai_driver acp63_dai[] = { +{ + .name = "acp-i2s-sp", + .id = I2S_SP_INSTANCE, + .playback = { + .stream_name = "I2S SP Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S SP Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-bt", + .id = I2S_BT_INSTANCE, + .playback = { + .stream_name = "I2S BT Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S BT Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-hs", + .id = I2S_HS_INSTANCE, + .playback = { + .stream_name = "I2S HS Playback", + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .stream_name = "I2S HS Capture", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-pdm-dmic", + .id = DMIC_INSTANCE, + .capture = { + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &acp_dmic_dai_ops, +}, +}; + +static int acp63_i2s_master_clock_generate(struct acp_chip_info *chip) +{ + int rc; + u32 data; + union clk_pll_req_no clk_pll; + + /* Clk5 pll register values to get mclk as 196.6MHz*/ + clk_pll.bits.fb_mult_int = 0x31; + clk_pll.bits.pll_spine_div = 0; + clk_pll.bits.gb_mult_frac = 0x26E9; + + rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ); + if (rc) + return rc; + + rc = amd_smn_read(0, CLK_SPLL_FIELD_2_N0, &data); + if (rc) + return rc; + if (data & PLL_FRANCE_EN) { + rc = amd_smn_write(0, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN); + if (rc) + return rc; + } + + rc = amd_smn_write(0, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg); + if (rc) + return rc; + + rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ); + if (rc) + return rc; + + rc = amd_smn_read(0, CLK_DFSBYPASS_CONTR, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1); + if (rc) + return rc; + + return amd_smn_write(0, CLK_DFS_CNTL_N0, CLK0_DIVIDER); +} + +static int acp63_audio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip; + int ret; + + chip = dev_get_platdata(&pdev->dev); + if (!chip || !chip->base) { + dev_err(&pdev->dev, "ACP chip data is NULL\n"); + return -ENODEV; + } + + if (chip->acp_rev != ACP63_PCI_ID) { + dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); + return -ENODEV; + } + + chip->dev = dev; + chip->dai_driver = acp63_dai; + chip->num_dai = ARRAY_SIZE(acp63_dai); + + if (chip->is_i2s_config && chip->rsrc->soc_mclk) { + ret = acp63_i2s_master_clock_generate(chip); + if (ret) + return ret; + } + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } + acp_platform_register(dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp63_audio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); + + acp_platform_unregister(dev); + pm_runtime_disable(&pdev->dev); +} + +static int acp63_pcm_resume(struct device *dev) +{ + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream; + struct snd_pcm_substream *substream; + snd_pcm_uframes_t buf_in_frames; + u64 buf_size; + + if (chip->is_i2s_config && chip->rsrc->soc_mclk) + acp63_i2s_master_clock_generate(chip); + + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + substream = stream->substream; + if (substream && substream->runtime) { + buf_in_frames = (substream->runtime->buffer_size); + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); + if (stream->dai_id) + restore_acp_i2s_params(substream, chip, stream); + else + restore_acp_pdm_params(substream, chip); + } + } + spin_unlock(&chip->acp_lock); + return 0; +} + +static const struct dev_pm_ops acp63_dma_pm_ops = { + SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume) +}; + +static struct platform_driver acp63_driver = { + .probe = acp63_audio_probe, + .remove = acp63_audio_remove, + .driver = { + .name = "acp_asoc_acp63", + .pm = pm_ptr(&acp63_dma_pm_ops), + }, +}; + +module_platform_driver(acp63_driver); + +MODULE_DESCRIPTION("AMD ACP acp63 Driver"); +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 new file mode 100644 index 000000000..bca311c88 --- /dev/null +++ b/sound/soc/amd/acp/acp70.c @@ -0,0 +1,228 @@ +// 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. +// +// Authors: Syed Saba kareem +/* + * Hardware interface for ACP7.0 block + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "amd.h" +#include "acp-mach.h" + +#include + +#define DRV_NAME "acp_asoc_acp70" + +#define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4 +#define CLK0_DIVIDER 0X19 + +static struct snd_soc_dai_driver acp70_dai[] = { +{ + .name = "acp-i2s-sp", + .id = I2S_SP_INSTANCE, + .playback = { + .stream_name = "I2S SP Playback", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .capture = { + .stream_name = "I2S SP Capture", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-bt", + .id = I2S_BT_INSTANCE, + .playback = { + .stream_name = "I2S BT Playback", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .capture = { + .stream_name = "I2S BT Capture", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-i2s-hs", + .id = I2S_HS_INSTANCE, + .playback = { + .stream_name = "I2S HS Playback", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .capture = { + .stream_name = "I2S HS Capture", + .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 = 32, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &asoc_acp_cpu_dai_ops, +}, +{ + .name = "acp-pdm-dmic", + .id = DMIC_INSTANCE, + .capture = { + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &acp_dmic_dai_ops, +}, +}; + +static int acp_acp70_audio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip; + int ret; + + chip = dev_get_platdata(&pdev->dev); + if (!chip || !chip->base) { + dev_err(&pdev->dev, "ACP chip data is NULL\n"); + return -ENODEV; + } + + switch (chip->acp_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: + case ACP72_PCI_ID: + break; + default: + dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); + return -ENODEV; + } + + chip->dev = dev; + chip->dai_driver = acp70_dai; + chip->num_dai = ARRAY_SIZE(acp70_dai); + + /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ + ret = amd_smn_write(0, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); + if (ret) { + dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); + return ret; + } + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } + acp_platform_register(dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp_acp70_audio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); + + acp_platform_unregister(dev); + pm_runtime_disable(&pdev->dev); +} + +static int acp70_pcm_resume(struct device *dev) +{ + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); + struct acp_stream *stream; + struct snd_pcm_substream *substream; + snd_pcm_uframes_t buf_in_frames; + u64 buf_size; + + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { + substream = stream->substream; + if (substream && substream->runtime) { + buf_in_frames = (substream->runtime->buffer_size); + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); + if (stream->dai_id) + restore_acp_i2s_params(substream, chip, stream); + else + restore_acp_pdm_params(substream, chip); + } + } + spin_unlock(&chip->acp_lock); + return 0; +} + +static const struct dev_pm_ops acp70_dma_pm_ops = { + SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume) +}; + +static struct platform_driver acp70_driver = { + .probe = acp_acp70_audio_probe, + .remove = acp_acp70_audio_remove, + .driver = { + .name = "acp_asoc_acp70", + .pm = pm_ptr(&acp70_dma_pm_ops), + }, +}; + +module_platform_driver(acp70_driver); + +MODULE_DESCRIPTION("AMD ACP ACP70 Driver"); +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 000000000..984685602 --- /dev/null +++ b/sound/soc/amd/acp/acp_common.h @@ -0,0 +1,20 @@ +/* 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 +#define ACP72_PCI_ID 0x72 + +#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 000000000..1dbbaba3c --- /dev/null +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -0,0 +1,557 @@ +// 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 +#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_endpoint spk_2_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 2, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint spk_3_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 3, + .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_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l56x4_l1u3210_adr[] = { + { + .adr = 0x00013301FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013201FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013101FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00013001FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l0u01_adr[] = { + { + .adr = 0x00003001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00003101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l1u01_adr[] = { + { + .adr = 0x00013001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l1u13_adr[] = { + { + .adr = 0x00013101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013301FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x4_l0u0246_adr[] = { + { + .adr = 0x00003001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00003201FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00003401FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00003601FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l0u0_adr[] = { + { + .adr = 0x00003001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l0u1_adr[] = { + { + .adr = 0x00003101FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43b_l0u1_adr[] = { + { + .adr = 0x00003101FA2A3B01ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l1u0_cs35l56x4_l1u0123_adr[] = { + { + .adr = 0x00013001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + }, + { + .adr = 0x00013001FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013201FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00013301FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l45_l0u0_adr[] = { + { + .adr = 0x00003001FA424501ull, + /* Re-use endpoints, but cs42l45 has no speaker */ + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints) - 1, + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l45" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l45_l1u0_adr[] = { + { + .adr = 0x00013001FA424501ull, + /* Re-use endpoints, but cs42l45 has no speaker */ + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints) - 1, + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l45" + } +}; + +static const struct snd_soc_acpi_link_adr acp63_cs35l56x4_l1u3210[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56x4_l1u3210_adr), + .adr_d = cs35l56x4_l1u3210_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs35l63x4_l0u0246[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x4_l0u0246_adr), + .adr_d = cs35l63x4_l0u0246_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l43_l0u1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_l0u1_adr), + .adr_d = cs42l43_l0u1_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l43b_l0u1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43b_l0u1_adr), + .adr_d = cs42l43b_l0u1_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l43_l0u0_cs35l56x4_l1u3210[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_l0u0_adr), + .adr_d = cs42l43_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56x4_l1u3210_adr), + .adr_d = cs35l56x4_l1u3210_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l43_l1u0_cs35l56x4_l1u0123[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l43_l1u0_cs35l56x4_l1u0123_adr), + .adr_d = cs42l43_l1u0_cs35l56x4_l1u0123_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l0u0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l0u0_cs35l63x2_l1u01[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l63x2_l1u01_adr), + .adr_d = cs35l63x2_l1u01_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l0u0_cs35l63x2_l1u13[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l63x2_l1u13_adr), + .adr_d = cs35l63x2_l1u13_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l1u0[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l1u0_cs35l63x2_l0u01[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x2_l0u01_adr), + .adr_d = cs35l63x2_l0u01_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp63_cs42l45_l1u0_cs35l63x4_l0u0246[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x4_l0u0246_adr), + .adr_d = cs35l63x4_l0u0246_adr, + }, + {} +}; + +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", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_cs42l43_l0u0_cs35l56x4_l1u3210, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_cs42l45_l1u0_cs35l63x4_l0u0246, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_cs42l45_l0u0_cs35l63x2_l1u01, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_cs42l45_l0u0_cs35l63x2_l1u13, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_cs42l45_l1u0_cs35l63x2_l0u01, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp63_cs42l43_l1u0_cs35l56x4_l1u0123, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp63_cs35l56x4_l1u3210, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp63_cs35l63x4_l0u0246, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp63_cs42l43_l0u1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp63_cs42l43b_l0u1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp63_cs42l45_l0u0, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp63_cs42l45_l1u0, + .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-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c new file mode 100644 index 000000000..815e088b4 --- /dev/null +++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c @@ -0,0 +1,880 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acp70-acpi-match.c - tables and support for ACP 7.0 & ACP7.1 + * ACPI enumeration. + * + * Copyright 2025 Advanced Micro Devices, Inc. + */ + +#include +#include "soc-acpi-amd-sdca-quirks.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_endpoint spk_2_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 2, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint spk_3_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 3, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint jack_amp_g1_dmic_endpoints[] = { + /* Jack Endpoint */ + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + /* Amp Endpoint, work as spk_l_endpoint */ + { + .num = 1, + .aggregated = 1, + .group_position = 0, + .group_id = 1, + }, + /* DMIC Endpoint */ + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_endpoint jack_dmic_endpoints[] = { + /* Jack Endpoint */ + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + /* DMIC Endpoint */ + { + /* + * rt721 endpoint #2 maps to AIF3 (internal DMIC capture). + * Endpoint #1 is AIF2 amp path and is handled by external amps + * on this platform. + */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt712_vb_1_group1_adr[] = { + { + .adr = 0x000130025D071201ull, + .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints), + .endpoints = jack_amp_g1_dmic_endpoints, + .name_prefix = "rt712" + } +}; + +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 acp70_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_adr_device rt1320_1_single_adr[] = { + { + .adr = 0x000130025D132001ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1320-1" + } +}; + +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l56x4_l1u3210_adr[] = { + { + .adr = 0x00013301FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013201FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013101FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00013001FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l0u01_adr[] = { + { + .adr = 0x00003001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00003101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l1u01_adr[] = { + { + .adr = 0x00013001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x2_l1u13_adr[] = { + { + .adr = 0x00013101FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013301FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, +}; + +static const struct snd_soc_acpi_adr_device cs35l63x4_l0u0246_adr[] = { + { + .adr = 0x00003001FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00003201FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00003401FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00003601FA356301ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l0u0_adr[] = { + { + .adr = 0x00003001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l0u1_adr[] = { + { + .adr = 0x00003101FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43b_l0u1_adr[] = { + { + .adr = 0x00003101FA2A3B01ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l43_l1u0_cs35l56x4_l1u0123_adr[] = { + { + .adr = 0x00013001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + }, + { + .adr = 0x00013001FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013201FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP3" + }, + { + .adr = 0x00013301FA355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP4" + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l45_l0u0_adr[] = { + { + .adr = 0x00003001FA424501ull, + /* Re-use endpoints, but cs42l45 has no speaker */ + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints) - 1, + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l45" + } +}; + +static const struct snd_soc_acpi_adr_device cs42l45_l1u0_adr[] = { + { + .adr = 0x00013001FA424501ull, + /* Re-use endpoints, but cs42l45 has no speaker */ + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints) - 1, + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l45" + } +}; + +static const struct snd_soc_acpi_link_adr acp70_cs35l56x4_l1u3210[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56x4_l1u3210_adr), + .adr_d = cs35l56x4_l1u3210_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs35l63x4_l0u0246[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x4_l0u0246_adr), + .adr_d = cs35l63x4_l0u0246_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l43_l0u1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_l0u1_adr), + .adr_d = cs42l43_l0u1_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l43b_l0u1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43b_l0u1_adr), + .adr_d = cs42l43b_l0u1_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l43_l0u0_cs35l56x4_l1u3210[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_l0u0_adr), + .adr_d = cs42l43_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56x4_l1u3210_adr), + .adr_d = cs35l56x4_l1u3210_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l43_l1u0_cs35l56x4_l1u0123[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l43_l1u0_cs35l56x4_l1u0123_adr), + .adr_d = cs42l43_l1u0_cs35l56x4_l1u0123_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l0u0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l0u0_cs35l63x2_l1u01[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l63x2_l1u01_adr), + .adr_d = cs35l63x2_l1u01_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l0u0_cs35l63x2_l1u13[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l45_l0u0_adr), + .adr_d = cs42l45_l0u0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l63x2_l1u13_adr), + .adr_d = cs35l63x2_l1u13_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l1u0[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l1u0_cs35l63x2_l0u01[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x2_l0u01_adr), + .adr_d = cs35l63x2_l0u01_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_cs42l45_l1u0_cs35l63x4_l0u0246[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs42l45_l1u0_adr), + .adr_d = cs42l45_l1u0_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs35l63x4_l0u0246_adr), + .adr_d = cs35l63x4_l0u0246_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_alc712_vb_l1[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt712_vb_1_group1_adr), + .adr_d = rt712_vb_1_group1_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_rt722_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr acp70_rt722_l0_rt1320_l1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1320_1_single_adr), + .adr_d = rt1320_1_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_adr_device tas2783_2_adr[] = { + { + /* left */ + .adr = 0x00003c0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-1", + }, + { + /* right */ + .adr = 0x00003d0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-2", + }, + { + /* left */ + .adr = 0x0000390102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-3", + }, + { + /* right */ + .adr = 0x00003a0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-4", + }, +}; + +static const struct snd_soc_acpi_link_adr acp70_tas2783_2[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tas2783_2_adr), + .adr_d = tas2783_2_adr, + }, + {} +}; + +static const struct snd_soc_acpi_adr_device rt1320_0_single_adr[] = { + { + .adr = 0x000030025D132001ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1320-1" + } +}; + +static const struct snd_soc_acpi_adr_device rt722_1_single_adr[] = { + { + .adr = 0x000130025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_link_adr acp70_rt1320_l0_rt722_l1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt1320_0_single_adr), + .adr_d = rt1320_0_single_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt722_1_single_adr), + .adr_d = rt722_1_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_adr_device rt721_l1u0_tas2783x2_l1u8b_adr[] = { + { + .adr = 0x000130025D072101ull, + /* + * On this platform speakers are provided by two TAS2783 amps. + * Keep rt721 as UAJ + DMIC only. + */ + .num_endpoints = ARRAY_SIZE(jack_dmic_endpoints), + .endpoints = jack_dmic_endpoints, + .name_prefix = "rt721", + }, + { + .adr = 0x0001380102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-1", + }, + { + .adr = 0x00013B0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-2", + }, +}; + +static const struct snd_soc_acpi_link_adr acp70_rt721_l1u0_tas2783x2_l1u8b[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt721_l1u0_tas2783x2_l1u8b_adr), + .adr_d = rt721_l1u0_tas2783x2_l1u8b_adr, + }, + {} +}; + +static const struct snd_soc_acpi_adr_device rt712_vb_l1u0_adr[] = { + { + .adr = 0x000130025D071201ull, + /* + * On this platform speakers are provided by two TAS2783 amps, + * so the AIF2 amp path is left unused: jack + DMIC only. + */ + .num_endpoints = ARRAY_SIZE(jack_dmic_endpoints), + .endpoints = jack_dmic_endpoints, + .name_prefix = "rt712" + } +}; + +/* + * Unique ID 0xC drives the left speaker and 0x9 the right one. The order of the + * entries matters as much as the endpoints: asoc_sdw_parse_sdw_endpoints() + * appends them to the dailink in array order and sdw_compute_slave_ports() + * hands out payload block offsets in that same order, so the first entry is the + * one that receives channel 0. + */ +static const struct snd_soc_acpi_adr_device tas2783x2_l0u9c_adr[] = { + { + .adr = 0x00003C0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-1", + }, + { + .adr = 0x0000390102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-2", + }, +}; + +/* HP OmniBook X Flip 14-kc0xxx (board 8EA1) */ +static const struct snd_soc_acpi_link_adr acp70_tas2783x2_l0u9c_rt712_vb_l1u0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tas2783x2_l0u9c_adr), + .adr_d = tas2783x2_l0u9c_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt712_vb_l1u0_adr), + .adr_d = rt712_vb_l1u0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_endpoint rt721_endpoints[] = { + { /* Jack Playback/Capture Endpoint (AIF1) */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Amplifier Endpoint (AIF2, internal amp) */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint (AIF3) */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt721_1_single_adr[] = { + { + .adr = 0x000130025D072101ull, + .num_endpoints = ARRAY_SIZE(rt721_endpoints), + .endpoints = rt721_endpoints, + .name_prefix = "rt721" + } +}; + +static const struct snd_soc_acpi_link_adr acp70_rt721_only[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt721_1_single_adr), + .adr_d = rt721_1_single_adr, + }, + {} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = { + { + .link_mask = BIT(0), + .links = acp70_tas2783_2, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_tas2783x2_l0u9c_rt712_vb_l1u0, + .machine_check = snd_soc_acpi_amd_sdca_is_device_rt712_vb, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_rt1320_l0_rt722_l1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_rt722_l0_rt1320_l1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_4_in_1_sdca, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_cs42l43_l0u0_cs35l56x4_l1u3210, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_cs42l45_l1u0_cs35l63x4_l0u0246, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_cs42l45_l0u0_cs35l63x2_l1u01, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_cs42l45_l0u0_cs35l63x2_l1u13, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_cs42l45_l1u0_cs35l63x2_l0u01, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_cs42l43_l1u0_cs35l56x4_l1u0123, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_cs35l56x4_l1u3210, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp70_cs35l63x4_l0u0246, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp70_rt722_only, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp70_cs42l43_l0u1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp70_cs42l43b_l0u1, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(0), + .links = acp70_cs42l45_l0u0, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_cs42l45_l1u0, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_alc712_vb_l1, + .machine_check = snd_soc_acpi_amd_sdca_is_device_rt712_vb, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_rt721_l1u0_tas2783x2_l1u8b, + .drv_name = "amd_sdw", + }, + { + .link_mask = BIT(1), + .links = acp70_rt721_only, + .drv_name = "amd_sdw", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sdw_machines); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_sdw_machines[] = { + { + .link_mask = BIT(0), + .links = acp70_rt722_only, + .drv_name = "amd_sof_sdw", + .sof_tplg_filename = "sof-acp_7_0-rt722-l0.tplg", + .fw_filename = "sof-acp_7_0.ri", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sof_sdw_machines); + +MODULE_DESCRIPTION("AMD ACP7.0 & ACP7.1 tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +#if IS_ENABLED(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) +MODULE_IMPORT_NS("SND_SOC_SDCA"); +#endif diff --git a/sound/soc/amd/acp/amd-acpi-mach.c b/sound/soc/amd/acp/amd-acpi-mach.c new file mode 100644 index 000000000..27da2a862 --- /dev/null +++ b/sound/soc/amd/acp/amd-acpi-mach.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acpi-match.c - tables and support for ACP platforms + * ACPI enumeration. + * + * Copyright 2025 Advanced Micro Devices, Inc. + */ + +#include + +static struct snd_soc_acpi_codecs amp_rt1019 = { + .num_codecs = 1, + .codecs = {"10EC1019"} +}; + +static struct snd_soc_acpi_codecs amp_max = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { + { + .id = "10EC5682", + .drv_name = "acp3xalc56821019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682sm98360", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682s1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "AMDI1019", + .drv_name = "renoir-acp", + }, + { + .id = "ESSX8336", + .drv_name = "acp3x-es83xx", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { + { + .id = "10508825", + .drv_name = "rmb-nau8825-max", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "AMDI0007", + .drv_name = "rembrandt-acp", + }, + { + .id = "RTL5682", + .drv_name = "rmb-rt5682s-rt1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_rmb_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { + { + .id = "AMDI0052", + .drv_name = "acp63-acp", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp63_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { + { + .id = "AMDI0029", + .drv_name = "acp70-acp", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp70_acp_machines, "SND_SOC_ACP_COMMON"); + +MODULE_DESCRIPTION("AMD ACP tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Venkataprasad.potturu@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 000000000..0160b0df2 --- /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 + +/* + * SDW AMD ACPI scan helper function + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 new file mode 100644 index 000000000..73a028e67 --- /dev/null +++ b/sound/soc/amd/acp/amd.h @@ -0,0 +1,365 @@ +/* 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) 2021 Advanced Micro Devices, Inc. All rights reserved. + * + * Author: Ajit Kumar Pandey + */ + +#ifndef __AMD_ACP_H +#define __AMD_ACP_H + +#include +#include +#include +#include + +#include "acp_common.h" +#include "chip_offset_byte.h" + +#define DMIC_INSTANCE 0x00 +#define I2S_SP_INSTANCE 0x01 +#define I2S_BT_INSTANCE 0x02 +#define I2S_HS_INSTANCE 0x03 + +#define MEM_WINDOW_START 0x4080000 + +#define ACP_I2S_REG_START 0x1242400 +#define ACP_I2S_REG_END 0x1242810 +#define ACP3x_I2STDM_REG_START 0x1242400 +#define ACP3x_I2STDM_REG_END 0x1242410 +#define ACP3x_BT_TDM_REG_START 0x1242800 +#define ACP3x_BT_TDM_REG_END 0x1242810 + +#define THRESHOLD(bit, base) ((bit) + (base)) +#define I2S_RX_THRESHOLD(base) THRESHOLD(7, base) +#define I2S_TX_THRESHOLD(base) THRESHOLD(8, base) +#define BT_TX_THRESHOLD(base) THRESHOLD(6, base) +#define BT_RX_THRESHOLD(base) THRESHOLD(5, base) +#define HS_TX_THRESHOLD(base) THRESHOLD(4, base) +#define HS_RX_THRESHOLD(base) THRESHOLD(3, base) + +#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 +#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 +#define ACP_SRAM_BT_PB_PTE_OFFSET 0x200 +#define ACP_SRAM_BT_CP_PTE_OFFSET 0x300 +#define ACP_SRAM_PDM_PTE_OFFSET 0x400 +#define ACP_SRAM_HS_PB_PTE_OFFSET 0x500 +#define ACP_SRAM_HS_CP_PTE_OFFSET 0x600 +#define PAGE_SIZE_4K_ENABLE 0x2 + +#define I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define I2S_SP_RX_MEM_WINDOW_START 0x4020000 +#define I2S_BT_TX_MEM_WINDOW_START 0x4040000 +#define I2S_BT_RX_MEM_WINDOW_START 0x4060000 +#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 +#define BT_CAPT_FIFO_ADDR_OFFSET 0xB00 +#define HS_PB_FIFO_ADDR_OFFSET 0xD00 +#define HS_CAPT_FIFO_ADDR_OFFSET 0xF00 +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 8 +#define PLAYBACK_MAX_PERIOD_SIZE 8192 +#define PLAYBACK_MIN_PERIOD_SIZE 1024 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 8 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 1024 + +#define MAX_BUFFER 65536 +#define MIN_BUFFER MAX_BUFFER +#define FIFO_SIZE 0x100 +#define DMA_SIZE 0x40 +#define FRM_LEN 0x100 + +#define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38 + +#define ACP_MAX_STREAM 8 + +#define TDM_ENABLE 1 +#define TDM_DISABLE 0 + +#define SLOT_WIDTH_8 0x8 +#define SLOT_WIDTH_16 0x10 +#define SLOT_WIDTH_24 0x18 +#define SLOT_WIDTH_32 0x20 + +#define ACP6X_PGFSM_CONTROL 0x1024 +#define ACP6X_PGFSM_STATUS 0x1028 + +#define ACP63_PGFSM_CONTROL ACP6X_PGFSM_CONTROL +#define ACP63_PGFSM_STATUS ACP6X_PGFSM_STATUS + +#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 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP_ERROR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xffffffff + +#define ACP_TIMEOUT 500 +#define DELAY_US 5 +#define ACP_SUSPEND_DELAY_MS 2000 + +#define PDM_DMA_STAT 0x10 +#define PDM_DMA_INTR_MASK 0x10000 +#define PDM_DEC_64 0x2 +#define PDM_CLK_FREQ_MASK 0x07 +#define PDM_MISC_CTRL_MASK 0x18 +#define PDM_ENABLE 0x01 +#define PDM_DISABLE 0x00 +#define DMA_EN_MASK 0x02 +#define DELAY_US 5 +#define PDM_TIMEOUT 1000 +#define ACP_REGION2_OFFSET 0x02000000 + +struct acp_chip_info { + char *name; /* Platform name */ + struct resource *res; + struct device *dev; + struct snd_soc_dai_driver *dai_driver; + + unsigned int acp_rev; /* ACP Revision id */ + void __iomem *base; /* ACP memory PCI base */ + struct snd_acp_hw_ops *acp_hw_ops; + int (*acp_hw_ops_init)(struct acp_chip_info *chip); + struct platform_device *chip_pdev; + struct acp_resource *rsrc; /* Platform specific resources*/ + struct list_head stream_list; + spinlock_t acp_lock; /* Used to protect stream_list */ + struct platform_device *dmic_codec_dev; + struct platform_device *acp_plat_dev; + struct platform_device *mach_dev; + struct snd_soc_acpi_mach *machines; + int num_dai; + u32 addr; + u32 bclk_div; + u32 lrclk_div; + u32 ch_mask; + u32 tdm_tx_fmt[3]; + u32 tdm_rx_fmt[3]; + u32 xfer_tx_resolution[3]; + u32 xfer_rx_resolution[3]; + 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 */ + bool tdm_mode; +}; + +struct acp_stream { + struct list_head list; + struct snd_pcm_substream *substream; + int irq_bit; + int dai_id; + int id; + int dir; + u64 bytescount; + u32 reg_offset; + u32 pte_offset; + u32 fifo_offset; +}; + +struct acp_resource { + int offset; + int no_of_ctrls; + int irqp_used; + bool soc_mclk; + u32 irq_reg_offset; + u64 scratch_reg_offset; + u64 sram_pte_offset; +}; + +/** + * struct snd_acp_hw_ops - ACP PCI driver platform specific ops + * @acp_init: ACP initialization + * @acp_deinit: ACP de-initialization + * @irq: ACP irq handler + * @en_interrupts: ACP enable interrupts + * @dis_interrupts: ACP disable interrupts + */ +struct snd_acp_hw_ops { + /* ACP hardware initilizations */ + int (*acp_init)(struct acp_chip_info *chip); + int (*acp_deinit)(struct acp_chip_info *chip); + + /* ACP Interrupts*/ + irqreturn_t (*irq)(int irq, void *data); + int (*en_interrupts)(struct acp_chip_info *chip); + int (*dis_interrupts)(struct acp_chip_info *chip); +}; + +enum acp_config { + ACP_CONFIG_0 = 0, + ACP_CONFIG_1, + ACP_CONFIG_2, + ACP_CONFIG_3, + ACP_CONFIG_4, + ACP_CONFIG_5, + ACP_CONFIG_6, + ACP_CONFIG_7, + ACP_CONFIG_8, + ACP_CONFIG_9, + ACP_CONFIG_10, + ACP_CONFIG_11, + ACP_CONFIG_12, + 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 struct acp_resource rn_rsrc; +extern struct acp_resource rmb_rsrc; +extern struct acp_resource acp63_rsrc; +extern struct acp_resource acp70_rsrc; + +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[]; + +extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; +extern const struct snd_soc_dai_ops acp_dmic_dai_ops; + +int acp_platform_register(struct device *dev); +int acp_platform_unregister(struct device *dev); + +int acp_machine_select(struct acp_chip_info *chip); + +int acp_init(struct acp_chip_info *chip); +int acp_deinit(struct acp_chip_info *chip); +int acp_enable_interrupts(struct acp_chip_info *chip); +int acp_disable_interrupts(struct acp_chip_info *chip); +irqreturn_t acp_irq_handler(int irq, void *data); + +extern struct snd_acp_hw_ops acp31_common_hw_ops; +extern struct snd_acp_hw_ops acp6x_common_hw_ops; +extern struct snd_acp_hw_ops acp63_common_hw_ops; +extern struct snd_acp_hw_ops acp70_common_hw_ops; +extern int acp31_hw_ops_init(struct acp_chip_info *chip); +extern int acp6x_hw_ops_init(struct acp_chip_info *chip); +extern int acp63_hw_ops_init(struct acp_chip_info *chip); +extern int acp70_hw_ops_init(struct acp_chip_info *chip); +/* Machine configuration */ +int snd_amd_acp_find_config(struct pci_dev *pci); + +void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream); +void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size); +void restore_acp_pdm_params(struct snd_pcm_substream *substream, + struct acp_chip_info *chip); + +int restore_acp_i2s_params(struct snd_pcm_substream *substream, + struct acp_chip_info *chip, struct acp_stream *stream); + +void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip); + +static inline int acp_hw_init(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_init) + return chip->acp_hw_ops->acp_init(chip); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_deinit) + return chip->acp_hw_ops->acp_deinit(chip); + return -EOPNOTSUPP; +} + +static inline int acp_hw_en_interrupts(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->en_interrupts) + return chip->acp_hw_ops->en_interrupts(chip); + return -EOPNOTSUPP; +} + +static inline int acp_hw_dis_interrupts(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->dis_interrupts) + chip->acp_hw_ops->dis_interrupts(chip); + return -EOPNOTSUPP; +} + +static inline u64 acp_get_byte_count(struct acp_chip_info *chip, int dai_id, int direction) +{ + u64 byte_count = 0, low = 0, high = 0; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (dai_id) { + case I2S_BT_INSTANCE: + high = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(chip)); + break; + case I2S_SP_INSTANCE: + high = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(chip)); + break; + case I2S_HS_INSTANCE: + high = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW); + break; + default: + dev_err(chip->dev, "Invalid dai id %x\n", dai_id); + goto POINTER_RETURN_BYTES; + } + } else { + switch (dai_id) { + case I2S_BT_INSTANCE: + high = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(chip)); + break; + case I2S_SP_INSTANCE: + high = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(chip)); + break; + case I2S_HS_INSTANCE: + high = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW); + break; + case DMIC_INSTANCE: + high = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + break; + default: + dev_err(chip->dev, "Invalid dai id %x\n", dai_id); + goto POINTER_RETURN_BYTES; + } + } + /* Get 64 bit value from two 32 bit registers */ + byte_count = (high << 32) | low; + +POINTER_RETURN_BYTES: + return byte_count; +} +#endif diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h new file mode 100644 index 000000000..82275c9de --- /dev/null +++ b/sound/soc/amd/acp/chip_offset_byte.h @@ -0,0 +1,146 @@ +/* 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) 2021 Advanced Micro Devices, Inc. All rights reserved. + * + * Author: Ajit Kumar Pandey + */ + +#ifndef _ACP_IP_OFFSET_HEADER +#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(chip, offset, ctrl) \ + (chip->base + chip->rsrc->irq_reg_offset + offset + (ctrl * 0x04)) + +#define ACP_EXTERNAL_INTR_ENB(chip) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x0, 0x0) +#define ACP_EXTERNAL_INTR_CNTL(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x4, ctrl) +#define ACP_EXTERNAL_INTR_STAT(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, \ + (0x4 + (chip->rsrc->no_of_ctrls * 0x04)), ctrl) + +/* Registers from ACP_AUDIO_BUFFERS block */ + +#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 +#define ACP_HS_RX_FIFOADDR 0x3A9C +#define ACP_HS_RX_FIFOSIZE 0x3AA0 +#define ACP_HS_RX_DMA_SIZE 0x3AA4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x3AA8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x3AAC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x3AB0 +#define ACP_HS_TX_RINGBUFADDR 0x3AB4 +#define ACP_HS_TX_RINGBUFSIZE 0x3AB8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x3ABC +#define ACP_HS_TX_FIFOADDR 0x3AC0 +#define ACP_HS_TX_FIFOSIZE 0x3AC4 +#define ACP_HS_TX_DMA_SIZE 0x3AC8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x3ACC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x3AD0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x3AD4 + +#define ACP_I2STDM_IER 0x2400 +#define ACP_I2STDM_IRER 0x2404 +#define ACP_I2STDM_RXFRMT 0x2408 +#define ACP_I2STDM_ITER 0x240C +#define ACP_I2STDM_TXFRMT 0x2410 + +/* Registers from ACP_BT_TDM block */ + +#define ACP_BTTDM_IER 0x2800 +#define ACP_BTTDM_IRER 0x2804 +#define ACP_BTTDM_RXFRMT 0x2808 +#define ACP_BTTDM_ITER 0x280C +#define ACP_BTTDM_TXFRMT 0x2810 + +/* Registers from ACP_HS_TDM block */ +#define ACP_HSTDM_IER 0x2814 +#define ACP_HSTDM_IRER 0x2818 +#define ACP_HSTDM_RXFRMT 0x281C +#define ACP_HSTDM_ITER 0x2820 +#define ACP_HSTDM_TXFRMT 0x2824 + +/* Registers from ACP_WOV_PDM block */ + +#define ACP_WOV_PDM_ENABLE 0x2C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x2C08 +#define ACP_WOV_RX_RINGBUFADDR 0x2C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x2C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x2C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x2C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x2C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x2C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x2C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x2C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x2C2C +#define ACP_WOV_PDM_VAD_CTRL 0x2C30 +#define ACP_WOV_BUFFER_STATUS 0x2C58 +#define ACP_WOV_MISC_CTRL 0x2C5C +#define ACP_WOV_CLK_CTRL 0x2C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x2C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x2C68 + +#define ACP_I2STDM0_MSTRCLKGEN 0x2414 +#define ACP_I2STDM1_MSTRCLKGEN 0x2418 +#define ACP_I2STDM2_MSTRCLKGEN 0x241C +#endif diff --git a/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c new file mode 100644 index 000000000..9248b6d09 --- /dev/null +++ b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * soc-acpi-amd-sdca-quirks.c - tables and support for SDCA quirks + * + * Copyright(c) 2025 Advanced Micro Devices, Inc. All rights reserved. + * + */ + +#include +#include +#include +#include "soc-acpi-amd-sdca-quirks.h" + +/* + * Pretend machine quirk. The argument type is not the traditional + * 'struct snd_soc_acpi_mach' pointer but instead the sdw_amd_ctx + * which contains the peripheral information required for the + * SoundWire/SDCA filter on the SMART_MIC setup and interface + * revision. When the return value is false, the entry in the + * 'snd_soc_acpi_mach' table needs to be skipped. + */ +bool snd_soc_acpi_amd_sdca_is_device_rt712_vb(void *arg) +{ + struct sdw_amd_ctx *ctx = arg; + int i; + + if (!ctx) + return false; + + for (i = 0; i < ctx->peripherals->num_peripherals; i++) { + if (sdca_device_quirk_match(ctx->peripherals->array[i], + SDCA_QUIRKS_RT712_VB)) + return true; + } + + return false; +} + diff --git a/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.h b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.h new file mode 100644 index 000000000..0e644e71e --- /dev/null +++ b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * soc-acpi-amd-sdca-quirks.h - tables and support for SDCA quirks + * + * Copyright(c) 2025 Advanced Micro Devices, Inc. All rights reserved. + * + */ + +#ifndef _SND_SOC_ACPI_AMD_SDCA_QUIRKS +#define _SND_SOC_ACPI_AMD_SDCA_QUIRKS + +#if IS_ENABLED(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) + +bool snd_soc_acpi_amd_sdca_is_device_rt712_vb(void *arg); + +#else + +static inline bool snd_soc_acpi_amd_sdca_is_device_rt712_vb(void *arg) +{ + return false; +} + +#endif + +#endif 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 000000000..3930cc46f --- /dev/null +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -0,0 +1,62 @@ +/* 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 +#include +#include +#include + +#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 ACP70_PCI_REV 0x70 +#define ACP71_PCI_REV 0x71 +#define ACP72_PCI_REV 0x72 + +#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) +#define ASOC_SDW_FOUR_SPK BIT(4) +#define ASOC_SDW_ACP_DMIC BIT(5) +#define ASOC_SDW_CODEC_SPKR BIT(15) + +#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 + +#define ACP70_SW_AUDIO0_TX 0 +#define ACP70_SW_AUDIO1_TX 1 +#define ACP70_SW_AUDIO2_TX 2 + +#define ACP70_SW_AUDIO0_RX 3 +#define ACP70_SW_AUDIO1_RX 4 +#define ACP70_SW_AUDIO2_RX 5 + +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); +int get_acp70_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 new file mode 100644 index 000000000..4affb00bd --- /dev/null +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -0,0 +1,560 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec. +// +//Copyright 2016 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "raven/acp3x.h" +#include "../codecs/rt5682.h" +#include "../codecs/rt1015.h" + +#define PCO_PLAT_CLK 48000000 +#define RT5682_PLL_FREQ (48000 * 512) +#define DUAL_CHANNEL 2 + +static struct snd_soc_jack pco_jack; +static struct snd_soc_jack_pin pco_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static struct clk *rt5682_dai_wclk; +static struct clk *rt5682_dai_bclk; +static struct gpio_desc *dmic_sel; +void *soc_is_rltk_max(struct device *dev); + +enum { + RT5682 = 0, + MAX, + EC, +}; + +static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + /* set rt5682 dai fmt */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S + | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP); + if (ret < 0) { + dev_err(rtd->card->dev, + "Failed to set rt5682 dai fmt: %d\n", ret); + return ret; + } + + /* set codec PLL */ + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, + PCO_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(rtd->dev, "can't set rt5682 PLL: %d\n", ret); + return ret; + } + + /* Set codec sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, + "Failed to set rt5682 SYSCLK: %d\n", ret); + return ret; + } + + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(rtd->dev, + "Failed to set rt5682 tdm bclk ratio: %d\n", ret); + return ret; + } + + rt5682_dai_wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); + if (IS_ERR(rt5682_dai_wclk)) + return PTR_ERR(rt5682_dai_wclk); + + rt5682_dai_bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); + if (IS_ERR(rt5682_dai_bclk)) + return PTR_ERR(rt5682_dai_bclk); + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &pco_jack, + pco_jack_pins, + ARRAY_SIZE(pco_jack_pins)); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, &pco_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return ret; +} + +static int rt5682_clk_enable(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + + /* RT5682 will support only 48K output with 48M mclk */ + clk_set_rate(rt5682_dai_wclk, 48000); + clk_set_rate(rt5682_dai_bclk, 48000 * 64); + ret = clk_prepare_enable(rt5682_dai_wclk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable wclk %d\n", ret); + return ret; + } + + return ret; +} + +static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int srate, i, ret; + + ret = 0; + srate = params_rate(params); + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (strcmp(codec_dai->name, "rt1015-aif")) + continue; + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, + 64 * srate, 256 * srate); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, + 256 * srate, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + } + return ret; +} + +static void rt5682_clk_disable(void) +{ + clk_disable_unprepare(rt5682_dai_wclk); +} + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int acp3x_5682_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + machine->cap_i2s_instance = I2S_SP_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + return rt5682_clk_enable(substream); +} + +static int acp3x_max_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->play_i2s_instance = I2S_BT_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + return rt5682_clk_enable(substream); +} + +static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + snd_soc_dai_set_bclk_ratio(codec_dai, 64); + + return rt5682_clk_enable(substream); +} + +static int dmic_switch; + +static int dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = dmic_switch; + return 0; +} + +static int dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (dmic_sel) { + dmic_switch = ucontrol->value.integer.value[0]; + gpiod_set_value(dmic_sel, dmic_switch); + } + return 0; +} + +static void rt5682_shutdown(struct snd_pcm_substream *substream) +{ + rt5682_clk_disable(); +} + +static const struct snd_soc_ops acp3x_5682_ops = { + .startup = acp3x_5682_startup, + .shutdown = rt5682_shutdown, +}; + +static const struct snd_soc_ops acp3x_max_play_ops = { + .startup = acp3x_max_startup, + .shutdown = rt5682_shutdown, + .hw_params = acp3x_1015_hw_params, +}; + +static const struct snd_soc_ops acp3x_ec_cap0_ops = { + .startup = acp3x_ec_dmic0_startup, + .shutdown = rt5682_shutdown, +}; + +SND_SOC_DAILINK_DEF(acp3x_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp3x_bt, + DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.2"))); + +SND_SOC_DAILINK_DEF(rt5682, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); +SND_SOC_DAILINK_DEF(max, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(rt1015p, + DAILINK_COMP_ARRAY(COMP_CODEC("RTL1015:00", "HiFi"))); +SND_SOC_DAILINK_DEF(rt1015, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1015:00", "rt1015-aif"), + COMP_CODEC("i2c-10EC1015:01", "rt1015-aif"))); +SND_SOC_DAILINK_DEF(cros_ec, + DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0"))); + +static struct snd_soc_codec_conf rt1015_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_dai_link acp3x_dai[] = { + [RT5682] = { + .name = "acp3x-5682-play", + .stream_name = "Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBP_CFP, + .init = acp3x_5682_init, + .ops = &acp3x_5682_ops, + SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform), + }, + [MAX] = { + .name = "acp3x-max98357-play", + .stream_name = "HiFi Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBC_CFC, + .playback_only = 1, + .ops = &acp3x_max_play_ops, + .cpus = acp3x_bt, + .num_cpus = ARRAY_SIZE(acp3x_bt), + .platforms = platform, + .num_platforms = ARRAY_SIZE(platform), + }, + [EC] = { + .name = "acp3x-ec-dmic0-capture", + .stream_name = "Capture DMIC0", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBC_CFC, + .capture_only = 1, + .ops = &acp3x_ec_cap0_ops, + SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), + }, +}; + +static const char * const dmic_mux_text[] = { + "Front Mic", + "Rear Mic", +}; + +static SOC_ENUM_SINGLE_DECL( + acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text); + +static const struct snd_kcontrol_new acp3x_dmic_mux_control = + SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum, + dmic_get, dmic_set); + +static const struct snd_soc_dapm_widget acp3x_5682_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Spk", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), +}; + +static const struct snd_soc_dapm_route acp3x_5682_audio_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Spk", NULL, "Speaker"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, +}; + +static const struct snd_kcontrol_new acp3x_5682_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Spk"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_card acp3x_5682 = { + .name = "acp3xalc5682m98357", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_5682_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_5682_widgets), + .dapm_routes = acp3x_5682_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_5682_audio_route), + .controls = acp3x_5682_mc_controls, + .num_controls = ARRAY_SIZE(acp3x_5682_mc_controls), +}; + +static const struct snd_soc_dapm_widget acp3x_1015_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_1015_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, + {"Left Spk", NULL, "Left SPO"}, + {"Right Spk", NULL, "Right SPO"}, +}; + +static const struct snd_kcontrol_new acp3x_mc_1015_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static struct snd_soc_card acp3x_1015 = { + .name = "acp3xalc56821015", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_1015_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_1015_widgets), + .dapm_routes = acp3x_1015_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_1015_route), + .codec_conf = rt1015_conf, + .num_configs = ARRAY_SIZE(rt1015_conf), + .controls = acp3x_mc_1015_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_1015_controls), +}; + +static const struct snd_soc_dapm_widget acp3x_1015p_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), + SND_SOC_DAPM_SPK("Speakers", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_1015p_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, + /* speaker */ + { "Speakers", NULL, "Speaker" }, +}; + +static const struct snd_kcontrol_new acp3x_mc_1015p_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_card acp3x_1015p = { + .name = "acp3xalc56821015p", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_1015p_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_1015p_widgets), + .dapm_routes = acp3x_1015p_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_1015p_route), + .controls = acp3x_mc_1015p_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_1015p_controls), +}; + +void *soc_is_rltk_max(struct device *dev) +{ + const struct acpi_device_id *match; + + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) + return NULL; + return (void *)match->driver_data; +} + +static void card_spk_dai_link_present(struct snd_soc_dai_link *links, + const char *card_name) +{ + if (!strcmp(card_name, "acp3xalc56821015")) { + links[1].codecs = rt1015; + links[1].num_codecs = ARRAY_SIZE(rt1015); + } else if (!strcmp(card_name, "acp3xalc56821015p")) { + links[1].codecs = rt1015p; + links[1].num_codecs = ARRAY_SIZE(rt1015p); + } else { + links[1].codecs = max; + links[1].num_codecs = ARRAY_SIZE(max); + } +} + +static int acp3x_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + struct acp3x_platform_info *machine; + struct device *dev = &pdev->dev; + + card = (struct snd_soc_card *)soc_is_rltk_max(dev); + if (!card) + return -ENODEV; + + machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL); + if (!machine) + return -ENOMEM; + + card_spk_dai_link_present(card->dai_link, card->name); + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + + dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW); + if (IS_ERR(dmic_sel)) { + dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", + PTR_ERR(dmic_sel)); + return PTR_ERR(dmic_sel); + } + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card(%s) failed\n", + card->name); + } + return 0; +} + +static const struct acpi_device_id acp3x_audio_acpi_match[] = { + { "AMDI5682", (unsigned long)&acp3x_5682}, + { "AMDI1015", (unsigned long)&acp3x_1015}, + { "10021015", (unsigned long)&acp3x_1015p}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match); + +static struct platform_driver acp3x_audio = { + .driver = { + .name = "acp3x-alc5682-max98357", + .acpi_match_table = ACPI_PTR(acp3x_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = acp3x_probe, +}; + +module_platform_driver(acp3x_audio); + +MODULE_AUTHOR("akshu.agrawal@amd.com"); +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("ALC5682 ALC1015, ALC1015P & MAX98357 audio support"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp7x/Makefile b/sound/soc/amd/acp7x/Makefile new file mode 100644 index 000000000..9426e3b47 --- /dev/null +++ b/sound/soc/amd/acp7x/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +# ACP7.x variants platform Support +snd-pci-acp7x-y := pci-acp7x.o acp7x-common.o + +obj-$(CONFIG_SND_SOC_AMD_ACP7X) += snd-pci-acp7x.o diff --git a/sound/soc/amd/acp7x/acp7x-common.c b/sound/soc/amd/acp7x/acp7x-common.c new file mode 100644 index 000000000..df94864a1 --- /dev/null +++ b/sound/soc/amd/acp7x/acp7x-common.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ACP PCI driver callback routines for ACP7.x + * platforms. + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include + +#include "acp7x.h" + +static int acp7x_power_on(void __iomem *acp_base) +{ + u32 val = 0; + + val = readl(acp_base + ACP_PGFSM_STATUS); + if (!(val & ACP7X_PGFSM_STATUS_MASK)) + return 0; + + writel(ACP7X_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + val = readl(acp_base + ACP_PGFSM_CONTROL); + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, + ((val & ACP7X_PGFSM_STATUS_MASK) == 0), DELAY_US, ACP7X_TIMEOUT); +} + +static int acp7x_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP7X_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP7X_TIMEOUT); +} + +static int acp7x_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp7x_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp7x_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int acp7x_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp7x_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int __maybe_unused snd_acp7x_suspend(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + return ret; +} + +static int __maybe_unused snd_acp7x_runtime_resume(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static int __maybe_unused snd_acp7x_resume(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + return ret; +} + +void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp7x_init; + hw_ops->acp_deinit = acp7x_deinit; + hw_ops->acp_suspend = snd_acp7x_suspend; + hw_ops->acp_resume = snd_acp7x_resume; + hw_ops->acp_suspend_runtime = snd_acp7x_suspend; + hw_ops->acp_resume_runtime = snd_acp7x_runtime_resume; +} diff --git a/sound/soc/amd/acp7x/acp7x.h b/sound/soc/amd/acp7x/acp7x.h new file mode 100644 index 000000000..ddb5eabf6 --- /dev/null +++ b/sound/soc/amd/acp7x/acp7x.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AMD Common ACP header file for ACP7.X variants(ACP7.D/7.E/7.F) + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __SOUND_SOC_AMD_ACP7X_H +#define __SOUND_SOC_AMD_ACP7X_H + +#include +#include +#include +#include +#include + +#include + +#define ACP_DEVICE_ID 0x15E2 +#define ACP7X_REG_START 0x1240000 +#define ACP7X_REG_END 0x125C000 + +#define ACP7D_PCI_REV 0x7D +#define ACP7E_PCI_REV 0x7E +#define ACP7F_PCI_REV 0x7F + +/* Common register helper bits used by acp7x-common.c */ +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define DELAY_US 5 +#define ACP7X_TIMEOUT 5000 + +#define ACP7X_PGFSM_CNTL_POWER_ON_MASK 7 +#define ACP7X_PGFSM_STATUS_MASK 0x3F + +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 + +struct acp_hw_ops { + int (*acp_init)(void __iomem *acp_base, struct device *dev); + int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + int (*acp_suspend)(struct device *dev); + int (*acp_resume)(struct device *dev); + int (*acp_suspend_runtime)(struct device *dev); + int (*acp_resume_runtime)(struct device *dev); +}; + +struct acp7x_dev_data { + void __iomem *acp7x_base; + struct acp_hw_ops *hw_ops; + u32 addr; + u32 reg_range; + u32 acp_rev; +}; + +void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops); + +static inline int acp_hw_init(struct acp7x_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_init) + return adata->hw_ops->acp_init(adata->acp7x_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp7x_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_deinit) + return adata->hw_ops->acp_deinit(adata->acp7x_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend) + return adata->hw_ops->acp_suspend(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_resume(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume) + return adata->hw_ops->acp_resume(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend_runtime(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime) + return adata->hw_ops->acp_suspend_runtime(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_runtime_resume(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime) + return adata->hw_ops->acp_resume_runtime(dev); + return -EOPNOTSUPP; +} + +int snd_amd_acp_find_config(struct pci_dev *pci); + +#endif /* __SOUND_SOC_AMD_ACP7X_H */ diff --git a/sound/soc/amd/acp7x/pci-acp7x.c b/sound/soc/amd/acp7x/pci-acp7x.c new file mode 100644 index 000000000..d29a149cf --- /dev/null +++ b/sound/soc/amd/acp7x/pci-acp7x.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD common ACP PCI driver for ACP7.x variants + * which includes ACP7.D/7.E/7.F and future variants + * with same register layout. + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acp7x.h" + +static int acp_hw_init_ops(struct acp7x_dev_data *adata, struct pci_dev *pci) +{ + adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops), + GFP_KERNEL); + if (!adata->hw_ops) + return -ENOMEM; + + switch (adata->acp_rev) { + case ACP7D_PCI_REV: + case ACP7E_PCI_REV: + case ACP7F_PCI_REV: + acp7x_hw_init_ops(adata->hw_ops); + break; + default: + dev_err(&pci->dev, "ACP device not found\n"); + return -ENODEV; + } + return 0; +} + +static int snd_acp7x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp7x_dev_data *adata; + u32 addr; + u32 flag; + int ret; + + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* ACP PCI revision id check for ACP7.x platforms */ + switch (pci->revision) { + case ACP7D_PCI_REV: + case ACP7E_PCI_REV: + case ACP7F_PCI_REV: + break; + default: + return -ENODEV; + } + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP7.x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + adata = devm_kzalloc(&pci->dev, sizeof(struct acp7x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + addr = pci_resource_start(pci, 0); + adata->acp7x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp7x_base) { + ret = -ENOMEM; + goto release_regions; + } + adata->addr = addr; + adata->reg_range = ACP7X_REG_END - ACP7X_REG_START; + adata->acp_rev = pci->revision; + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = acp_hw_init_ops(adata, pci); + if (ret) { + dev_err(&pci->dev, "ACP hw ops init failed\n"); + goto release_regions; + } + ret = acp_hw_init(adata, &pci->dev); + if (ret) + goto release_regions; + + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int __maybe_unused snd_acp_suspend(struct device *dev) +{ + return acp_hw_suspend(dev); +} + +static int __maybe_unused snd_acp_runtime_resume(struct device *dev) +{ + return acp_hw_runtime_resume(dev); +} + +static int __maybe_unused snd_acp_resume(struct device *dev) +{ + return acp_hw_resume(dev); +} + +static const struct dev_pm_ops acp7x_pm_ops = { + SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) +}; + +static void snd_acp7x_remove(struct pci_dev *pci) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = pci_get_drvdata(pci); + ret = acp_hw_deinit(adata, &pci->dev); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp7x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp7x_ids); + +static struct pci_driver acp7x_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp7x_ids, + .probe = snd_acp7x_probe, + .remove = snd_acp7x_remove, + .driver = { + .pm = &acp7x_pm_ops, + } +}; + +module_pci_driver(acp7x_pci_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP PCI driver for ACP7.X"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/amd/include/acp_2_2_d.h b/sound/soc/amd/include/acp_2_2_d.h new file mode 100644 index 000000000..d07ec8646 --- /dev/null +++ b/sound/soc/amd/include/acp_2_2_d.h @@ -0,0 +1,593 @@ +/* SPDX-License-Identifier: MIT */ +/* + * ACP_2_2 Register documentation + * + * Copyright (C) 2014 Advanced Micro Devices, Inc. + */ + +#ifndef ACP_2_2_D_H +#define ACP_2_2_D_H + +#define mmACP_DMA_CNTL_0 0x5000 +#define mmACP_DMA_CNTL_1 0x5001 +#define mmACP_DMA_CNTL_2 0x5002 +#define mmACP_DMA_CNTL_3 0x5003 +#define mmACP_DMA_CNTL_4 0x5004 +#define mmACP_DMA_CNTL_5 0x5005 +#define mmACP_DMA_CNTL_6 0x5006 +#define mmACP_DMA_CNTL_7 0x5007 +#define mmACP_DMA_CNTL_8 0x5008 +#define mmACP_DMA_CNTL_9 0x5009 +#define mmACP_DMA_CNTL_10 0x500a +#define mmACP_DMA_CNTL_11 0x500b +#define mmACP_DMA_CNTL_12 0x500c +#define mmACP_DMA_CNTL_13 0x500d +#define mmACP_DMA_CNTL_14 0x500e +#define mmACP_DMA_CNTL_15 0x500f +#define mmACP_DMA_DSCR_STRT_IDX_0 0x5010 +#define mmACP_DMA_DSCR_STRT_IDX_1 0x5011 +#define mmACP_DMA_DSCR_STRT_IDX_2 0x5012 +#define mmACP_DMA_DSCR_STRT_IDX_3 0x5013 +#define mmACP_DMA_DSCR_STRT_IDX_4 0x5014 +#define mmACP_DMA_DSCR_STRT_IDX_5 0x5015 +#define mmACP_DMA_DSCR_STRT_IDX_6 0x5016 +#define mmACP_DMA_DSCR_STRT_IDX_7 0x5017 +#define mmACP_DMA_DSCR_STRT_IDX_8 0x5018 +#define mmACP_DMA_DSCR_STRT_IDX_9 0x5019 +#define mmACP_DMA_DSCR_STRT_IDX_10 0x501a +#define mmACP_DMA_DSCR_STRT_IDX_11 0x501b +#define mmACP_DMA_DSCR_STRT_IDX_12 0x501c +#define mmACP_DMA_DSCR_STRT_IDX_13 0x501d +#define mmACP_DMA_DSCR_STRT_IDX_14 0x501e +#define mmACP_DMA_DSCR_STRT_IDX_15 0x501f +#define mmACP_DMA_DSCR_CNT_0 0x5020 +#define mmACP_DMA_DSCR_CNT_1 0x5021 +#define mmACP_DMA_DSCR_CNT_2 0x5022 +#define mmACP_DMA_DSCR_CNT_3 0x5023 +#define mmACP_DMA_DSCR_CNT_4 0x5024 +#define mmACP_DMA_DSCR_CNT_5 0x5025 +#define mmACP_DMA_DSCR_CNT_6 0x5026 +#define mmACP_DMA_DSCR_CNT_7 0x5027 +#define mmACP_DMA_DSCR_CNT_8 0x5028 +#define mmACP_DMA_DSCR_CNT_9 0x5029 +#define mmACP_DMA_DSCR_CNT_10 0x502a +#define mmACP_DMA_DSCR_CNT_11 0x502b +#define mmACP_DMA_DSCR_CNT_12 0x502c +#define mmACP_DMA_DSCR_CNT_13 0x502d +#define mmACP_DMA_DSCR_CNT_14 0x502e +#define mmACP_DMA_DSCR_CNT_15 0x502f +#define mmACP_DMA_PRIO_0 0x5030 +#define mmACP_DMA_PRIO_1 0x5031 +#define mmACP_DMA_PRIO_2 0x5032 +#define mmACP_DMA_PRIO_3 0x5033 +#define mmACP_DMA_PRIO_4 0x5034 +#define mmACP_DMA_PRIO_5 0x5035 +#define mmACP_DMA_PRIO_6 0x5036 +#define mmACP_DMA_PRIO_7 0x5037 +#define mmACP_DMA_PRIO_8 0x5038 +#define mmACP_DMA_PRIO_9 0x5039 +#define mmACP_DMA_PRIO_10 0x503a +#define mmACP_DMA_PRIO_11 0x503b +#define mmACP_DMA_PRIO_12 0x503c +#define mmACP_DMA_PRIO_13 0x503d +#define mmACP_DMA_PRIO_14 0x503e +#define mmACP_DMA_PRIO_15 0x503f +#define mmACP_DMA_CUR_DSCR_0 0x5040 +#define mmACP_DMA_CUR_DSCR_1 0x5041 +#define mmACP_DMA_CUR_DSCR_2 0x5042 +#define mmACP_DMA_CUR_DSCR_3 0x5043 +#define mmACP_DMA_CUR_DSCR_4 0x5044 +#define mmACP_DMA_CUR_DSCR_5 0x5045 +#define mmACP_DMA_CUR_DSCR_6 0x5046 +#define mmACP_DMA_CUR_DSCR_7 0x5047 +#define mmACP_DMA_CUR_DSCR_8 0x5048 +#define mmACP_DMA_CUR_DSCR_9 0x5049 +#define mmACP_DMA_CUR_DSCR_10 0x504a +#define mmACP_DMA_CUR_DSCR_11 0x504b +#define mmACP_DMA_CUR_DSCR_12 0x504c +#define mmACP_DMA_CUR_DSCR_13 0x504d +#define mmACP_DMA_CUR_DSCR_14 0x504e +#define mmACP_DMA_CUR_DSCR_15 0x504f +#define mmACP_DMA_CUR_TRANS_CNT_0 0x5050 +#define mmACP_DMA_CUR_TRANS_CNT_1 0x5051 +#define mmACP_DMA_CUR_TRANS_CNT_2 0x5052 +#define mmACP_DMA_CUR_TRANS_CNT_3 0x5053 +#define mmACP_DMA_CUR_TRANS_CNT_4 0x5054 +#define mmACP_DMA_CUR_TRANS_CNT_5 0x5055 +#define mmACP_DMA_CUR_TRANS_CNT_6 0x5056 +#define mmACP_DMA_CUR_TRANS_CNT_7 0x5057 +#define mmACP_DMA_CUR_TRANS_CNT_8 0x5058 +#define mmACP_DMA_CUR_TRANS_CNT_9 0x5059 +#define mmACP_DMA_CUR_TRANS_CNT_10 0x505a +#define mmACP_DMA_CUR_TRANS_CNT_11 0x505b +#define mmACP_DMA_CUR_TRANS_CNT_12 0x505c +#define mmACP_DMA_CUR_TRANS_CNT_13 0x505d +#define mmACP_DMA_CUR_TRANS_CNT_14 0x505e +#define mmACP_DMA_CUR_TRANS_CNT_15 0x505f +#define mmACP_DMA_ERR_STS_0 0x5060 +#define mmACP_DMA_ERR_STS_1 0x5061 +#define mmACP_DMA_ERR_STS_2 0x5062 +#define mmACP_DMA_ERR_STS_3 0x5063 +#define mmACP_DMA_ERR_STS_4 0x5064 +#define mmACP_DMA_ERR_STS_5 0x5065 +#define mmACP_DMA_ERR_STS_6 0x5066 +#define mmACP_DMA_ERR_STS_7 0x5067 +#define mmACP_DMA_ERR_STS_8 0x5068 +#define mmACP_DMA_ERR_STS_9 0x5069 +#define mmACP_DMA_ERR_STS_10 0x506a +#define mmACP_DMA_ERR_STS_11 0x506b +#define mmACP_DMA_ERR_STS_12 0x506c +#define mmACP_DMA_ERR_STS_13 0x506d +#define mmACP_DMA_ERR_STS_14 0x506e +#define mmACP_DMA_ERR_STS_15 0x506f +#define mmACP_DMA_DESC_BASE_ADDR 0x5070 +#define mmACP_DMA_DESC_MAX_NUM_DSCR 0x5071 +#define mmACP_DMA_CH_STS 0x5072 +#define mmACP_DMA_CH_GROUP 0x5073 +#define mmACP_DSP0_CACHE_OFFSET0 0x5078 +#define mmACP_DSP0_CACHE_SIZE0 0x5079 +#define mmACP_DSP0_CACHE_OFFSET1 0x507a +#define mmACP_DSP0_CACHE_SIZE1 0x507b +#define mmACP_DSP0_CACHE_OFFSET2 0x507c +#define mmACP_DSP0_CACHE_SIZE2 0x507d +#define mmACP_DSP0_CACHE_OFFSET3 0x507e +#define mmACP_DSP0_CACHE_SIZE3 0x507f +#define mmACP_DSP0_CACHE_OFFSET4 0x5080 +#define mmACP_DSP0_CACHE_SIZE4 0x5081 +#define mmACP_DSP0_CACHE_OFFSET5 0x5082 +#define mmACP_DSP0_CACHE_SIZE5 0x5083 +#define mmACP_DSP0_CACHE_OFFSET6 0x5084 +#define mmACP_DSP0_CACHE_SIZE6 0x5085 +#define mmACP_DSP0_CACHE_OFFSET7 0x5086 +#define mmACP_DSP0_CACHE_SIZE7 0x5087 +#define mmACP_DSP0_CACHE_OFFSET8 0x5088 +#define mmACP_DSP0_CACHE_SIZE8 0x5089 +#define mmACP_DSP0_NONCACHE_OFFSET0 0x508a +#define mmACP_DSP0_NONCACHE_SIZE0 0x508b +#define mmACP_DSP0_NONCACHE_OFFSET1 0x508c +#define mmACP_DSP0_NONCACHE_SIZE1 0x508d +#define mmACP_DSP0_DEBUG_PC 0x508e +#define mmACP_DSP0_NMI_SEL 0x508f +#define mmACP_DSP0_CLKRST_CNTL 0x5090 +#define mmACP_DSP0_RUNSTALL 0x5091 +#define mmACP_DSP0_OCD_HALT_ON_RST 0x5092 +#define mmACP_DSP0_WAIT_MODE 0x5093 +#define mmACP_DSP0_VECT_SEL 0x5094 +#define mmACP_DSP0_DEBUG_REG1 0x5095 +#define mmACP_DSP0_DEBUG_REG2 0x5096 +#define mmACP_DSP0_DEBUG_REG3 0x5097 +#define mmACP_DSP1_CACHE_OFFSET0 0x509d +#define mmACP_DSP1_CACHE_SIZE0 0x509e +#define mmACP_DSP1_CACHE_OFFSET1 0x509f +#define mmACP_DSP1_CACHE_SIZE1 0x50a0 +#define mmACP_DSP1_CACHE_OFFSET2 0x50a1 +#define mmACP_DSP1_CACHE_SIZE2 0x50a2 +#define mmACP_DSP1_CACHE_OFFSET3 0x50a3 +#define mmACP_DSP1_CACHE_SIZE3 0x50a4 +#define mmACP_DSP1_CACHE_OFFSET4 0x50a5 +#define mmACP_DSP1_CACHE_SIZE4 0x50a6 +#define mmACP_DSP1_CACHE_OFFSET5 0x50a7 +#define mmACP_DSP1_CACHE_SIZE5 0x50a8 +#define mmACP_DSP1_CACHE_OFFSET6 0x50a9 +#define mmACP_DSP1_CACHE_SIZE6 0x50aa +#define mmACP_DSP1_CACHE_OFFSET7 0x50ab +#define mmACP_DSP1_CACHE_SIZE7 0x50ac +#define mmACP_DSP1_CACHE_OFFSET8 0x50ad +#define mmACP_DSP1_CACHE_SIZE8 0x50ae +#define mmACP_DSP1_NONCACHE_OFFSET0 0x50af +#define mmACP_DSP1_NONCACHE_SIZE0 0x50b0 +#define mmACP_DSP1_NONCACHE_OFFSET1 0x50b1 +#define mmACP_DSP1_NONCACHE_SIZE1 0x50b2 +#define mmACP_DSP1_DEBUG_PC 0x50b3 +#define mmACP_DSP1_NMI_SEL 0x50b4 +#define mmACP_DSP1_CLKRST_CNTL 0x50b5 +#define mmACP_DSP1_RUNSTALL 0x50b6 +#define mmACP_DSP1_OCD_HALT_ON_RST 0x50b7 +#define mmACP_DSP1_WAIT_MODE 0x50b8 +#define mmACP_DSP1_VECT_SEL 0x50b9 +#define mmACP_DSP1_DEBUG_REG1 0x50ba +#define mmACP_DSP1_DEBUG_REG2 0x50bb +#define mmACP_DSP1_DEBUG_REG3 0x50bc +#define mmACP_DSP2_CACHE_OFFSET0 0x50c2 +#define mmACP_DSP2_CACHE_SIZE0 0x50c3 +#define mmACP_DSP2_CACHE_OFFSET1 0x50c4 +#define mmACP_DSP2_CACHE_SIZE1 0x50c5 +#define mmACP_DSP2_CACHE_OFFSET2 0x50c6 +#define mmACP_DSP2_CACHE_SIZE2 0x50c7 +#define mmACP_DSP2_CACHE_OFFSET3 0x50c8 +#define mmACP_DSP2_CACHE_SIZE3 0x50c9 +#define mmACP_DSP2_CACHE_OFFSET4 0x50ca +#define mmACP_DSP2_CACHE_SIZE4 0x50cb +#define mmACP_DSP2_CACHE_OFFSET5 0x50cc +#define mmACP_DSP2_CACHE_SIZE5 0x50cd +#define mmACP_DSP2_CACHE_OFFSET6 0x50ce +#define mmACP_DSP2_CACHE_SIZE6 0x50cf +#define mmACP_DSP2_CACHE_OFFSET7 0x50d0 +#define mmACP_DSP2_CACHE_SIZE7 0x50d1 +#define mmACP_DSP2_CACHE_OFFSET8 0x50d2 +#define mmACP_DSP2_CACHE_SIZE8 0x50d3 +#define mmACP_DSP2_NONCACHE_OFFSET0 0x50d4 +#define mmACP_DSP2_NONCACHE_SIZE0 0x50d5 +#define mmACP_DSP2_NONCACHE_OFFSET1 0x50d6 +#define mmACP_DSP2_NONCACHE_SIZE1 0x50d7 +#define mmACP_DSP2_DEBUG_PC 0x50d8 +#define mmACP_DSP2_NMI_SEL 0x50d9 +#define mmACP_DSP2_CLKRST_CNTL 0x50da +#define mmACP_DSP2_RUNSTALL 0x50db +#define mmACP_DSP2_OCD_HALT_ON_RST 0x50dc +#define mmACP_DSP2_WAIT_MODE 0x50dd +#define mmACP_DSP2_VECT_SEL 0x50de +#define mmACP_DSP2_DEBUG_REG1 0x50df +#define mmACP_DSP2_DEBUG_REG2 0x50e0 +#define mmACP_DSP2_DEBUG_REG3 0x50e1 +#define mmACP_AXI2DAGB_ONION_CNTL 0x50e7 +#define mmACP_AXI2DAGB_ONION_ERR_STATUS_WR 0x50e8 +#define mmACP_AXI2DAGB_ONION_ERR_STATUS_RD 0x50e9 +#define mmACP_DAGB_Onion_TransPerf_Counter_Control 0x50ea +#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Current 0x50eb +#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Peak 0x50ec +#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Current 0x50ed +#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Peak 0x50ee +#define mmACP_AXI2DAGB_GARLIC_CNTL 0x50f3 +#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_WR 0x50f4 +#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_RD 0x50f5 +#define mmACP_DAGB_Garlic_TransPerf_Counter_Control 0x50f6 +#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Current 0x50f7 +#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak 0x50f8 +#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Current 0x50f9 +#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak 0x50fa +#define mmACP_DAGB_PAGE_SIZE_GRP_1 0x50ff +#define mmACP_DAGB_BASE_ADDR_GRP_1 0x5100 +#define mmACP_DAGB_PAGE_SIZE_GRP_2 0x5101 +#define mmACP_DAGB_BASE_ADDR_GRP_2 0x5102 +#define mmACP_DAGB_PAGE_SIZE_GRP_3 0x5103 +#define mmACP_DAGB_BASE_ADDR_GRP_3 0x5104 +#define mmACP_DAGB_PAGE_SIZE_GRP_4 0x5105 +#define mmACP_DAGB_BASE_ADDR_GRP_4 0x5106 +#define mmACP_DAGB_PAGE_SIZE_GRP_5 0x5107 +#define mmACP_DAGB_BASE_ADDR_GRP_5 0x5108 +#define mmACP_DAGB_PAGE_SIZE_GRP_6 0x5109 +#define mmACP_DAGB_BASE_ADDR_GRP_6 0x510a +#define mmACP_DAGB_PAGE_SIZE_GRP_7 0x510b +#define mmACP_DAGB_BASE_ADDR_GRP_7 0x510c +#define mmACP_DAGB_PAGE_SIZE_GRP_8 0x510d +#define mmACP_DAGB_BASE_ADDR_GRP_8 0x510e +#define mmACP_DAGB_ATU_CTRL 0x510f +#define mmACP_CONTROL 0x5131 +#define mmACP_STATUS 0x5133 +#define mmACP_SOFT_RESET 0x5134 +#define mmACP_PwrMgmt_CNTL 0x5135 +#define mmACP_CAC_INDICATOR_CONTROL 0x5136 +#define mmACP_SMU_MAILBOX 0x5137 +#define mmACP_FUTURE_REG_SCLK_0 0x5138 +#define mmACP_FUTURE_REG_SCLK_1 0x5139 +#define mmACP_FUTURE_REG_SCLK_2 0x513a +#define mmACP_FUTURE_REG_SCLK_3 0x513b +#define mmACP_FUTURE_REG_SCLK_4 0x513c +#define mmACP_DAGB_DEBUG_CNT_ENABLE 0x513d +#define mmACP_DAGBG_WR_ASK_CNT 0x513e +#define mmACP_DAGBG_WR_GO_CNT 0x513f +#define mmACP_DAGBG_WR_EXP_RESP_CNT 0x5140 +#define mmACP_DAGBG_WR_ACTUAL_RESP_CNT 0x5141 +#define mmACP_DAGBG_RD_ASK_CNT 0x5142 +#define mmACP_DAGBG_RD_GO_CNT 0x5143 +#define mmACP_DAGBG_RD_EXP_RESP_CNT 0x5144 +#define mmACP_DAGBG_RD_ACTUAL_RESP_CNT 0x5145 +#define mmACP_DAGBO_WR_ASK_CNT 0x5146 +#define mmACP_DAGBO_WR_GO_CNT 0x5147 +#define mmACP_DAGBO_WR_EXP_RESP_CNT 0x5148 +#define mmACP_DAGBO_WR_ACTUAL_RESP_CNT 0x5149 +#define mmACP_DAGBO_RD_ASK_CNT 0x514a +#define mmACP_DAGBO_RD_GO_CNT 0x514b +#define mmACP_DAGBO_RD_EXP_RESP_CNT 0x514c +#define mmACP_DAGBO_RD_ACTUAL_RESP_CNT 0x514d +#define mmACP_BRB_CONTROL 0x5156 +#define mmACP_EXTERNAL_INTR_ENB 0x5157 +#define mmACP_EXTERNAL_INTR_CNTL 0x5158 +#define mmACP_ERROR_SOURCE_STS 0x5159 +#define mmACP_DSP_SW_INTR_TRIG 0x515a +#define mmACP_DSP_SW_INTR_CNTL 0x515b +#define mmACP_DAGBG_TIMEOUT_CNTL 0x515c +#define mmACP_DAGBO_TIMEOUT_CNTL 0x515d +#define mmACP_EXTERNAL_INTR_STAT 0x515e +#define mmACP_DSP_SW_INTR_STAT 0x515f +#define mmACP_DSP0_INTR_CNTL 0x5160 +#define mmACP_DSP0_INTR_STAT 0x5161 +#define mmACP_DSP0_TIMEOUT_CNTL 0x5162 +#define mmACP_DSP1_INTR_CNTL 0x5163 +#define mmACP_DSP1_INTR_STAT 0x5164 +#define mmACP_DSP1_TIMEOUT_CNTL 0x5165 +#define mmACP_DSP2_INTR_CNTL 0x5166 +#define mmACP_DSP2_INTR_STAT 0x5167 +#define mmACP_DSP2_TIMEOUT_CNTL 0x5168 +#define mmACP_DSP0_EXT_TIMER_CNTL 0x5169 +#define mmACP_DSP1_EXT_TIMER_CNTL 0x516a +#define mmACP_DSP2_EXT_TIMER_CNTL 0x516b +#define mmACP_AXI2DAGB_SEM_0 0x516c +#define mmACP_AXI2DAGB_SEM_1 0x516d +#define mmACP_AXI2DAGB_SEM_2 0x516e +#define mmACP_AXI2DAGB_SEM_3 0x516f +#define mmACP_AXI2DAGB_SEM_4 0x5170 +#define mmACP_AXI2DAGB_SEM_5 0x5171 +#define mmACP_AXI2DAGB_SEM_6 0x5172 +#define mmACP_AXI2DAGB_SEM_7 0x5173 +#define mmACP_AXI2DAGB_SEM_8 0x5174 +#define mmACP_AXI2DAGB_SEM_9 0x5175 +#define mmACP_AXI2DAGB_SEM_10 0x5176 +#define mmACP_AXI2DAGB_SEM_11 0x5177 +#define mmACP_AXI2DAGB_SEM_12 0x5178 +#define mmACP_AXI2DAGB_SEM_13 0x5179 +#define mmACP_AXI2DAGB_SEM_14 0x517a +#define mmACP_AXI2DAGB_SEM_15 0x517b +#define mmACP_AXI2DAGB_SEM_16 0x517c +#define mmACP_AXI2DAGB_SEM_17 0x517d +#define mmACP_AXI2DAGB_SEM_18 0x517e +#define mmACP_AXI2DAGB_SEM_19 0x517f +#define mmACP_AXI2DAGB_SEM_20 0x5180 +#define mmACP_AXI2DAGB_SEM_21 0x5181 +#define mmACP_AXI2DAGB_SEM_22 0x5182 +#define mmACP_AXI2DAGB_SEM_23 0x5183 +#define mmACP_AXI2DAGB_SEM_24 0x5184 +#define mmACP_AXI2DAGB_SEM_25 0x5185 +#define mmACP_AXI2DAGB_SEM_26 0x5186 +#define mmACP_AXI2DAGB_SEM_27 0x5187 +#define mmACP_AXI2DAGB_SEM_28 0x5188 +#define mmACP_AXI2DAGB_SEM_29 0x5189 +#define mmACP_AXI2DAGB_SEM_30 0x518a +#define mmACP_AXI2DAGB_SEM_31 0x518b +#define mmACP_AXI2DAGB_SEM_32 0x518c +#define mmACP_AXI2DAGB_SEM_33 0x518d +#define mmACP_AXI2DAGB_SEM_34 0x518e +#define mmACP_AXI2DAGB_SEM_35 0x518f +#define mmACP_AXI2DAGB_SEM_36 0x5190 +#define mmACP_AXI2DAGB_SEM_37 0x5191 +#define mmACP_AXI2DAGB_SEM_38 0x5192 +#define mmACP_AXI2DAGB_SEM_39 0x5193 +#define mmACP_AXI2DAGB_SEM_40 0x5194 +#define mmACP_AXI2DAGB_SEM_41 0x5195 +#define mmACP_AXI2DAGB_SEM_42 0x5196 +#define mmACP_AXI2DAGB_SEM_43 0x5197 +#define mmACP_AXI2DAGB_SEM_44 0x5198 +#define mmACP_AXI2DAGB_SEM_45 0x5199 +#define mmACP_AXI2DAGB_SEM_46 0x519a +#define mmACP_AXI2DAGB_SEM_47 0x519b +#define mmACP_SRBM_Client_Base_Addr 0x519c +#define mmACP_SRBM_Client_RDDATA 0x519d +#define mmACP_SRBM_Cycle_Sts 0x519e +#define mmACP_SRBM_Targ_Idx_Addr 0x519f +#define mmACP_SRBM_Targ_Idx_Data 0x51a0 +#define mmACP_SEMA_ADDR_LOW 0x51a1 +#define mmACP_SEMA_ADDR_HIGH 0x51a2 +#define mmACP_SEMA_CMD 0x51a3 +#define mmACP_SEMA_STS 0x51a4 +#define mmACP_SEMA_REQ 0x51a5 +#define mmACP_FW_STATUS 0x51a6 +#define mmACP_FUTURE_REG_ACLK_0 0x51a7 +#define mmACP_FUTURE_REG_ACLK_1 0x51a8 +#define mmACP_FUTURE_REG_ACLK_2 0x51a9 +#define mmACP_FUTURE_REG_ACLK_3 0x51aa +#define mmACP_FUTURE_REG_ACLK_4 0x51ab +#define mmACP_TIMER 0x51ac +#define mmACP_TIMER_CNTL 0x51ad +#define mmACP_DSP0_TIMER 0x51ae +#define mmACP_DSP1_TIMER 0x51af +#define mmACP_DSP2_TIMER 0x51b0 +#define mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH 0x51b1 +#define mmACP_I2S_TRANSMIT_BYTE_CNT_LOW 0x51b2 +#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH 0x51b3 +#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW 0x51b4 +#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH 0x51b5 +#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW 0x51b6 +#define mmACP_DSP0_CS_STATE 0x51b7 +#define mmACP_DSP1_CS_STATE 0x51b8 +#define mmACP_DSP2_CS_STATE 0x51b9 +#define mmACP_SCRATCH_REG_BASE_ADDR 0x51ba +#define mmCC_ACP_EFUSE 0x51c8 +#define mmACP_PGFSM_RETAIN_REG 0x51c9 +#define mmACP_PGFSM_CONFIG_REG 0x51ca +#define mmACP_PGFSM_WRITE_REG 0x51cb +#define mmACP_PGFSM_READ_REG_0 0x51cc +#define mmACP_PGFSM_READ_REG_1 0x51cd +#define mmACP_PGFSM_READ_REG_2 0x51ce +#define mmACP_PGFSM_READ_REG_3 0x51cf +#define mmACP_PGFSM_READ_REG_4 0x51d0 +#define mmACP_PGFSM_READ_REG_5 0x51d1 +#define mmACP_IP_PGFSM_ENABLE 0x51d2 +#define mmACP_I2S_PIN_CONFIG 0x51d3 +#define mmACP_AZALIA_I2S_SELECT 0x51d4 +#define mmACP_CHIP_PKG_FOR_PAD_ISOLATION 0x51d5 +#define mmACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL 0x51d6 +#define mmACP_BT_UART_PAD_SEL 0x51d7 +#define mmACP_SCRATCH_REG_0 0x52c0 +#define mmACP_SCRATCH_REG_1 0x52c1 +#define mmACP_SCRATCH_REG_2 0x52c2 +#define mmACP_SCRATCH_REG_3 0x52c3 +#define mmACP_SCRATCH_REG_4 0x52c4 +#define mmACP_SCRATCH_REG_5 0x52c5 +#define mmACP_SCRATCH_REG_6 0x52c6 +#define mmACP_SCRATCH_REG_7 0x52c7 +#define mmACP_SCRATCH_REG_8 0x52c8 +#define mmACP_SCRATCH_REG_9 0x52c9 +#define mmACP_SCRATCH_REG_10 0x52ca +#define mmACP_SCRATCH_REG_11 0x52cb +#define mmACP_SCRATCH_REG_12 0x52cc +#define mmACP_SCRATCH_REG_13 0x52cd +#define mmACP_SCRATCH_REG_14 0x52ce +#define mmACP_SCRATCH_REG_15 0x52cf +#define mmACP_SCRATCH_REG_16 0x52d0 +#define mmACP_SCRATCH_REG_17 0x52d1 +#define mmACP_SCRATCH_REG_18 0x52d2 +#define mmACP_SCRATCH_REG_19 0x52d3 +#define mmACP_SCRATCH_REG_20 0x52d4 +#define mmACP_SCRATCH_REG_21 0x52d5 +#define mmACP_SCRATCH_REG_22 0x52d6 +#define mmACP_SCRATCH_REG_23 0x52d7 +#define mmACP_SCRATCH_REG_24 0x52d8 +#define mmACP_SCRATCH_REG_25 0x52d9 +#define mmACP_SCRATCH_REG_26 0x52da +#define mmACP_SCRATCH_REG_27 0x52db +#define mmACP_SCRATCH_REG_28 0x52dc +#define mmACP_SCRATCH_REG_29 0x52dd +#define mmACP_SCRATCH_REG_30 0x52de +#define mmACP_SCRATCH_REG_31 0x52df +#define mmACP_SCRATCH_REG_32 0x52e0 +#define mmACP_SCRATCH_REG_33 0x52e1 +#define mmACP_SCRATCH_REG_34 0x52e2 +#define mmACP_SCRATCH_REG_35 0x52e3 +#define mmACP_SCRATCH_REG_36 0x52e4 +#define mmACP_SCRATCH_REG_37 0x52e5 +#define mmACP_SCRATCH_REG_38 0x52e6 +#define mmACP_SCRATCH_REG_39 0x52e7 +#define mmACP_SCRATCH_REG_40 0x52e8 +#define mmACP_SCRATCH_REG_41 0x52e9 +#define mmACP_SCRATCH_REG_42 0x52ea +#define mmACP_SCRATCH_REG_43 0x52eb +#define mmACP_SCRATCH_REG_44 0x52ec +#define mmACP_SCRATCH_REG_45 0x52ed +#define mmACP_SCRATCH_REG_46 0x52ee +#define mmACP_SCRATCH_REG_47 0x52ef +#define mmACP_VOICE_WAKEUP_ENABLE 0x51e8 +#define mmACP_VOICE_WAKEUP_STATUS 0x51e9 +#define mmI2S_VOICE_WAKEUP_LOWER_THRESHOLD 0x51ea +#define mmI2S_VOICE_WAKEUP_HIGHER_THRESHOLD 0x51eb +#define mmI2S_VOICE_WAKEUP_NO_OF_SAMPLES 0x51ec +#define mmI2S_VOICE_WAKEUP_NO_OF_PEAKS 0x51ed +#define mmI2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS 0x51ee +#define mmI2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION 0x51ef +#define mmI2S_VOICE_WAKEUP_DATA_PATH_SWITCH 0x51f0 +#define mmI2S_VOICE_WAKEUP_DATA_POINTER 0x51f1 +#define mmI2S_VOICE_WAKEUP_AUTH_MATCH 0x51f2 +#define mmI2S_VOICE_WAKEUP_8KB_WRAP 0x51f3 +#define mmACP_I2S_RECEIVED_BYTE_CNT_HIGH 0x51f4 +#define mmACP_I2S_RECEIVED_BYTE_CNT_LOW 0x51f5 +#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH 0x51f6 +#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW 0x51f7 +#define mmACP_MEM_SHUT_DOWN_REQ_LO 0x51f8 +#define mmACP_MEM_SHUT_DOWN_REQ_HI 0x51f9 +#define mmACP_MEM_SHUT_DOWN_STS_LO 0x51fa +#define mmACP_MEM_SHUT_DOWN_STS_HI 0x51fb +#define mmACP_MEM_DEEP_SLEEP_REQ_LO 0x51fc +#define mmACP_MEM_DEEP_SLEEP_REQ_HI 0x51fd +#define mmACP_MEM_DEEP_SLEEP_STS_LO 0x51fe +#define mmACP_MEM_DEEP_SLEEP_STS_HI 0x51ff +#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO 0x5200 +#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI 0x5201 +#define mmACP_MEM_WAKEUP_FROM_SLEEP_LO 0x5202 +#define mmACP_MEM_WAKEUP_FROM_SLEEP_HI 0x5203 +#define mmACP_I2SSP_IER 0x5210 +#define mmACP_I2SSP_IRER 0x5211 +#define mmACP_I2SSP_ITER 0x5212 +#define mmACP_I2SSP_CER 0x5213 +#define mmACP_I2SSP_CCR 0x5214 +#define mmACP_I2SSP_RXFFR 0x5215 +#define mmACP_I2SSP_TXFFR 0x5216 +#define mmACP_I2SSP_LRBR0 0x5218 +#define mmACP_I2SSP_RRBR0 0x5219 +#define mmACP_I2SSP_RER0 0x521a +#define mmACP_I2SSP_TER0 0x521b +#define mmACP_I2SSP_RCR0 0x521c +#define mmACP_I2SSP_TCR0 0x521d +#define mmACP_I2SSP_ISR0 0x521e +#define mmACP_I2SSP_IMR0 0x521f +#define mmACP_I2SSP_ROR0 0x5220 +#define mmACP_I2SSP_TOR0 0x5221 +#define mmACP_I2SSP_RFCR0 0x5222 +#define mmACP_I2SSP_TFCR0 0x5223 +#define mmACP_I2SSP_RFF0 0x5224 +#define mmACP_I2SSP_TFF0 0x5225 +#define mmACP_I2SSP_RXDMA 0x5226 +#define mmACP_I2SSP_RRXDMA 0x5227 +#define mmACP_I2SSP_TXDMA 0x5228 +#define mmACP_I2SSP_RTXDMA 0x5229 +#define mmACP_I2SSP_COMP_PARAM_2 0x522a +#define mmACP_I2SSP_COMP_PARAM_1 0x522b +#define mmACP_I2SSP_COMP_VERSION 0x522c +#define mmACP_I2SSP_COMP_TYPE 0x522d +#define mmACP_I2SMICSP_IER 0x522e +#define mmACP_I2SMICSP_IRER 0x522f +#define mmACP_I2SMICSP_ITER 0x5230 +#define mmACP_I2SMICSP_CER 0x5231 +#define mmACP_I2SMICSP_CCR 0x5232 +#define mmACP_I2SMICSP_RXFFR 0x5233 +#define mmACP_I2SMICSP_TXFFR 0x5234 +#define mmACP_I2SMICSP_LRBR0 0x5236 +#define mmACP_I2SMICSP_RRBR0 0x5237 +#define mmACP_I2SMICSP_RER0 0x5238 +#define mmACP_I2SMICSP_TER0 0x5239 +#define mmACP_I2SMICSP_RCR0 0x523a +#define mmACP_I2SMICSP_TCR0 0x523b +#define mmACP_I2SMICSP_ISR0 0x523c +#define mmACP_I2SMICSP_IMR0 0x523d +#define mmACP_I2SMICSP_ROR0 0x523e +#define mmACP_I2SMICSP_TOR0 0x523f +#define mmACP_I2SMICSP_RFCR0 0x5240 +#define mmACP_I2SMICSP_TFCR0 0x5241 +#define mmACP_I2SMICSP_RFF0 0x5242 +#define mmACP_I2SMICSP_TFF0 0x5243 +#define mmACP_I2SMICSP_LRBR1 0x5246 +#define mmACP_I2SMICSP_RRBR1 0x5247 +#define mmACP_I2SMICSP_RER1 0x5248 +#define mmACP_I2SMICSP_TER1 0x5249 +#define mmACP_I2SMICSP_RCR1 0x524a +#define mmACP_I2SMICSP_TCR1 0x524b +#define mmACP_I2SMICSP_ISR1 0x524c +#define mmACP_I2SMICSP_IMR1 0x524d +#define mmACP_I2SMICSP_ROR1 0x524e +#define mmACP_I2SMICSP_TOR1 0x524f +#define mmACP_I2SMICSP_RFCR1 0x5250 +#define mmACP_I2SMICSP_TFCR1 0x5251 +#define mmACP_I2SMICSP_RFF1 0x5252 +#define mmACP_I2SMICSP_TFF1 0x5253 +#define mmACP_I2SMICSP_RXDMA 0x5254 +#define mmACP_I2SMICSP_RRXDMA 0x5255 +#define mmACP_I2SMICSP_TXDMA 0x5256 +#define mmACP_I2SMICSP_RTXDMA 0x5257 +#define mmACP_I2SMICSP_COMP_PARAM_2 0x5258 +#define mmACP_I2SMICSP_COMP_PARAM_1 0x5259 +#define mmACP_I2SMICSP_COMP_VERSION 0x525a +#define mmACP_I2SMICSP_COMP_TYPE 0x525b +#define mmACP_I2SBT_IER 0x525c +#define mmACP_I2SBT_IRER 0x525d +#define mmACP_I2SBT_ITER 0x525e +#define mmACP_I2SBT_CER 0x525f +#define mmACP_I2SBT_CCR 0x5260 +#define mmACP_I2SBT_RXFFR 0x5261 +#define mmACP_I2SBT_TXFFR 0x5262 +#define mmACP_I2SBT_LRBR0 0x5264 +#define mmACP_I2SBT_RRBR0 0x5265 +#define mmACP_I2SBT_RER0 0x5266 +#define mmACP_I2SBT_TER0 0x5267 +#define mmACP_I2SBT_RCR0 0x5268 +#define mmACP_I2SBT_TCR0 0x5269 +#define mmACP_I2SBT_ISR0 0x526a +#define mmACP_I2SBT_IMR0 0x526b +#define mmACP_I2SBT_ROR0 0x526c +#define mmACP_I2SBT_TOR0 0x526d +#define mmACP_I2SBT_RFCR0 0x526e +#define mmACP_I2SBT_TFCR0 0x526f +#define mmACP_I2SBT_RFF0 0x5270 +#define mmACP_I2SBT_TFF0 0x5271 +#define mmACP_I2SBT_LRBR1 0x5274 +#define mmACP_I2SBT_RRBR1 0x5275 +#define mmACP_I2SBT_RER1 0x5276 +#define mmACP_I2SBT_TER1 0x5277 +#define mmACP_I2SBT_RCR1 0x5278 +#define mmACP_I2SBT_TCR1 0x5279 +#define mmACP_I2SBT_ISR1 0x527a +#define mmACP_I2SBT_IMR1 0x527b +#define mmACP_I2SBT_ROR1 0x527c +#define mmACP_I2SBT_TOR1 0x527d +#define mmACP_I2SBT_RFCR1 0x527e +#define mmACP_I2SBT_TFCR1 0x527f +#define mmACP_I2SBT_RFF1 0x5280 +#define mmACP_I2SBT_TFF1 0x5281 +#define mmACP_I2SBT_RXDMA 0x5282 +#define mmACP_I2SBT_RRXDMA 0x5283 +#define mmACP_I2SBT_TXDMA 0x5284 +#define mmACP_I2SBT_RTXDMA 0x5285 +#define mmACP_I2SBT_COMP_PARAM_2 0x5286 +#define mmACP_I2SBT_COMP_PARAM_1 0x5287 +#define mmACP_I2SBT_COMP_VERSION 0x5288 +#define mmACP_I2SBT_COMP_TYPE 0x5289 + +#endif /* ACP_2_2_D_H */ diff --git a/sound/soc/amd/include/acp_2_2_enum.h b/sound/soc/amd/include/acp_2_2_enum.h new file mode 100644 index 000000000..26c7993ac --- /dev/null +++ b/sound/soc/amd/include/acp_2_2_enum.h @@ -0,0 +1,1052 @@ +/* SPDX-License-Identifier: MIT */ +/* + * ACP_2_2 Register documentation + * + * Copyright (C) 2014 Advanced Micro Devices, Inc. + */ + +#ifndef ACP_2_2_ENUM_H +#define ACP_2_2_ENUM_H + +typedef enum DebugBlockId { + DBG_BLOCK_ID_RESERVED = 0x0, + DBG_BLOCK_ID_DBG = 0x1, + DBG_BLOCK_ID_VMC = 0x2, + DBG_BLOCK_ID_PDMA = 0x3, + DBG_BLOCK_ID_CG = 0x4, + DBG_BLOCK_ID_SRBM = 0x5, + DBG_BLOCK_ID_GRBM = 0x6, + DBG_BLOCK_ID_RLC = 0x7, + DBG_BLOCK_ID_CSC = 0x8, + DBG_BLOCK_ID_SEM = 0x9, + DBG_BLOCK_ID_IH = 0xa, + DBG_BLOCK_ID_SC = 0xb, + DBG_BLOCK_ID_SQ = 0xc, + DBG_BLOCK_ID_UVDU = 0xd, + DBG_BLOCK_ID_SQA = 0xe, + DBG_BLOCK_ID_SDMA0 = 0xf, + DBG_BLOCK_ID_SDMA1 = 0x10, + DBG_BLOCK_ID_SPIM = 0x11, + DBG_BLOCK_ID_GDS = 0x12, + DBG_BLOCK_ID_VC0 = 0x13, + DBG_BLOCK_ID_VC1 = 0x14, + DBG_BLOCK_ID_PA0 = 0x15, + DBG_BLOCK_ID_PA1 = 0x16, + DBG_BLOCK_ID_CP0 = 0x17, + DBG_BLOCK_ID_CP1 = 0x18, + DBG_BLOCK_ID_CP2 = 0x19, + DBG_BLOCK_ID_XBR = 0x1a, + DBG_BLOCK_ID_UVDM = 0x1b, + DBG_BLOCK_ID_VGT0 = 0x1c, + DBG_BLOCK_ID_VGT1 = 0x1d, + DBG_BLOCK_ID_IA = 0x1e, + DBG_BLOCK_ID_SXM0 = 0x1f, + DBG_BLOCK_ID_SXM1 = 0x20, + DBG_BLOCK_ID_SCT0 = 0x21, + DBG_BLOCK_ID_SCT1 = 0x22, + DBG_BLOCK_ID_SPM0 = 0x23, + DBG_BLOCK_ID_SPM1 = 0x24, + DBG_BLOCK_ID_UNUSED0 = 0x25, + DBG_BLOCK_ID_UNUSED1 = 0x26, + DBG_BLOCK_ID_TCAA = 0x27, + DBG_BLOCK_ID_TCAB = 0x28, + DBG_BLOCK_ID_TCCA = 0x29, + DBG_BLOCK_ID_TCCB = 0x2a, + DBG_BLOCK_ID_MCC0 = 0x2b, + DBG_BLOCK_ID_MCC1 = 0x2c, + DBG_BLOCK_ID_MCC2 = 0x2d, + DBG_BLOCK_ID_MCC3 = 0x2e, + DBG_BLOCK_ID_SXS0 = 0x2f, + DBG_BLOCK_ID_SXS1 = 0x30, + DBG_BLOCK_ID_SXS2 = 0x31, + DBG_BLOCK_ID_SXS3 = 0x32, + DBG_BLOCK_ID_SXS4 = 0x33, + DBG_BLOCK_ID_SXS5 = 0x34, + DBG_BLOCK_ID_SXS6 = 0x35, + DBG_BLOCK_ID_SXS7 = 0x36, + DBG_BLOCK_ID_SXS8 = 0x37, + DBG_BLOCK_ID_SXS9 = 0x38, + DBG_BLOCK_ID_BCI0 = 0x39, + DBG_BLOCK_ID_BCI1 = 0x3a, + DBG_BLOCK_ID_BCI2 = 0x3b, + DBG_BLOCK_ID_BCI3 = 0x3c, + DBG_BLOCK_ID_MCB = 0x3d, + DBG_BLOCK_ID_UNUSED6 = 0x3e, + DBG_BLOCK_ID_SQA00 = 0x3f, + DBG_BLOCK_ID_SQA01 = 0x40, + DBG_BLOCK_ID_SQA02 = 0x41, + DBG_BLOCK_ID_SQA10 = 0x42, + DBG_BLOCK_ID_SQA11 = 0x43, + DBG_BLOCK_ID_SQA12 = 0x44, + DBG_BLOCK_ID_UNUSED7 = 0x45, + DBG_BLOCK_ID_UNUSED8 = 0x46, + DBG_BLOCK_ID_SQB00 = 0x47, + DBG_BLOCK_ID_SQB01 = 0x48, + DBG_BLOCK_ID_SQB10 = 0x49, + DBG_BLOCK_ID_SQB11 = 0x4a, + DBG_BLOCK_ID_SQ00 = 0x4b, + DBG_BLOCK_ID_SQ01 = 0x4c, + DBG_BLOCK_ID_SQ10 = 0x4d, + DBG_BLOCK_ID_SQ11 = 0x4e, + DBG_BLOCK_ID_CB00 = 0x4f, + DBG_BLOCK_ID_CB01 = 0x50, + DBG_BLOCK_ID_CB02 = 0x51, + DBG_BLOCK_ID_CB03 = 0x52, + DBG_BLOCK_ID_CB04 = 0x53, + DBG_BLOCK_ID_UNUSED9 = 0x54, + DBG_BLOCK_ID_UNUSED10 = 0x55, + DBG_BLOCK_ID_UNUSED11 = 0x56, + DBG_BLOCK_ID_CB10 = 0x57, + DBG_BLOCK_ID_CB11 = 0x58, + DBG_BLOCK_ID_CB12 = 0x59, + DBG_BLOCK_ID_CB13 = 0x5a, + DBG_BLOCK_ID_CB14 = 0x5b, + DBG_BLOCK_ID_UNUSED12 = 0x5c, + DBG_BLOCK_ID_UNUSED13 = 0x5d, + DBG_BLOCK_ID_UNUSED14 = 0x5e, + DBG_BLOCK_ID_TCP0 = 0x5f, + DBG_BLOCK_ID_TCP1 = 0x60, + DBG_BLOCK_ID_TCP2 = 0x61, + DBG_BLOCK_ID_TCP3 = 0x62, + DBG_BLOCK_ID_TCP4 = 0x63, + DBG_BLOCK_ID_TCP5 = 0x64, + DBG_BLOCK_ID_TCP6 = 0x65, + DBG_BLOCK_ID_TCP7 = 0x66, + DBG_BLOCK_ID_TCP8 = 0x67, + DBG_BLOCK_ID_TCP9 = 0x68, + DBG_BLOCK_ID_TCP10 = 0x69, + DBG_BLOCK_ID_TCP11 = 0x6a, + DBG_BLOCK_ID_TCP12 = 0x6b, + DBG_BLOCK_ID_TCP13 = 0x6c, + DBG_BLOCK_ID_TCP14 = 0x6d, + DBG_BLOCK_ID_TCP15 = 0x6e, + DBG_BLOCK_ID_TCP16 = 0x6f, + DBG_BLOCK_ID_TCP17 = 0x70, + DBG_BLOCK_ID_TCP18 = 0x71, + DBG_BLOCK_ID_TCP19 = 0x72, + DBG_BLOCK_ID_TCP20 = 0x73, + DBG_BLOCK_ID_TCP21 = 0x74, + DBG_BLOCK_ID_TCP22 = 0x75, + DBG_BLOCK_ID_TCP23 = 0x76, + DBG_BLOCK_ID_TCP_RESERVED0 = 0x77, + DBG_BLOCK_ID_TCP_RESERVED1 = 0x78, + DBG_BLOCK_ID_TCP_RESERVED2 = 0x79, + DBG_BLOCK_ID_TCP_RESERVED3 = 0x7a, + DBG_BLOCK_ID_TCP_RESERVED4 = 0x7b, + DBG_BLOCK_ID_TCP_RESERVED5 = 0x7c, + DBG_BLOCK_ID_TCP_RESERVED6 = 0x7d, + DBG_BLOCK_ID_TCP_RESERVED7 = 0x7e, + DBG_BLOCK_ID_DB00 = 0x7f, + DBG_BLOCK_ID_DB01 = 0x80, + DBG_BLOCK_ID_DB02 = 0x81, + DBG_BLOCK_ID_DB03 = 0x82, + DBG_BLOCK_ID_DB04 = 0x83, + DBG_BLOCK_ID_UNUSED15 = 0x84, + DBG_BLOCK_ID_UNUSED16 = 0x85, + DBG_BLOCK_ID_UNUSED17 = 0x86, + DBG_BLOCK_ID_DB10 = 0x87, + DBG_BLOCK_ID_DB11 = 0x88, + DBG_BLOCK_ID_DB12 = 0x89, + DBG_BLOCK_ID_DB13 = 0x8a, + DBG_BLOCK_ID_DB14 = 0x8b, + DBG_BLOCK_ID_UNUSED18 = 0x8c, + DBG_BLOCK_ID_UNUSED19 = 0x8d, + DBG_BLOCK_ID_UNUSED20 = 0x8e, + DBG_BLOCK_ID_TCC0 = 0x8f, + DBG_BLOCK_ID_TCC1 = 0x90, + DBG_BLOCK_ID_TCC2 = 0x91, + DBG_BLOCK_ID_TCC3 = 0x92, + DBG_BLOCK_ID_TCC4 = 0x93, + DBG_BLOCK_ID_TCC5 = 0x94, + DBG_BLOCK_ID_TCC6 = 0x95, + DBG_BLOCK_ID_TCC7 = 0x96, + DBG_BLOCK_ID_SPS00 = 0x97, + DBG_BLOCK_ID_SPS01 = 0x98, + DBG_BLOCK_ID_SPS02 = 0x99, + DBG_BLOCK_ID_SPS10 = 0x9a, + DBG_BLOCK_ID_SPS11 = 0x9b, + DBG_BLOCK_ID_SPS12 = 0x9c, + DBG_BLOCK_ID_UNUSED21 = 0x9d, + DBG_BLOCK_ID_UNUSED22 = 0x9e, + DBG_BLOCK_ID_TA00 = 0x9f, + DBG_BLOCK_ID_TA01 = 0xa0, + DBG_BLOCK_ID_TA02 = 0xa1, + DBG_BLOCK_ID_TA03 = 0xa2, + DBG_BLOCK_ID_TA04 = 0xa3, + DBG_BLOCK_ID_TA05 = 0xa4, + DBG_BLOCK_ID_TA06 = 0xa5, + DBG_BLOCK_ID_TA07 = 0xa6, + DBG_BLOCK_ID_TA08 = 0xa7, + DBG_BLOCK_ID_TA09 = 0xa8, + DBG_BLOCK_ID_TA0A = 0xa9, + DBG_BLOCK_ID_TA0B = 0xaa, + DBG_BLOCK_ID_UNUSED23 = 0xab, + DBG_BLOCK_ID_UNUSED24 = 0xac, + DBG_BLOCK_ID_UNUSED25 = 0xad, + DBG_BLOCK_ID_UNUSED26 = 0xae, + DBG_BLOCK_ID_TA10 = 0xaf, + DBG_BLOCK_ID_TA11 = 0xb0, + DBG_BLOCK_ID_TA12 = 0xb1, + DBG_BLOCK_ID_TA13 = 0xb2, + DBG_BLOCK_ID_TA14 = 0xb3, + DBG_BLOCK_ID_TA15 = 0xb4, + DBG_BLOCK_ID_TA16 = 0xb5, + DBG_BLOCK_ID_TA17 = 0xb6, + DBG_BLOCK_ID_TA18 = 0xb7, + DBG_BLOCK_ID_TA19 = 0xb8, + DBG_BLOCK_ID_TA1A = 0xb9, + DBG_BLOCK_ID_TA1B = 0xba, + DBG_BLOCK_ID_UNUSED27 = 0xbb, + DBG_BLOCK_ID_UNUSED28 = 0xbc, + DBG_BLOCK_ID_UNUSED29 = 0xbd, + DBG_BLOCK_ID_UNUSED30 = 0xbe, + DBG_BLOCK_ID_TD00 = 0xbf, + DBG_BLOCK_ID_TD01 = 0xc0, + DBG_BLOCK_ID_TD02 = 0xc1, + DBG_BLOCK_ID_TD03 = 0xc2, + DBG_BLOCK_ID_TD04 = 0xc3, + DBG_BLOCK_ID_TD05 = 0xc4, + DBG_BLOCK_ID_TD06 = 0xc5, + DBG_BLOCK_ID_TD07 = 0xc6, + DBG_BLOCK_ID_TD08 = 0xc7, + DBG_BLOCK_ID_TD09 = 0xc8, + DBG_BLOCK_ID_TD0A = 0xc9, + DBG_BLOCK_ID_TD0B = 0xca, + DBG_BLOCK_ID_UNUSED31 = 0xcb, + DBG_BLOCK_ID_UNUSED32 = 0xcc, + DBG_BLOCK_ID_UNUSED33 = 0xcd, + DBG_BLOCK_ID_UNUSED34 = 0xce, + DBG_BLOCK_ID_TD10 = 0xcf, + DBG_BLOCK_ID_TD11 = 0xd0, + DBG_BLOCK_ID_TD12 = 0xd1, + DBG_BLOCK_ID_TD13 = 0xd2, + DBG_BLOCK_ID_TD14 = 0xd3, + DBG_BLOCK_ID_TD15 = 0xd4, + DBG_BLOCK_ID_TD16 = 0xd5, + DBG_BLOCK_ID_TD17 = 0xd6, + DBG_BLOCK_ID_TD18 = 0xd7, + DBG_BLOCK_ID_TD19 = 0xd8, + DBG_BLOCK_ID_TD1A = 0xd9, + DBG_BLOCK_ID_TD1B = 0xda, + DBG_BLOCK_ID_UNUSED35 = 0xdb, + DBG_BLOCK_ID_UNUSED36 = 0xdc, + DBG_BLOCK_ID_UNUSED37 = 0xdd, + DBG_BLOCK_ID_UNUSED38 = 0xde, + DBG_BLOCK_ID_LDS00 = 0xdf, + DBG_BLOCK_ID_LDS01 = 0xe0, + DBG_BLOCK_ID_LDS02 = 0xe1, + DBG_BLOCK_ID_LDS03 = 0xe2, + DBG_BLOCK_ID_LDS04 = 0xe3, + DBG_BLOCK_ID_LDS05 = 0xe4, + DBG_BLOCK_ID_LDS06 = 0xe5, + DBG_BLOCK_ID_LDS07 = 0xe6, + DBG_BLOCK_ID_LDS08 = 0xe7, + DBG_BLOCK_ID_LDS09 = 0xe8, + DBG_BLOCK_ID_LDS0A = 0xe9, + DBG_BLOCK_ID_LDS0B = 0xea, + DBG_BLOCK_ID_UNUSED39 = 0xeb, + DBG_BLOCK_ID_UNUSED40 = 0xec, + DBG_BLOCK_ID_UNUSED41 = 0xed, + DBG_BLOCK_ID_UNUSED42 = 0xee, + DBG_BLOCK_ID_LDS10 = 0xef, + DBG_BLOCK_ID_LDS11 = 0xf0, + DBG_BLOCK_ID_LDS12 = 0xf1, + DBG_BLOCK_ID_LDS13 = 0xf2, + DBG_BLOCK_ID_LDS14 = 0xf3, + DBG_BLOCK_ID_LDS15 = 0xf4, + DBG_BLOCK_ID_LDS16 = 0xf5, + DBG_BLOCK_ID_LDS17 = 0xf6, + DBG_BLOCK_ID_LDS18 = 0xf7, + DBG_BLOCK_ID_LDS19 = 0xf8, + DBG_BLOCK_ID_LDS1A = 0xf9, + DBG_BLOCK_ID_LDS1B = 0xfa, + DBG_BLOCK_ID_UNUSED43 = 0xfb, + DBG_BLOCK_ID_UNUSED44 = 0xfc, + DBG_BLOCK_ID_UNUSED45 = 0xfd, + DBG_BLOCK_ID_UNUSED46 = 0xfe, +} DebugBlockId; +typedef enum DebugBlockId_BY2 { + DBG_BLOCK_ID_RESERVED_BY2 = 0x0, + DBG_BLOCK_ID_VMC_BY2 = 0x1, + DBG_BLOCK_ID_UNUSED0_BY2 = 0x2, + DBG_BLOCK_ID_GRBM_BY2 = 0x3, + DBG_BLOCK_ID_CSC_BY2 = 0x4, + DBG_BLOCK_ID_IH_BY2 = 0x5, + DBG_BLOCK_ID_SQ_BY2 = 0x6, + DBG_BLOCK_ID_UVD_BY2 = 0x7, + DBG_BLOCK_ID_SDMA0_BY2 = 0x8, + DBG_BLOCK_ID_SPIM_BY2 = 0x9, + DBG_BLOCK_ID_VC0_BY2 = 0xa, + DBG_BLOCK_ID_PA_BY2 = 0xb, + DBG_BLOCK_ID_CP0_BY2 = 0xc, + DBG_BLOCK_ID_CP2_BY2 = 0xd, + DBG_BLOCK_ID_PC0_BY2 = 0xe, + DBG_BLOCK_ID_BCI0_BY2 = 0xf, + DBG_BLOCK_ID_SXM0_BY2 = 0x10, + DBG_BLOCK_ID_SCT0_BY2 = 0x11, + DBG_BLOCK_ID_SPM0_BY2 = 0x12, + DBG_BLOCK_ID_BCI2_BY2 = 0x13, + DBG_BLOCK_ID_TCA_BY2 = 0x14, + DBG_BLOCK_ID_TCCA_BY2 = 0x15, + DBG_BLOCK_ID_MCC_BY2 = 0x16, + DBG_BLOCK_ID_MCC2_BY2 = 0x17, + DBG_BLOCK_ID_MCD_BY2 = 0x18, + DBG_BLOCK_ID_MCD2_BY2 = 0x19, + DBG_BLOCK_ID_MCD4_BY2 = 0x1a, + DBG_BLOCK_ID_MCB_BY2 = 0x1b, + DBG_BLOCK_ID_SQA_BY2 = 0x1c, + DBG_BLOCK_ID_SQA02_BY2 = 0x1d, + DBG_BLOCK_ID_SQA11_BY2 = 0x1e, + DBG_BLOCK_ID_UNUSED8_BY2 = 0x1f, + DBG_BLOCK_ID_SQB_BY2 = 0x20, + DBG_BLOCK_ID_SQB10_BY2 = 0x21, + DBG_BLOCK_ID_UNUSED10_BY2 = 0x22, + DBG_BLOCK_ID_UNUSED12_BY2 = 0x23, + DBG_BLOCK_ID_CB_BY2 = 0x24, + DBG_BLOCK_ID_CB02_BY2 = 0x25, + DBG_BLOCK_ID_CB10_BY2 = 0x26, + DBG_BLOCK_ID_CB12_BY2 = 0x27, + DBG_BLOCK_ID_SXS_BY2 = 0x28, + DBG_BLOCK_ID_SXS2_BY2 = 0x29, + DBG_BLOCK_ID_SXS4_BY2 = 0x2a, + DBG_BLOCK_ID_SXS6_BY2 = 0x2b, + DBG_BLOCK_ID_DB_BY2 = 0x2c, + DBG_BLOCK_ID_DB02_BY2 = 0x2d, + DBG_BLOCK_ID_DB10_BY2 = 0x2e, + DBG_BLOCK_ID_DB12_BY2 = 0x2f, + DBG_BLOCK_ID_TCP_BY2 = 0x30, + DBG_BLOCK_ID_TCP2_BY2 = 0x31, + DBG_BLOCK_ID_TCP4_BY2 = 0x32, + DBG_BLOCK_ID_TCP6_BY2 = 0x33, + DBG_BLOCK_ID_TCP8_BY2 = 0x34, + DBG_BLOCK_ID_TCP10_BY2 = 0x35, + DBG_BLOCK_ID_TCP12_BY2 = 0x36, + DBG_BLOCK_ID_TCP14_BY2 = 0x37, + DBG_BLOCK_ID_TCP16_BY2 = 0x38, + DBG_BLOCK_ID_TCP18_BY2 = 0x39, + DBG_BLOCK_ID_TCP20_BY2 = 0x3a, + DBG_BLOCK_ID_TCP22_BY2 = 0x3b, + DBG_BLOCK_ID_TCP_RESERVED0_BY2 = 0x3c, + DBG_BLOCK_ID_TCP_RESERVED2_BY2 = 0x3d, + DBG_BLOCK_ID_TCP_RESERVED4_BY2 = 0x3e, + DBG_BLOCK_ID_TCP_RESERVED6_BY2 = 0x3f, + DBG_BLOCK_ID_TCC_BY2 = 0x40, + DBG_BLOCK_ID_TCC2_BY2 = 0x41, + DBG_BLOCK_ID_TCC4_BY2 = 0x42, + DBG_BLOCK_ID_TCC6_BY2 = 0x43, + DBG_BLOCK_ID_SPS_BY2 = 0x44, + DBG_BLOCK_ID_SPS02_BY2 = 0x45, + DBG_BLOCK_ID_SPS11_BY2 = 0x46, + DBG_BLOCK_ID_UNUSED14_BY2 = 0x47, + DBG_BLOCK_ID_TA_BY2 = 0x48, + DBG_BLOCK_ID_TA02_BY2 = 0x49, + DBG_BLOCK_ID_TA04_BY2 = 0x4a, + DBG_BLOCK_ID_TA06_BY2 = 0x4b, + DBG_BLOCK_ID_TA08_BY2 = 0x4c, + DBG_BLOCK_ID_TA0A_BY2 = 0x4d, + DBG_BLOCK_ID_UNUSED20_BY2 = 0x4e, + DBG_BLOCK_ID_UNUSED22_BY2 = 0x4f, + DBG_BLOCK_ID_TA10_BY2 = 0x50, + DBG_BLOCK_ID_TA12_BY2 = 0x51, + DBG_BLOCK_ID_TA14_BY2 = 0x52, + DBG_BLOCK_ID_TA16_BY2 = 0x53, + DBG_BLOCK_ID_TA18_BY2 = 0x54, + DBG_BLOCK_ID_TA1A_BY2 = 0x55, + DBG_BLOCK_ID_UNUSED24_BY2 = 0x56, + DBG_BLOCK_ID_UNUSED26_BY2 = 0x57, + DBG_BLOCK_ID_TD_BY2 = 0x58, + DBG_BLOCK_ID_TD02_BY2 = 0x59, + DBG_BLOCK_ID_TD04_BY2 = 0x5a, + DBG_BLOCK_ID_TD06_BY2 = 0x5b, + DBG_BLOCK_ID_TD08_BY2 = 0x5c, + DBG_BLOCK_ID_TD0A_BY2 = 0x5d, + DBG_BLOCK_ID_UNUSED28_BY2 = 0x5e, + DBG_BLOCK_ID_UNUSED30_BY2 = 0x5f, + DBG_BLOCK_ID_TD10_BY2 = 0x60, + DBG_BLOCK_ID_TD12_BY2 = 0x61, + DBG_BLOCK_ID_TD14_BY2 = 0x62, + DBG_BLOCK_ID_TD16_BY2 = 0x63, + DBG_BLOCK_ID_TD18_BY2 = 0x64, + DBG_BLOCK_ID_TD1A_BY2 = 0x65, + DBG_BLOCK_ID_UNUSED32_BY2 = 0x66, + DBG_BLOCK_ID_UNUSED34_BY2 = 0x67, + DBG_BLOCK_ID_LDS_BY2 = 0x68, + DBG_BLOCK_ID_LDS02_BY2 = 0x69, + DBG_BLOCK_ID_LDS04_BY2 = 0x6a, + DBG_BLOCK_ID_LDS06_BY2 = 0x6b, + DBG_BLOCK_ID_LDS08_BY2 = 0x6c, + DBG_BLOCK_ID_LDS0A_BY2 = 0x6d, + DBG_BLOCK_ID_UNUSED36_BY2 = 0x6e, + DBG_BLOCK_ID_UNUSED38_BY2 = 0x6f, + DBG_BLOCK_ID_LDS10_BY2 = 0x70, + DBG_BLOCK_ID_LDS12_BY2 = 0x71, + DBG_BLOCK_ID_LDS14_BY2 = 0x72, + DBG_BLOCK_ID_LDS16_BY2 = 0x73, + DBG_BLOCK_ID_LDS18_BY2 = 0x74, + DBG_BLOCK_ID_LDS1A_BY2 = 0x75, + DBG_BLOCK_ID_UNUSED40_BY2 = 0x76, + DBG_BLOCK_ID_UNUSED42_BY2 = 0x77, +} DebugBlockId_BY2; +typedef enum DebugBlockId_BY4 { + DBG_BLOCK_ID_RESERVED_BY4 = 0x0, + DBG_BLOCK_ID_UNUSED0_BY4 = 0x1, + DBG_BLOCK_ID_CSC_BY4 = 0x2, + DBG_BLOCK_ID_SQ_BY4 = 0x3, + DBG_BLOCK_ID_SDMA0_BY4 = 0x4, + DBG_BLOCK_ID_VC0_BY4 = 0x5, + DBG_BLOCK_ID_CP0_BY4 = 0x6, + DBG_BLOCK_ID_UNUSED1_BY4 = 0x7, + DBG_BLOCK_ID_SXM0_BY4 = 0x8, + DBG_BLOCK_ID_SPM0_BY4 = 0x9, + DBG_BLOCK_ID_TCAA_BY4 = 0xa, + DBG_BLOCK_ID_MCC_BY4 = 0xb, + DBG_BLOCK_ID_MCD_BY4 = 0xc, + DBG_BLOCK_ID_MCD4_BY4 = 0xd, + DBG_BLOCK_ID_SQA_BY4 = 0xe, + DBG_BLOCK_ID_SQA11_BY4 = 0xf, + DBG_BLOCK_ID_SQB_BY4 = 0x10, + DBG_BLOCK_ID_UNUSED10_BY4 = 0x11, + DBG_BLOCK_ID_CB_BY4 = 0x12, + DBG_BLOCK_ID_CB10_BY4 = 0x13, + DBG_BLOCK_ID_SXS_BY4 = 0x14, + DBG_BLOCK_ID_SXS4_BY4 = 0x15, + DBG_BLOCK_ID_DB_BY4 = 0x16, + DBG_BLOCK_ID_DB10_BY4 = 0x17, + DBG_BLOCK_ID_TCP_BY4 = 0x18, + DBG_BLOCK_ID_TCP4_BY4 = 0x19, + DBG_BLOCK_ID_TCP8_BY4 = 0x1a, + DBG_BLOCK_ID_TCP12_BY4 = 0x1b, + DBG_BLOCK_ID_TCP16_BY4 = 0x1c, + DBG_BLOCK_ID_TCP20_BY4 = 0x1d, + DBG_BLOCK_ID_TCP_RESERVED0_BY4 = 0x1e, + DBG_BLOCK_ID_TCP_RESERVED4_BY4 = 0x1f, + DBG_BLOCK_ID_TCC_BY4 = 0x20, + DBG_BLOCK_ID_TCC4_BY4 = 0x21, + DBG_BLOCK_ID_SPS_BY4 = 0x22, + DBG_BLOCK_ID_SPS11_BY4 = 0x23, + DBG_BLOCK_ID_TA_BY4 = 0x24, + DBG_BLOCK_ID_TA04_BY4 = 0x25, + DBG_BLOCK_ID_TA08_BY4 = 0x26, + DBG_BLOCK_ID_UNUSED20_BY4 = 0x27, + DBG_BLOCK_ID_TA10_BY4 = 0x28, + DBG_BLOCK_ID_TA14_BY4 = 0x29, + DBG_BLOCK_ID_TA18_BY4 = 0x2a, + DBG_BLOCK_ID_UNUSED24_BY4 = 0x2b, + DBG_BLOCK_ID_TD_BY4 = 0x2c, + DBG_BLOCK_ID_TD04_BY4 = 0x2d, + DBG_BLOCK_ID_TD08_BY4 = 0x2e, + DBG_BLOCK_ID_UNUSED28_BY4 = 0x2f, + DBG_BLOCK_ID_TD10_BY4 = 0x30, + DBG_BLOCK_ID_TD14_BY4 = 0x31, + DBG_BLOCK_ID_TD18_BY4 = 0x32, + DBG_BLOCK_ID_UNUSED32_BY4 = 0x33, + DBG_BLOCK_ID_LDS_BY4 = 0x34, + DBG_BLOCK_ID_LDS04_BY4 = 0x35, + DBG_BLOCK_ID_LDS08_BY4 = 0x36, + DBG_BLOCK_ID_UNUSED36_BY4 = 0x37, + DBG_BLOCK_ID_LDS10_BY4 = 0x38, + DBG_BLOCK_ID_LDS14_BY4 = 0x39, + DBG_BLOCK_ID_LDS18_BY4 = 0x3a, + DBG_BLOCK_ID_UNUSED40_BY4 = 0x3b, +} DebugBlockId_BY4; +typedef enum DebugBlockId_BY8 { + DBG_BLOCK_ID_RESERVED_BY8 = 0x0, + DBG_BLOCK_ID_CSC_BY8 = 0x1, + DBG_BLOCK_ID_SDMA0_BY8 = 0x2, + DBG_BLOCK_ID_CP0_BY8 = 0x3, + DBG_BLOCK_ID_SXM0_BY8 = 0x4, + DBG_BLOCK_ID_TCA_BY8 = 0x5, + DBG_BLOCK_ID_MCD_BY8 = 0x6, + DBG_BLOCK_ID_SQA_BY8 = 0x7, + DBG_BLOCK_ID_SQB_BY8 = 0x8, + DBG_BLOCK_ID_CB_BY8 = 0x9, + DBG_BLOCK_ID_SXS_BY8 = 0xa, + DBG_BLOCK_ID_DB_BY8 = 0xb, + DBG_BLOCK_ID_TCP_BY8 = 0xc, + DBG_BLOCK_ID_TCP8_BY8 = 0xd, + DBG_BLOCK_ID_TCP16_BY8 = 0xe, + DBG_BLOCK_ID_TCP_RESERVED0_BY8 = 0xf, + DBG_BLOCK_ID_TCC_BY8 = 0x10, + DBG_BLOCK_ID_SPS_BY8 = 0x11, + DBG_BLOCK_ID_TA_BY8 = 0x12, + DBG_BLOCK_ID_TA08_BY8 = 0x13, + DBG_BLOCK_ID_TA10_BY8 = 0x14, + DBG_BLOCK_ID_TA18_BY8 = 0x15, + DBG_BLOCK_ID_TD_BY8 = 0x16, + DBG_BLOCK_ID_TD08_BY8 = 0x17, + DBG_BLOCK_ID_TD10_BY8 = 0x18, + DBG_BLOCK_ID_TD18_BY8 = 0x19, + DBG_BLOCK_ID_LDS_BY8 = 0x1a, + DBG_BLOCK_ID_LDS08_BY8 = 0x1b, + DBG_BLOCK_ID_LDS10_BY8 = 0x1c, + DBG_BLOCK_ID_LDS18_BY8 = 0x1d, +} DebugBlockId_BY8; +typedef enum DebugBlockId_BY16 { + DBG_BLOCK_ID_RESERVED_BY16 = 0x0, + DBG_BLOCK_ID_SDMA0_BY16 = 0x1, + DBG_BLOCK_ID_SXM_BY16 = 0x2, + DBG_BLOCK_ID_MCD_BY16 = 0x3, + DBG_BLOCK_ID_SQB_BY16 = 0x4, + DBG_BLOCK_ID_SXS_BY16 = 0x5, + DBG_BLOCK_ID_TCP_BY16 = 0x6, + DBG_BLOCK_ID_TCP16_BY16 = 0x7, + DBG_BLOCK_ID_TCC_BY16 = 0x8, + DBG_BLOCK_ID_TA_BY16 = 0x9, + DBG_BLOCK_ID_TA10_BY16 = 0xa, + DBG_BLOCK_ID_TD_BY16 = 0xb, + DBG_BLOCK_ID_TD10_BY16 = 0xc, + DBG_BLOCK_ID_LDS_BY16 = 0xd, + DBG_BLOCK_ID_LDS10_BY16 = 0xe, +} DebugBlockId_BY16; +typedef enum SurfaceEndian { + ENDIAN_NONE = 0x0, + ENDIAN_8IN16 = 0x1, + ENDIAN_8IN32 = 0x2, + ENDIAN_8IN64 = 0x3, +} SurfaceEndian; +typedef enum ArrayMode { + ARRAY_LINEAR_GENERAL = 0x0, + ARRAY_LINEAR_ALIGNED = 0x1, + ARRAY_1D_TILED_THIN1 = 0x2, + ARRAY_1D_TILED_THICK = 0x3, + ARRAY_2D_TILED_THIN1 = 0x4, + ARRAY_PRT_TILED_THIN1 = 0x5, + ARRAY_PRT_2D_TILED_THIN1 = 0x6, + ARRAY_2D_TILED_THICK = 0x7, + ARRAY_2D_TILED_XTHICK = 0x8, + ARRAY_PRT_TILED_THICK = 0x9, + ARRAY_PRT_2D_TILED_THICK = 0xa, + ARRAY_PRT_3D_TILED_THIN1 = 0xb, + ARRAY_3D_TILED_THIN1 = 0xc, + ARRAY_3D_TILED_THICK = 0xd, + ARRAY_3D_TILED_XTHICK = 0xe, + ARRAY_PRT_3D_TILED_THICK = 0xf, +} ArrayMode; +typedef enum PipeTiling { + CONFIG_1_PIPE = 0x0, + CONFIG_2_PIPE = 0x1, + CONFIG_4_PIPE = 0x2, + CONFIG_8_PIPE = 0x3, +} PipeTiling; +typedef enum BankTiling { + CONFIG_4_BANK = 0x0, + CONFIG_8_BANK = 0x1, +} BankTiling; +typedef enum GroupInterleave { + CONFIG_256B_GROUP = 0x0, + CONFIG_512B_GROUP = 0x1, +} GroupInterleave; +typedef enum RowTiling { + CONFIG_1KB_ROW = 0x0, + CONFIG_2KB_ROW = 0x1, + CONFIG_4KB_ROW = 0x2, + CONFIG_8KB_ROW = 0x3, + CONFIG_1KB_ROW_OPT = 0x4, + CONFIG_2KB_ROW_OPT = 0x5, + CONFIG_4KB_ROW_OPT = 0x6, + CONFIG_8KB_ROW_OPT = 0x7, +} RowTiling; +typedef enum BankSwapBytes { + CONFIG_128B_SWAPS = 0x0, + CONFIG_256B_SWAPS = 0x1, + CONFIG_512B_SWAPS = 0x2, + CONFIG_1KB_SWAPS = 0x3, +} BankSwapBytes; +typedef enum SampleSplitBytes { + CONFIG_1KB_SPLIT = 0x0, + CONFIG_2KB_SPLIT = 0x1, + CONFIG_4KB_SPLIT = 0x2, + CONFIG_8KB_SPLIT = 0x3, +} SampleSplitBytes; +typedef enum NumPipes { + ADDR_CONFIG_1_PIPE = 0x0, + ADDR_CONFIG_2_PIPE = 0x1, + ADDR_CONFIG_4_PIPE = 0x2, + ADDR_CONFIG_8_PIPE = 0x3, +} NumPipes; +typedef enum PipeInterleaveSize { + ADDR_CONFIG_PIPE_INTERLEAVE_256B = 0x0, + ADDR_CONFIG_PIPE_INTERLEAVE_512B = 0x1, +} PipeInterleaveSize; +typedef enum BankInterleaveSize { + ADDR_CONFIG_BANK_INTERLEAVE_1 = 0x0, + ADDR_CONFIG_BANK_INTERLEAVE_2 = 0x1, + ADDR_CONFIG_BANK_INTERLEAVE_4 = 0x2, + ADDR_CONFIG_BANK_INTERLEAVE_8 = 0x3, +} BankInterleaveSize; +typedef enum NumShaderEngines { + ADDR_CONFIG_1_SHADER_ENGINE = 0x0, + ADDR_CONFIG_2_SHADER_ENGINE = 0x1, +} NumShaderEngines; +typedef enum ShaderEngineTileSize { + ADDR_CONFIG_SE_TILE_16 = 0x0, + ADDR_CONFIG_SE_TILE_32 = 0x1, +} ShaderEngineTileSize; +typedef enum NumGPUs { + ADDR_CONFIG_1_GPU = 0x0, + ADDR_CONFIG_2_GPU = 0x1, + ADDR_CONFIG_4_GPU = 0x2, +} NumGPUs; +typedef enum MultiGPUTileSize { + ADDR_CONFIG_GPU_TILE_16 = 0x0, + ADDR_CONFIG_GPU_TILE_32 = 0x1, + ADDR_CONFIG_GPU_TILE_64 = 0x2, + ADDR_CONFIG_GPU_TILE_128 = 0x3, +} MultiGPUTileSize; +typedef enum RowSize { + ADDR_CONFIG_1KB_ROW = 0x0, + ADDR_CONFIG_2KB_ROW = 0x1, + ADDR_CONFIG_4KB_ROW = 0x2, +} RowSize; +typedef enum NumLowerPipes { + ADDR_CONFIG_1_LOWER_PIPES = 0x0, + ADDR_CONFIG_2_LOWER_PIPES = 0x1, +} NumLowerPipes; +typedef enum ColorTransform { + DCC_CT_AUTO = 0x0, + DCC_CT_NONE = 0x1, + ABGR_TO_A_BG_G_RB = 0x2, + BGRA_TO_BG_G_RB_A = 0x3, +} ColorTransform; +typedef enum CompareRef { + REF_NEVER = 0x0, + REF_LESS = 0x1, + REF_EQUAL = 0x2, + REF_LEQUAL = 0x3, + REF_GREATER = 0x4, + REF_NOTEQUAL = 0x5, + REF_GEQUAL = 0x6, + REF_ALWAYS = 0x7, +} CompareRef; +typedef enum ReadSize { + READ_256_BITS = 0x0, + READ_512_BITS = 0x1, +} ReadSize; +typedef enum DepthFormat { + DEPTH_INVALID = 0x0, + DEPTH_16 = 0x1, + DEPTH_X8_24 = 0x2, + DEPTH_8_24 = 0x3, + DEPTH_X8_24_FLOAT = 0x4, + DEPTH_8_24_FLOAT = 0x5, + DEPTH_32_FLOAT = 0x6, + DEPTH_X24_8_32_FLOAT = 0x7, +} DepthFormat; +typedef enum ZFormat { + Z_INVALID = 0x0, + Z_16 = 0x1, + Z_24 = 0x2, + Z_32_FLOAT = 0x3, +} ZFormat; +typedef enum StencilFormat { + STENCIL_INVALID = 0x0, + STENCIL_8 = 0x1, +} StencilFormat; +typedef enum CmaskMode { + CMASK_CLEAR_NONE = 0x0, + CMASK_CLEAR_ONE = 0x1, + CMASK_CLEAR_ALL = 0x2, + CMASK_ANY_EXPANDED = 0x3, + CMASK_ALPHA0_FRAG1 = 0x4, + CMASK_ALPHA0_FRAG2 = 0x5, + CMASK_ALPHA0_FRAG4 = 0x6, + CMASK_ALPHA0_FRAGS = 0x7, + CMASK_ALPHA1_FRAG1 = 0x8, + CMASK_ALPHA1_FRAG2 = 0x9, + CMASK_ALPHA1_FRAG4 = 0xa, + CMASK_ALPHA1_FRAGS = 0xb, + CMASK_ALPHAX_FRAG1 = 0xc, + CMASK_ALPHAX_FRAG2 = 0xd, + CMASK_ALPHAX_FRAG4 = 0xe, + CMASK_ALPHAX_FRAGS = 0xf, +} CmaskMode; +typedef enum QuadExportFormat { + EXPORT_UNUSED = 0x0, + EXPORT_32_R = 0x1, + EXPORT_32_GR = 0x2, + EXPORT_32_AR = 0x3, + EXPORT_FP16_ABGR = 0x4, + EXPORT_UNSIGNED16_ABGR = 0x5, + EXPORT_SIGNED16_ABGR = 0x6, + EXPORT_32_ABGR = 0x7, +} QuadExportFormat; +typedef enum QuadExportFormatOld { + EXPORT_4P_32BPC_ABGR = 0x0, + EXPORT_4P_16BPC_ABGR = 0x1, + EXPORT_4P_32BPC_GR = 0x2, + EXPORT_4P_32BPC_AR = 0x3, + EXPORT_2P_32BPC_ABGR = 0x4, + EXPORT_8P_32BPC_R = 0x5, +} QuadExportFormatOld; +typedef enum ColorFormat { + COLOR_INVALID = 0x0, + COLOR_8 = 0x1, + COLOR_16 = 0x2, + COLOR_8_8 = 0x3, + COLOR_32 = 0x4, + COLOR_16_16 = 0x5, + COLOR_10_11_11 = 0x6, + COLOR_11_11_10 = 0x7, + COLOR_10_10_10_2 = 0x8, + COLOR_2_10_10_10 = 0x9, + COLOR_8_8_8_8 = 0xa, + COLOR_32_32 = 0xb, + COLOR_16_16_16_16 = 0xc, + COLOR_RESERVED_13 = 0xd, + COLOR_32_32_32_32 = 0xe, + COLOR_RESERVED_15 = 0xf, + COLOR_5_6_5 = 0x10, + COLOR_1_5_5_5 = 0x11, + COLOR_5_5_5_1 = 0x12, + COLOR_4_4_4_4 = 0x13, + COLOR_8_24 = 0x14, + COLOR_24_8 = 0x15, + COLOR_X24_8_32_FLOAT = 0x16, + COLOR_RESERVED_23 = 0x17, +} ColorFormat; +typedef enum SurfaceFormat { + FMT_INVALID = 0x0, + FMT_8 = 0x1, + FMT_16 = 0x2, + FMT_8_8 = 0x3, + FMT_32 = 0x4, + FMT_16_16 = 0x5, + FMT_10_11_11 = 0x6, + FMT_11_11_10 = 0x7, + FMT_10_10_10_2 = 0x8, + FMT_2_10_10_10 = 0x9, + FMT_8_8_8_8 = 0xa, + FMT_32_32 = 0xb, + FMT_16_16_16_16 = 0xc, + FMT_32_32_32 = 0xd, + FMT_32_32_32_32 = 0xe, + FMT_RESERVED_4 = 0xf, + FMT_5_6_5 = 0x10, + FMT_1_5_5_5 = 0x11, + FMT_5_5_5_1 = 0x12, + FMT_4_4_4_4 = 0x13, + FMT_8_24 = 0x14, + FMT_24_8 = 0x15, + FMT_X24_8_32_FLOAT = 0x16, + FMT_RESERVED_33 = 0x17, + FMT_11_11_10_FLOAT = 0x18, + FMT_16_FLOAT = 0x19, + FMT_32_FLOAT = 0x1a, + FMT_16_16_FLOAT = 0x1b, + FMT_8_24_FLOAT = 0x1c, + FMT_24_8_FLOAT = 0x1d, + FMT_32_32_FLOAT = 0x1e, + FMT_10_11_11_FLOAT = 0x1f, + FMT_16_16_16_16_FLOAT = 0x20, + FMT_3_3_2 = 0x21, + FMT_6_5_5 = 0x22, + FMT_32_32_32_32_FLOAT = 0x23, + FMT_RESERVED_36 = 0x24, + FMT_1 = 0x25, + FMT_1_REVERSED = 0x26, + FMT_GB_GR = 0x27, + FMT_BG_RG = 0x28, + FMT_32_AS_8 = 0x29, + FMT_32_AS_8_8 = 0x2a, + FMT_5_9_9_9_SHAREDEXP = 0x2b, + FMT_8_8_8 = 0x2c, + FMT_16_16_16 = 0x2d, + FMT_16_16_16_FLOAT = 0x2e, + FMT_4_4 = 0x2f, + FMT_32_32_32_FLOAT = 0x30, + FMT_BC1 = 0x31, + FMT_BC2 = 0x32, + FMT_BC3 = 0x33, + FMT_BC4 = 0x34, + FMT_BC5 = 0x35, + FMT_BC6 = 0x36, + FMT_BC7 = 0x37, + FMT_32_AS_32_32_32_32 = 0x38, + FMT_APC3 = 0x39, + FMT_APC4 = 0x3a, + FMT_APC5 = 0x3b, + FMT_APC6 = 0x3c, + FMT_APC7 = 0x3d, + FMT_CTX1 = 0x3e, + FMT_RESERVED_63 = 0x3f, +} SurfaceFormat; +typedef enum BUF_DATA_FORMAT { + BUF_DATA_FORMAT_INVALID = 0x0, + BUF_DATA_FORMAT_8 = 0x1, + BUF_DATA_FORMAT_16 = 0x2, + BUF_DATA_FORMAT_8_8 = 0x3, + BUF_DATA_FORMAT_32 = 0x4, + BUF_DATA_FORMAT_16_16 = 0x5, + BUF_DATA_FORMAT_10_11_11 = 0x6, + BUF_DATA_FORMAT_11_11_10 = 0x7, + BUF_DATA_FORMAT_10_10_10_2 = 0x8, + BUF_DATA_FORMAT_2_10_10_10 = 0x9, + BUF_DATA_FORMAT_8_8_8_8 = 0xa, + BUF_DATA_FORMAT_32_32 = 0xb, + BUF_DATA_FORMAT_16_16_16_16 = 0xc, + BUF_DATA_FORMAT_32_32_32 = 0xd, + BUF_DATA_FORMAT_32_32_32_32 = 0xe, + BUF_DATA_FORMAT_RESERVED_15 = 0xf, +} BUF_DATA_FORMAT; +typedef enum IMG_DATA_FORMAT { + IMG_DATA_FORMAT_INVALID = 0x0, + IMG_DATA_FORMAT_8 = 0x1, + IMG_DATA_FORMAT_16 = 0x2, + IMG_DATA_FORMAT_8_8 = 0x3, + IMG_DATA_FORMAT_32 = 0x4, + IMG_DATA_FORMAT_16_16 = 0x5, + IMG_DATA_FORMAT_10_11_11 = 0x6, + IMG_DATA_FORMAT_11_11_10 = 0x7, + IMG_DATA_FORMAT_10_10_10_2 = 0x8, + IMG_DATA_FORMAT_2_10_10_10 = 0x9, + IMG_DATA_FORMAT_8_8_8_8 = 0xa, + IMG_DATA_FORMAT_32_32 = 0xb, + IMG_DATA_FORMAT_16_16_16_16 = 0xc, + IMG_DATA_FORMAT_32_32_32 = 0xd, + IMG_DATA_FORMAT_32_32_32_32 = 0xe, + IMG_DATA_FORMAT_RESERVED_15 = 0xf, + IMG_DATA_FORMAT_5_6_5 = 0x10, + IMG_DATA_FORMAT_1_5_5_5 = 0x11, + IMG_DATA_FORMAT_5_5_5_1 = 0x12, + IMG_DATA_FORMAT_4_4_4_4 = 0x13, + IMG_DATA_FORMAT_8_24 = 0x14, + IMG_DATA_FORMAT_24_8 = 0x15, + IMG_DATA_FORMAT_X24_8_32 = 0x16, + IMG_DATA_FORMAT_RESERVED_23 = 0x17, + IMG_DATA_FORMAT_RESERVED_24 = 0x18, + IMG_DATA_FORMAT_RESERVED_25 = 0x19, + IMG_DATA_FORMAT_RESERVED_26 = 0x1a, + IMG_DATA_FORMAT_RESERVED_27 = 0x1b, + IMG_DATA_FORMAT_RESERVED_28 = 0x1c, + IMG_DATA_FORMAT_RESERVED_29 = 0x1d, + IMG_DATA_FORMAT_RESERVED_30 = 0x1e, + IMG_DATA_FORMAT_RESERVED_31 = 0x1f, + IMG_DATA_FORMAT_GB_GR = 0x20, + IMG_DATA_FORMAT_BG_RG = 0x21, + IMG_DATA_FORMAT_5_9_9_9 = 0x22, + IMG_DATA_FORMAT_BC1 = 0x23, + IMG_DATA_FORMAT_BC2 = 0x24, + IMG_DATA_FORMAT_BC3 = 0x25, + IMG_DATA_FORMAT_BC4 = 0x26, + IMG_DATA_FORMAT_BC5 = 0x27, + IMG_DATA_FORMAT_BC6 = 0x28, + IMG_DATA_FORMAT_BC7 = 0x29, + IMG_DATA_FORMAT_RESERVED_42 = 0x2a, + IMG_DATA_FORMAT_RESERVED_43 = 0x2b, + IMG_DATA_FORMAT_FMASK8_S2_F1 = 0x2c, + IMG_DATA_FORMAT_FMASK8_S4_F1 = 0x2d, + IMG_DATA_FORMAT_FMASK8_S8_F1 = 0x2e, + IMG_DATA_FORMAT_FMASK8_S2_F2 = 0x2f, + IMG_DATA_FORMAT_FMASK8_S4_F2 = 0x30, + IMG_DATA_FORMAT_FMASK8_S4_F4 = 0x31, + IMG_DATA_FORMAT_FMASK16_S16_F1 = 0x32, + IMG_DATA_FORMAT_FMASK16_S8_F2 = 0x33, + IMG_DATA_FORMAT_FMASK32_S16_F2 = 0x34, + IMG_DATA_FORMAT_FMASK32_S8_F4 = 0x35, + IMG_DATA_FORMAT_FMASK32_S8_F8 = 0x36, + IMG_DATA_FORMAT_FMASK64_S16_F4 = 0x37, + IMG_DATA_FORMAT_FMASK64_S16_F8 = 0x38, + IMG_DATA_FORMAT_4_4 = 0x39, + IMG_DATA_FORMAT_6_5_5 = 0x3a, + IMG_DATA_FORMAT_1 = 0x3b, + IMG_DATA_FORMAT_1_REVERSED = 0x3c, + IMG_DATA_FORMAT_32_AS_8 = 0x3d, + IMG_DATA_FORMAT_32_AS_8_8 = 0x3e, + IMG_DATA_FORMAT_32_AS_32_32_32_32 = 0x3f, +} IMG_DATA_FORMAT; +typedef enum BUF_NUM_FORMAT { + BUF_NUM_FORMAT_UNORM = 0x0, + BUF_NUM_FORMAT_SNORM = 0x1, + BUF_NUM_FORMAT_USCALED = 0x2, + BUF_NUM_FORMAT_SSCALED = 0x3, + BUF_NUM_FORMAT_UINT = 0x4, + BUF_NUM_FORMAT_SINT = 0x5, + BUF_NUM_FORMAT_RESERVED_6 = 0x6, + BUF_NUM_FORMAT_FLOAT = 0x7, +} BUF_NUM_FORMAT; +typedef enum IMG_NUM_FORMAT { + IMG_NUM_FORMAT_UNORM = 0x0, + IMG_NUM_FORMAT_SNORM = 0x1, + IMG_NUM_FORMAT_USCALED = 0x2, + IMG_NUM_FORMAT_SSCALED = 0x3, + IMG_NUM_FORMAT_UINT = 0x4, + IMG_NUM_FORMAT_SINT = 0x5, + IMG_NUM_FORMAT_RESERVED_6 = 0x6, + IMG_NUM_FORMAT_FLOAT = 0x7, + IMG_NUM_FORMAT_RESERVED_8 = 0x8, + IMG_NUM_FORMAT_SRGB = 0x9, + IMG_NUM_FORMAT_RESERVED_10 = 0xa, + IMG_NUM_FORMAT_RESERVED_11 = 0xb, + IMG_NUM_FORMAT_RESERVED_12 = 0xc, + IMG_NUM_FORMAT_RESERVED_13 = 0xd, + IMG_NUM_FORMAT_RESERVED_14 = 0xe, + IMG_NUM_FORMAT_RESERVED_15 = 0xf, +} IMG_NUM_FORMAT; +typedef enum TileType { + ARRAY_COLOR_TILE = 0x0, + ARRAY_DEPTH_TILE = 0x1, +} TileType; +typedef enum NonDispTilingOrder { + ADDR_SURF_MICRO_TILING_DISPLAY = 0x0, + ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, +} NonDispTilingOrder; +typedef enum MicroTileMode { + ADDR_SURF_DISPLAY_MICRO_TILING = 0x0, + ADDR_SURF_THIN_MICRO_TILING = 0x1, + ADDR_SURF_DEPTH_MICRO_TILING = 0x2, + ADDR_SURF_ROTATED_MICRO_TILING = 0x3, + ADDR_SURF_THICK_MICRO_TILING = 0x4, +} MicroTileMode; +typedef enum TileSplit { + ADDR_SURF_TILE_SPLIT_64B = 0x0, + ADDR_SURF_TILE_SPLIT_128B = 0x1, + ADDR_SURF_TILE_SPLIT_256B = 0x2, + ADDR_SURF_TILE_SPLIT_512B = 0x3, + ADDR_SURF_TILE_SPLIT_1KB = 0x4, + ADDR_SURF_TILE_SPLIT_2KB = 0x5, + ADDR_SURF_TILE_SPLIT_4KB = 0x6, +} TileSplit; +typedef enum SampleSplit { + ADDR_SURF_SAMPLE_SPLIT_1 = 0x0, + ADDR_SURF_SAMPLE_SPLIT_2 = 0x1, + ADDR_SURF_SAMPLE_SPLIT_4 = 0x2, + ADDR_SURF_SAMPLE_SPLIT_8 = 0x3, +} SampleSplit; +typedef enum PipeConfig { + ADDR_SURF_P2 = 0x0, + ADDR_SURF_P2_RESERVED0 = 0x1, + ADDR_SURF_P2_RESERVED1 = 0x2, + ADDR_SURF_P2_RESERVED2 = 0x3, + ADDR_SURF_P4_8x16 = 0x4, + ADDR_SURF_P4_16x16 = 0x5, + ADDR_SURF_P4_16x32 = 0x6, + ADDR_SURF_P4_32x32 = 0x7, + ADDR_SURF_P8_16x16_8x16 = 0x8, + ADDR_SURF_P8_16x32_8x16 = 0x9, + ADDR_SURF_P8_32x32_8x16 = 0xa, + ADDR_SURF_P8_16x32_16x16 = 0xb, + ADDR_SURF_P8_32x32_16x16 = 0xc, + ADDR_SURF_P8_32x32_16x32 = 0xd, + ADDR_SURF_P8_32x64_32x32 = 0xe, + ADDR_SURF_P8_RESERVED0 = 0xf, + ADDR_SURF_P16_32x32_8x16 = 0x10, + ADDR_SURF_P16_32x32_16x16 = 0x11, +} PipeConfig; +typedef enum NumBanks { + ADDR_SURF_2_BANK = 0x0, + ADDR_SURF_4_BANK = 0x1, + ADDR_SURF_8_BANK = 0x2, + ADDR_SURF_16_BANK = 0x3, +} NumBanks; +typedef enum BankWidth { + ADDR_SURF_BANK_WIDTH_1 = 0x0, + ADDR_SURF_BANK_WIDTH_2 = 0x1, + ADDR_SURF_BANK_WIDTH_4 = 0x2, + ADDR_SURF_BANK_WIDTH_8 = 0x3, +} BankWidth; +typedef enum BankHeight { + ADDR_SURF_BANK_HEIGHT_1 = 0x0, + ADDR_SURF_BANK_HEIGHT_2 = 0x1, + ADDR_SURF_BANK_HEIGHT_4 = 0x2, + ADDR_SURF_BANK_HEIGHT_8 = 0x3, +} BankHeight; +typedef enum BankWidthHeight { + ADDR_SURF_BANK_WH_1 = 0x0, + ADDR_SURF_BANK_WH_2 = 0x1, + ADDR_SURF_BANK_WH_4 = 0x2, + ADDR_SURF_BANK_WH_8 = 0x3, +} BankWidthHeight; +typedef enum MacroTileAspect { + ADDR_SURF_MACRO_ASPECT_1 = 0x0, + ADDR_SURF_MACRO_ASPECT_2 = 0x1, + ADDR_SURF_MACRO_ASPECT_4 = 0x2, + ADDR_SURF_MACRO_ASPECT_8 = 0x3, +} MacroTileAspect; +typedef enum GATCL1RequestType { + GATCL1_TYPE_NORMAL = 0x0, + GATCL1_TYPE_SHOOTDOWN = 0x1, + GATCL1_TYPE_BYPASS = 0x2, +} GATCL1RequestType; +typedef enum TCC_CACHE_POLICIES { + TCC_CACHE_POLICY_LRU = 0x0, + TCC_CACHE_POLICY_STREAM = 0x1, +} TCC_CACHE_POLICIES; +typedef enum MTYPE { + MTYPE_NC_NV = 0x0, + MTYPE_NC = 0x1, + MTYPE_CC = 0x2, + MTYPE_UC = 0x3, +} MTYPE; +typedef enum PERFMON_COUNTER_MODE { + PERFMON_COUNTER_MODE_ACCUM = 0x0, + PERFMON_COUNTER_MODE_ACTIVE_CYCLES = 0x1, + PERFMON_COUNTER_MODE_MAX = 0x2, + PERFMON_COUNTER_MODE_DIRTY = 0x3, + PERFMON_COUNTER_MODE_SAMPLE = 0x4, + PERFMON_COUNTER_MODE_CYCLES_SINCE_FIRST_EVENT = 0x5, + PERFMON_COUNTER_MODE_CYCLES_SINCE_LAST_EVENT = 0x6, + PERFMON_COUNTER_MODE_CYCLES_GE_HI = 0x7, + PERFMON_COUNTER_MODE_CYCLES_EQ_HI = 0x8, + PERFMON_COUNTER_MODE_INACTIVE_CYCLES = 0x9, + PERFMON_COUNTER_MODE_RESERVED = 0xf, +} PERFMON_COUNTER_MODE; +typedef enum PERFMON_SPM_MODE { + PERFMON_SPM_MODE_OFF = 0x0, + PERFMON_SPM_MODE_16BIT_CLAMP = 0x1, + PERFMON_SPM_MODE_16BIT_NO_CLAMP = 0x2, + PERFMON_SPM_MODE_32BIT_CLAMP = 0x3, + PERFMON_SPM_MODE_32BIT_NO_CLAMP = 0x4, + PERFMON_SPM_MODE_RESERVED_5 = 0x5, + PERFMON_SPM_MODE_RESERVED_6 = 0x6, + PERFMON_SPM_MODE_RESERVED_7 = 0x7, + PERFMON_SPM_MODE_TEST_MODE_0 = 0x8, + PERFMON_SPM_MODE_TEST_MODE_1 = 0x9, + PERFMON_SPM_MODE_TEST_MODE_2 = 0xa, +} PERFMON_SPM_MODE; +typedef enum SurfaceTiling { + ARRAY_LINEAR = 0x0, + ARRAY_TILED = 0x1, +} SurfaceTiling; +typedef enum SurfaceArray { + ARRAY_1D = 0x0, + ARRAY_2D = 0x1, + ARRAY_3D = 0x2, + ARRAY_3D_SLICE = 0x3, +} SurfaceArray; +typedef enum ColorArray { + ARRAY_2D_ALT_COLOR = 0x0, + ARRAY_2D_COLOR = 0x1, + ARRAY_3D_SLICE_COLOR = 0x3, +} ColorArray; +typedef enum DepthArray { + ARRAY_2D_ALT_DEPTH = 0x0, + ARRAY_2D_DEPTH = 0x1, +} DepthArray; +typedef enum ENUM_NUM_SIMD_PER_CU { + NUM_SIMD_PER_CU = 0x4, +} ENUM_NUM_SIMD_PER_CU; +typedef enum MEM_PWR_FORCE_CTRL { + NO_FORCE_REQUEST = 0x0, + FORCE_LIGHT_SLEEP_REQUEST = 0x1, + FORCE_DEEP_SLEEP_REQUEST = 0x2, + FORCE_SHUT_DOWN_REQUEST = 0x3, +} MEM_PWR_FORCE_CTRL; +typedef enum MEM_PWR_FORCE_CTRL2 { + NO_FORCE_REQ = 0x0, + FORCE_LIGHT_SLEEP_REQ = 0x1, +} MEM_PWR_FORCE_CTRL2; +typedef enum MEM_PWR_DIS_CTRL { + ENABLE_MEM_PWR_CTRL = 0x0, + DISABLE_MEM_PWR_CTRL = 0x1, +} MEM_PWR_DIS_CTRL; +typedef enum MEM_PWR_SEL_CTRL { + DYNAMIC_SHUT_DOWN_ENABLE = 0x0, + DYNAMIC_DEEP_SLEEP_ENABLE = 0x1, + DYNAMIC_LIGHT_SLEEP_ENABLE = 0x2, +} MEM_PWR_SEL_CTRL; +typedef enum MEM_PWR_SEL_CTRL2 { + DYNAMIC_DEEP_SLEEP_EN = 0x0, + DYNAMIC_LIGHT_SLEEP_EN = 0x1, +} MEM_PWR_SEL_CTRL2; + +#endif /* ACP_2_2_ENUM_H */ diff --git a/sound/soc/amd/include/acp_2_2_sh_mask.h b/sound/soc/amd/include/acp_2_2_sh_mask.h new file mode 100644 index 000000000..9749c11e7 --- /dev/null +++ b/sound/soc/amd/include/acp_2_2_sh_mask.h @@ -0,0 +1,2276 @@ +/* SPDX-License-Identifier: MIT */ +/* + * ACP_2_2 Register documentation + * + * Copyright (C) 2014 Advanced Micro Devices, Inc. + */ + +#ifndef ACP_2_2_SH_MASK_H +#define ACP_2_2_SH_MASK_H + +#define ACP_DMA_CNTL_0__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_0__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_0__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_0__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_0__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_0__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_0__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_0__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_0__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_0__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_1__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_1__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_1__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_1__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_1__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_1__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_1__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_1__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_1__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_1__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_2__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_2__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_2__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_2__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_2__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_2__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_2__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_2__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_2__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_2__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_3__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_3__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_3__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_3__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_3__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_3__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_3__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_3__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_3__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_3__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_4__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_4__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_4__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_4__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_4__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_4__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_4__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_4__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_4__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_4__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_5__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_5__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_5__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_5__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_5__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_5__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_5__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_5__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_5__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_5__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_6__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_6__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_6__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_6__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_6__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_6__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_6__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_6__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_6__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_6__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_7__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_7__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_7__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_7__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_7__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_7__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_7__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_7__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_7__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_7__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_8__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_8__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_8__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_8__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_8__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_8__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_8__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_8__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_8__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_8__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_9__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_9__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_9__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_9__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_9__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_9__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_9__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_9__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_9__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_9__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_10__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_10__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_10__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_10__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_10__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_10__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_10__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_10__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_10__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_10__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_11__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_11__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_11__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_11__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_11__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_11__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_11__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_11__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_11__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_11__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_12__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_12__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_12__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_12__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_12__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_12__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_12__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_12__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_12__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_12__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_13__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_13__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_13__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_13__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_13__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_13__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_13__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_13__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_13__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_13__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_14__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_14__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_14__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_14__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_14__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_14__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_14__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_14__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_14__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_14__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_CNTL_15__DMAChRst_MASK 0x1 +#define ACP_DMA_CNTL_15__DMAChRst__SHIFT 0x0 +#define ACP_DMA_CNTL_15__DMAChRun_MASK 0x2 +#define ACP_DMA_CNTL_15__DMAChRun__SHIFT 0x1 +#define ACP_DMA_CNTL_15__DMAChIOCEn_MASK 0x4 +#define ACP_DMA_CNTL_15__DMAChIOCEn__SHIFT 0x2 +#define ACP_DMA_CNTL_15__Circular_DMA_En_MASK 0x8 +#define ACP_DMA_CNTL_15__Circular_DMA_En__SHIFT 0x3 +#define ACP_DMA_CNTL_15__DMAChGracefulRstEn_MASK 0x10 +#define ACP_DMA_CNTL_15__DMAChGracefulRstEn__SHIFT 0x4 +#define ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_1__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_1__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_2__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_2__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_3__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_3__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_4__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_4__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_5__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_5__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_6__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_6__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_7__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_7__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_8__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_8__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_9__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_9__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_10__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_10__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_11__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_11__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_12__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_12__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_13__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_13__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_14__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_14__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_STRT_IDX_15__DMAChDscrStrtIdx_MASK 0x3ff +#define ACP_DMA_DSCR_STRT_IDX_15__DMAChDscrStrtIdx__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_0__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_0__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_1__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_1__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_2__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_2__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_3__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_3__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_4__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_4__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_5__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_5__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_6__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_6__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_7__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_7__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_8__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_8__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_9__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_9__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_10__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_10__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_11__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_11__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_12__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_12__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_13__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_13__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_14__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_14__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_DSCR_CNT_15__DMAChDscrCnt_MASK 0x3ff +#define ACP_DMA_DSCR_CNT_15__DMAChDscrCnt__SHIFT 0x0 +#define ACP_DMA_PRIO_0__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_0__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_1__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_1__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_2__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_2__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_3__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_3__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_4__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_4__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_5__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_5__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_6__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_6__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_7__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_7__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_8__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_8__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_9__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_9__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_10__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_10__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_11__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_11__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_12__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_12__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_13__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_13__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_14__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_14__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_PRIO_15__DMAChPrioLvl_MASK 0x1 +#define ACP_DMA_PRIO_15__DMAChPrioLvl__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_0__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_0__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_1__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_1__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_2__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_2__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_3__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_3__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_4__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_4__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_5__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_5__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_6__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_6__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_7__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_7__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_8__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_8__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_9__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_9__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_10__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_10__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_11__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_11__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_12__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_12__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_13__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_13__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_14__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_14__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_DSCR_15__DMAChCurDscrIdx_MASK 0x3ff +#define ACP_DMA_CUR_DSCR_15__DMAChCurDscrIdx__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_0__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_0__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_1__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_1__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_2__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_2__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_3__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_3__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_4__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_4__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_5__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_5__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_6__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_6__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_7__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_7__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_8__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_8__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_9__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_9__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_10__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_10__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_11__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_11__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_12__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_12__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_13__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_13__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_14__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_14__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_CUR_TRANS_CNT_15__DMAChCurTransCnt_MASK 0x1ffff +#define ACP_DMA_CUR_TRANS_CNT_15__DMAChCurTransCnt__SHIFT 0x0 +#define ACP_DMA_ERR_STS_0__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_0__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_0__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_0__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_1__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_1__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_1__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_1__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_2__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_2__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_2__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_2__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_3__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_3__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_3__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_3__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_4__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_4__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_4__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_4__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_5__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_5__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_5__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_5__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_6__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_6__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_6__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_6__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_7__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_7__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_7__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_7__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_8__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_8__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_8__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_8__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_9__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_9__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_9__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_9__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_10__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_10__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_10__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_10__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_11__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_11__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_11__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_11__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_12__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_12__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_12__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_12__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_13__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_13__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_13__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_13__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_14__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_14__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_14__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_14__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_ERR_STS_15__DMAChTermErr_MASK 0x1 +#define ACP_DMA_ERR_STS_15__DMAChTermErr__SHIFT 0x0 +#define ACP_DMA_ERR_STS_15__DMAChErrCode_MASK 0x1e +#define ACP_DMA_ERR_STS_15__DMAChErrCode__SHIFT 0x1 +#define ACP_DMA_DESC_BASE_ADDR__DescriptorBaseAddr_MASK 0xffffffff +#define ACP_DMA_DESC_BASE_ADDR__DescriptorBaseAddr__SHIFT 0x0 +#define ACP_DMA_DESC_MAX_NUM_DSCR__MaximumNumberDescr_MASK 0xf +#define ACP_DMA_DESC_MAX_NUM_DSCR__MaximumNumberDescr__SHIFT 0x0 +#define ACP_DMA_CH_STS__DMAChSts_MASK 0xffff +#define ACP_DMA_CH_STS__DMAChSts__SHIFT 0x0 +#define ACP_DMA_CH_GROUP__DMAChanelGrouping_MASK 0x1 +#define ACP_DMA_CH_GROUP__DMAChanelGrouping__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET2__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET2__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE2__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE2__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE2__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE2__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET3__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET3__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE3__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE3__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE3__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE3__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET4__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET4__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE4__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE4__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE4__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE4__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET5__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET5__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE5__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE5__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE5__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE5__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET6__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET6__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE6__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE6__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE6__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE6__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET7__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET7__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE7__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE7__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE7__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE7__PageEnable__SHIFT 0x1f +#define ACP_DSP0_CACHE_OFFSET8__Offset_MASK 0xfffffff +#define ACP_DSP0_CACHE_OFFSET8__Offset__SHIFT 0x0 +#define ACP_DSP0_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_CACHE_SIZE8__Size_MASK 0xffffff +#define ACP_DSP0_CACHE_SIZE8__Size__SHIFT 0x0 +#define ACP_DSP0_CACHE_SIZE8__PageEnable_MASK 0x80000000 +#define ACP_DSP0_CACHE_SIZE8__PageEnable__SHIFT 0x1f +#define ACP_DSP0_NONCACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP0_NONCACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP0_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_NONCACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP0_NONCACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP0_NONCACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP0_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP0_NONCACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP0_NONCACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP0_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP0_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP0_NONCACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP0_NONCACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP0_NONCACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP0_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP0_DEBUG_PC__DebugPC_MASK 0xffffffff +#define ACP_DSP0_DEBUG_PC__DebugPC__SHIFT 0x0 +#define ACP_DSP0_NMI_SEL__NMISel_MASK 0x1 +#define ACP_DSP0_NMI_SEL__NMISel__SHIFT 0x0 +#define ACP_DSP0_CLKRST_CNTL__ClkEn_MASK 0x1 +#define ACP_DSP0_CLKRST_CNTL__ClkEn__SHIFT 0x0 +#define ACP_DSP0_CLKRST_CNTL__SoftResetDSP_MASK 0x2 +#define ACP_DSP0_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1 +#define ACP_DSP0_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4 +#define ACP_DSP0_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2 +#define ACP_DSP0_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8 +#define ACP_DSP0_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3 +#define ACP_DSP0_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10 +#define ACP_DSP0_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4 +#define ACP_DSP0_CLKRST_CNTL__Clk_ON_Status_MASK 0x20 +#define ACP_DSP0_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5 +#define ACP_DSP0_RUNSTALL__RunStallCntl_MASK 0x1 +#define ACP_DSP0_RUNSTALL__RunStallCntl__SHIFT 0x0 +#define ACP_DSP0_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1 +#define ACP_DSP0_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0 +#define ACP_DSP0_WAIT_MODE__WaitMode_MASK 0x1 +#define ACP_DSP0_WAIT_MODE__WaitMode__SHIFT 0x0 +#define ACP_DSP0_VECT_SEL__StaticVectorSel_MASK 0x1 +#define ACP_DSP0_VECT_SEL__StaticVectorSel__SHIFT 0x0 +#define ACP_DSP0_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff +#define ACP_DSP0_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0 +#define ACP_DSP0_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff +#define ACP_DSP0_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0 +#define ACP_DSP0_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff +#define ACP_DSP0_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET2__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET2__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE2__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE2__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE2__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE2__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET3__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET3__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE3__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE3__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE3__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE3__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET4__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET4__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE4__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE4__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE4__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE4__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET5__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET5__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE5__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE5__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE5__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE5__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET6__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET6__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE6__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE6__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE6__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE6__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET7__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET7__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE7__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE7__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE7__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE7__PageEnable__SHIFT 0x1f +#define ACP_DSP1_CACHE_OFFSET8__Offset_MASK 0xfffffff +#define ACP_DSP1_CACHE_OFFSET8__Offset__SHIFT 0x0 +#define ACP_DSP1_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_CACHE_SIZE8__Size_MASK 0xffffff +#define ACP_DSP1_CACHE_SIZE8__Size__SHIFT 0x0 +#define ACP_DSP1_CACHE_SIZE8__PageEnable_MASK 0x80000000 +#define ACP_DSP1_CACHE_SIZE8__PageEnable__SHIFT 0x1f +#define ACP_DSP1_NONCACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP1_NONCACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP1_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_NONCACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP1_NONCACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP1_NONCACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP1_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP1_NONCACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP1_NONCACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP1_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP1_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP1_NONCACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP1_NONCACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP1_NONCACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP1_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP1_DEBUG_PC__DebugPC_MASK 0xffffffff +#define ACP_DSP1_DEBUG_PC__DebugPC__SHIFT 0x0 +#define ACP_DSP1_NMI_SEL__NMISel_MASK 0x1 +#define ACP_DSP1_NMI_SEL__NMISel__SHIFT 0x0 +#define ACP_DSP1_CLKRST_CNTL__ClkEn_MASK 0x1 +#define ACP_DSP1_CLKRST_CNTL__ClkEn__SHIFT 0x0 +#define ACP_DSP1_CLKRST_CNTL__SoftResetDSP_MASK 0x2 +#define ACP_DSP1_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1 +#define ACP_DSP1_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4 +#define ACP_DSP1_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2 +#define ACP_DSP1_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8 +#define ACP_DSP1_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3 +#define ACP_DSP1_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10 +#define ACP_DSP1_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4 +#define ACP_DSP1_CLKRST_CNTL__Clk_ON_Status_MASK 0x20 +#define ACP_DSP1_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5 +#define ACP_DSP1_RUNSTALL__RunStallCntl_MASK 0x1 +#define ACP_DSP1_RUNSTALL__RunStallCntl__SHIFT 0x0 +#define ACP_DSP1_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1 +#define ACP_DSP1_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0 +#define ACP_DSP1_WAIT_MODE__WaitMode_MASK 0x1 +#define ACP_DSP1_WAIT_MODE__WaitMode__SHIFT 0x0 +#define ACP_DSP1_VECT_SEL__StaticVectorSel_MASK 0x1 +#define ACP_DSP1_VECT_SEL__StaticVectorSel__SHIFT 0x0 +#define ACP_DSP1_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff +#define ACP_DSP1_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0 +#define ACP_DSP1_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff +#define ACP_DSP1_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0 +#define ACP_DSP1_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff +#define ACP_DSP1_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET2__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET2__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE2__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE2__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE2__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE2__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET3__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET3__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE3__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE3__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE3__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE3__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET4__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET4__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE4__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE4__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE4__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE4__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET5__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET5__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE5__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE5__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE5__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE5__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET6__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET6__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE6__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE6__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE6__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE6__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET7__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET7__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE7__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE7__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE7__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE7__PageEnable__SHIFT 0x1f +#define ACP_DSP2_CACHE_OFFSET8__Offset_MASK 0xfffffff +#define ACP_DSP2_CACHE_OFFSET8__Offset__SHIFT 0x0 +#define ACP_DSP2_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_CACHE_SIZE8__Size_MASK 0xffffff +#define ACP_DSP2_CACHE_SIZE8__Size__SHIFT 0x0 +#define ACP_DSP2_CACHE_SIZE8__PageEnable_MASK 0x80000000 +#define ACP_DSP2_CACHE_SIZE8__PageEnable__SHIFT 0x1f +#define ACP_DSP2_NONCACHE_OFFSET0__Offset_MASK 0xfffffff +#define ACP_DSP2_NONCACHE_OFFSET0__Offset__SHIFT 0x0 +#define ACP_DSP2_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_NONCACHE_SIZE0__Size_MASK 0xffffff +#define ACP_DSP2_NONCACHE_SIZE0__Size__SHIFT 0x0 +#define ACP_DSP2_NONCACHE_SIZE0__PageEnable_MASK 0x80000000 +#define ACP_DSP2_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f +#define ACP_DSP2_NONCACHE_OFFSET1__Offset_MASK 0xfffffff +#define ACP_DSP2_NONCACHE_OFFSET1__Offset__SHIFT 0x0 +#define ACP_DSP2_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000 +#define ACP_DSP2_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f +#define ACP_DSP2_NONCACHE_SIZE1__Size_MASK 0xffffff +#define ACP_DSP2_NONCACHE_SIZE1__Size__SHIFT 0x0 +#define ACP_DSP2_NONCACHE_SIZE1__PageEnable_MASK 0x80000000 +#define ACP_DSP2_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f +#define ACP_DSP2_DEBUG_PC__DebugPC_MASK 0xffffffff +#define ACP_DSP2_DEBUG_PC__DebugPC__SHIFT 0x0 +#define ACP_DSP2_NMI_SEL__NMISel_MASK 0x1 +#define ACP_DSP2_NMI_SEL__NMISel__SHIFT 0x0 +#define ACP_DSP2_CLKRST_CNTL__ClkEn_MASK 0x1 +#define ACP_DSP2_CLKRST_CNTL__ClkEn__SHIFT 0x0 +#define ACP_DSP2_CLKRST_CNTL__SoftResetDSP_MASK 0x2 +#define ACP_DSP2_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1 +#define ACP_DSP2_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4 +#define ACP_DSP2_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2 +#define ACP_DSP2_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8 +#define ACP_DSP2_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3 +#define ACP_DSP2_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10 +#define ACP_DSP2_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4 +#define ACP_DSP2_CLKRST_CNTL__Clk_ON_Status_MASK 0x20 +#define ACP_DSP2_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5 +#define ACP_DSP2_RUNSTALL__RunStallCntl_MASK 0x1 +#define ACP_DSP2_RUNSTALL__RunStallCntl__SHIFT 0x0 +#define ACP_DSP2_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1 +#define ACP_DSP2_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0 +#define ACP_DSP2_WAIT_MODE__WaitMode_MASK 0x1 +#define ACP_DSP2_WAIT_MODE__WaitMode__SHIFT 0x0 +#define ACP_DSP2_VECT_SEL__StaticVectorSel_MASK 0x1 +#define ACP_DSP2_VECT_SEL__StaticVectorSel__SHIFT 0x0 +#define ACP_DSP2_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff +#define ACP_DSP2_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0 +#define ACP_DSP2_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff +#define ACP_DSP2_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0 +#define ACP_DSP2_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff +#define ACP_DSP2_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBDataSwap_MASK 0x3 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBDataSwap__SHIFT 0x0 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultRdReq_MASK 0x4 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultRdReq__SHIFT 0x2 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultWrReq_MASK 0x18 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultWrReq__SHIFT 0x3 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBMaxReadBurst_MASK 0x60 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBMaxReadBurst__SHIFT 0x5 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallEnb_MASK 0x80 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallEnb__SHIFT 0x7 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBNackChkEnb_MASK 0x100 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBNackChkEnb__SHIFT 0x8 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBAdrWinViolChkEnb_MASK 0x200 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBAdrWinViolChkEnb__SHIFT 0x9 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgEnb_MASK 0x400 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgEnb__SHIFT 0xa +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgCntMult_MASK 0x1800 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgCntMult__SHIFT 0xb +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallMode_MASK 0x2000 +#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallMode__SHIFT 0xd +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver_MASK 0x2000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver__SHIFT 0x19 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource_MASK 0x1c000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource__SHIFT 0x1a +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViol_MASK 0x20000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViol__SHIFT 0x1d +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackOver_MASK 0x40000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackOver__SHIFT 0x1e +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackVal_MASK 0x80000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackVal__SHIFT 0x1f +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver_MASK 0x2000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver__SHIFT 0x19 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource_MASK 0x1c000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource__SHIFT 0x1a +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViol_MASK 0x20000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViol__SHIFT 0x1d +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackOver_MASK 0x40000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackOver__SHIFT 0x1e +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackVal_MASK 0x80000000 +#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackVal__SHIFT 0x1f +#define ACP_DAGB_Onion_TransPerf_Counter_Control__EnbDAGBTransPerfCntr_MASK 0x1 +#define ACP_DAGB_Onion_TransPerf_Counter_Control__EnbDAGBTransPerfCntr__SHIFT 0x0 +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBDataSwap_MASK 0x3 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBDataSwap__SHIFT 0x0 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultRdReq_MASK 0x4 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultRdReq__SHIFT 0x2 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultWrReq_MASK 0x18 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultWrReq__SHIFT 0x3 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBMaxReadBurst_MASK 0x60 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBMaxReadBurst__SHIFT 0x5 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallEnb_MASK 0x80 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallEnb__SHIFT 0x7 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBNackChkEnb_MASK 0x100 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBNackChkEnb__SHIFT 0x8 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBAdrWinViolChkEnb_MASK 0x200 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBAdrWinViolChkEnb__SHIFT 0x9 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgEnb_MASK 0x400 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgEnb__SHIFT 0xa +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgCntMult_MASK 0x1800 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgCntMult__SHIFT 0xb +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallMode_MASK 0x2000 +#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallMode__SHIFT 0xd +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver_MASK 0x2000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver__SHIFT 0x19 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource_MASK 0x1c000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource__SHIFT 0x1a +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViol_MASK 0x20000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViol__SHIFT 0x1d +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackOver_MASK 0x40000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackOver__SHIFT 0x1e +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackVal_MASK 0x80000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackVal__SHIFT 0x1f +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver_MASK 0x2000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver__SHIFT 0x19 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource_MASK 0x1c000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource__SHIFT 0x1a +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViol_MASK 0x20000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViol__SHIFT 0x1d +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackOver_MASK 0x40000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackOver__SHIFT 0x1e +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackVal_MASK 0x80000000 +#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackVal__SHIFT 0x1f +#define ACP_DAGB_Garlic_TransPerf_Counter_Control__EnbDAGBTransPerfCntr_MASK 0x1 +#define ACP_DAGB_Garlic_TransPerf_Counter_Control__EnbDAGBTransPerfCntr__SHIFT 0x0 +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0 +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000 +#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_1__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_1__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_2__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_2__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_3__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_3__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_4__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_4__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_5__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_5__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_6__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_6__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_7__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_7__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_PAGE_SIZE_GRP_8__AXI2DAGBPageSize_MASK 0x3 +#define ACP_DAGB_PAGE_SIZE_GRP_8__AXI2DAGBPageSize__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBBaseAddr_MASK 0xfffffff +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBBaseAddr__SHIFT 0x0 +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBSnoopSel_MASK 0x20000000 +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBSnoopSel__SHIFT 0x1d +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBTargetMemSel_MASK 0x40000000 +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBTargetMemSel__SHIFT 0x1e +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBGrpEnable_MASK 0x80000000 +#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBGrpEnable__SHIFT 0x1f +#define ACP_DAGB_ATU_CTRL__AXI2DAGBCacheInvalidate_MASK 0x1 +#define ACP_DAGB_ATU_CTRL__AXI2DAGBCacheInvalidate__SHIFT 0x0 +#define ACP_CONTROL__ClkEn_MASK 0x1 +#define ACP_CONTROL__ClkEn__SHIFT 0x0 +#define ACP_CONTROL__JtagEn_MASK 0x400 +#define ACP_CONTROL__JtagEn__SHIFT 0xa +#define ACP_STATUS__ClkOn_MASK 0x1 +#define ACP_STATUS__ClkOn__SHIFT 0x0 +#define ACP_STATUS__ACPRefClkSpd_MASK 0x2 +#define ACP_STATUS__ACPRefClkSpd__SHIFT 0x1 +#define ACP_STATUS__SMUStutterLastEdge_MASK 0x4 +#define ACP_STATUS__SMUStutterLastEdge__SHIFT 0x2 +#define ACP_STATUS__MCStutterLastEdge_MASK 0x8 +#define ACP_STATUS__MCStutterLastEdge__SHIFT 0x3 +#define ACP_SOFT_RESET__SoftResetAud_MASK 0x100 +#define ACP_SOFT_RESET__SoftResetAud__SHIFT 0x8 +#define ACP_SOFT_RESET__SoftResetDMA_MASK 0x200 +#define ACP_SOFT_RESET__SoftResetDMA__SHIFT 0x9 +#define ACP_SOFT_RESET__InternalSoftResetMode_MASK 0x4000 +#define ACP_SOFT_RESET__InternalSoftResetMode__SHIFT 0xe +#define ACP_SOFT_RESET__ExternalSoftResetMode_MASK 0x8000 +#define ACP_SOFT_RESET__ExternalSoftResetMode__SHIFT 0xf +#define ACP_SOFT_RESET__SoftResetAudDone_MASK 0x1000000 +#define ACP_SOFT_RESET__SoftResetAudDone__SHIFT 0x18 +#define ACP_SOFT_RESET__SoftResetDMADone_MASK 0x2000000 +#define ACP_SOFT_RESET__SoftResetDMADone__SHIFT 0x19 +#define ACP_PwrMgmt_CNTL__SCLKSleepCntl_MASK 0x3 +#define ACP_PwrMgmt_CNTL__SCLKSleepCntl__SHIFT 0x0 +#define ACP_CAC_INDICATOR_CONTROL__ACP_Cac_Indicator_Counter_MASK 0xffff +#define ACP_CAC_INDICATOR_CONTROL__ACP_Cac_Indicator_Counter__SHIFT 0x0 +#define ACP_SMU_MAILBOX__ACP_SMU_Mailbox_MASK 0xffffffff +#define ACP_SMU_MAILBOX__ACP_SMU_Mailbox__SHIFT 0x0 +#define ACP_FUTURE_REG_SCLK_0__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_SCLK_0__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_SCLK_1__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_SCLK_1__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_SCLK_2__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_SCLK_2__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_SCLK_3__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_SCLK_3__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_SCLK_4__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_SCLK_4__ACPFutureReg__SHIFT 0x0 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_ask_cnt_enable_MASK 0x1 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_ask_cnt_enable__SHIFT 0x0 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_go_cnt_enable_MASK 0x2 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_go_cnt_enable__SHIFT 0x1 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_exp_respcnt_enable_MASK 0x4 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_exp_respcnt_enable__SHIFT 0x2 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_actual_respcnt_enable_MASK 0x8 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_actual_respcnt_enable__SHIFT 0x3 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_ask_cnt_enable_MASK 0x10 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_ask_cnt_enable__SHIFT 0x4 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_go_cnt_enable_MASK 0x20 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_go_cnt_enable__SHIFT 0x5 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_exp_respcnt_enable_MASK 0x40 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_exp_respcnt_enable__SHIFT 0x6 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_actual_respcnt_enable_MASK 0x80 +#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_actual_respcnt_enable__SHIFT 0x7 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_ask_cnt_enable_MASK 0x100 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_ask_cnt_enable__SHIFT 0x8 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_go_cnt_enable_MASK 0x200 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_go_cnt_enable__SHIFT 0x9 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_exp_respcnt_enable_MASK 0x400 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_exp_respcnt_enable__SHIFT 0xa +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_actual_respcnt_enable_MASK 0x800 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_actual_respcnt_enable__SHIFT 0xb +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_ask_cnt_enable_MASK 0x1000 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_ask_cnt_enable__SHIFT 0xc +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_go_cnt_enable_MASK 0x2000 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_go_cnt_enable__SHIFT 0xd +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_exp_respcnt_enable_MASK 0x4000 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_exp_respcnt_enable__SHIFT 0xe +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_actual_respcnt_enable_MASK 0x8000 +#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_actual_respcnt_enable__SHIFT 0xf +#define ACP_DAGBG_WR_ASK_CNT__garlic_wr_only_ask_cnt_MASK 0xffff +#define ACP_DAGBG_WR_ASK_CNT__garlic_wr_only_ask_cnt__SHIFT 0x0 +#define ACP_DAGBG_WR_GO_CNT__garlic_wr_only_go_cnt_MASK 0xffff +#define ACP_DAGBG_WR_GO_CNT__garlic_wr_only_go_cnt__SHIFT 0x0 +#define ACP_DAGBG_WR_EXP_RESP_CNT__garlic_wr_exp_resp_cnt_MASK 0xffff +#define ACP_DAGBG_WR_EXP_RESP_CNT__garlic_wr_exp_resp_cnt__SHIFT 0x0 +#define ACP_DAGBG_WR_ACTUAL_RESP_CNT__garlic_wr_actual_resp_cnt_MASK 0xffff +#define ACP_DAGBG_WR_ACTUAL_RESP_CNT__garlic_wr_actual_resp_cnt__SHIFT 0x0 +#define ACP_DAGBG_RD_ASK_CNT__garlic_rd_only_ask_cnt_MASK 0xffff +#define ACP_DAGBG_RD_ASK_CNT__garlic_rd_only_ask_cnt__SHIFT 0x0 +#define ACP_DAGBG_RD_GO_CNT__garlic_rd_only_go_cnt_MASK 0xffff +#define ACP_DAGBG_RD_GO_CNT__garlic_rd_only_go_cnt__SHIFT 0x0 +#define ACP_DAGBG_RD_EXP_RESP_CNT__garlic_rd_exp_resp_cnt_MASK 0xffff +#define ACP_DAGBG_RD_EXP_RESP_CNT__garlic_rd_exp_resp_cnt__SHIFT 0x0 +#define ACP_DAGBG_RD_ACTUAL_RESP_CNT__garlic_rd_actual_resp_cnt_MASK 0xffff +#define ACP_DAGBG_RD_ACTUAL_RESP_CNT__garlic_rd_actual_resp_cnt__SHIFT 0x0 +#define ACP_DAGBO_WR_ASK_CNT__onion_wr_only_ask_cnt_MASK 0xffff +#define ACP_DAGBO_WR_ASK_CNT__onion_wr_only_ask_cnt__SHIFT 0x0 +#define ACP_DAGBO_WR_GO_CNT__onion_wr_only_go_cnt_MASK 0xffff +#define ACP_DAGBO_WR_GO_CNT__onion_wr_only_go_cnt__SHIFT 0x0 +#define ACP_DAGBO_WR_EXP_RESP_CNT__onion_wr_exp_resp_cnt_MASK 0xffff +#define ACP_DAGBO_WR_EXP_RESP_CNT__onion_wr_exp_resp_cnt__SHIFT 0x0 +#define ACP_DAGBO_WR_ACTUAL_RESP_CNT__onion_wr_actual_resp_cnt_MASK 0xffff +#define ACP_DAGBO_WR_ACTUAL_RESP_CNT__onion_wr_actual_resp_cnt__SHIFT 0x0 +#define ACP_DAGBO_RD_ASK_CNT__onion_rd_only_ask_cnt_MASK 0xffff +#define ACP_DAGBO_RD_ASK_CNT__onion_rd_only_ask_cnt__SHIFT 0x0 +#define ACP_DAGBO_RD_GO_CNT__onion_rd_only_go_cnt_MASK 0xffff +#define ACP_DAGBO_RD_GO_CNT__onion_rd_only_go_cnt__SHIFT 0x0 +#define ACP_DAGBO_RD_EXP_RESP_CNT__onion_rd_exp_resp_cnt_MASK 0xffff +#define ACP_DAGBO_RD_EXP_RESP_CNT__onion_rd_exp_resp_cnt__SHIFT 0x0 +#define ACP_DAGBO_RD_ACTUAL_RESP_CNT__onion_rd_actual_resp_cnt_MASK 0xffff +#define ACP_DAGBO_RD_ACTUAL_RESP_CNT__onion_rd_actual_resp_cnt__SHIFT 0x0 +#define ACP_BRB_CONTROL__BRB_BlockSharedRAMArbCntrl_MASK 0xf +#define ACP_BRB_CONTROL__BRB_BlockSharedRAMArbCntrl__SHIFT 0x0 +#define ACP_EXTERNAL_INTR_ENB__ACPExtIntrEnb_MASK 0x1 +#define ACP_EXTERNAL_INTR_ENB__ACPExtIntrEnb__SHIFT 0x0 +#define ACP_EXTERNAL_INTR_CNTL__ACPErrMask_MASK 0x1 +#define ACP_EXTERNAL_INTR_CNTL__ACPErrMask__SHIFT 0x0 +#define ACP_EXTERNAL_INTR_CNTL__I2SMicDataAvMask_MASK 0x2 +#define ACP_EXTERNAL_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1 +#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4 +#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2 +#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8 +#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3 +#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataAvMask_MASK 0x10 +#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4 +#define ACP_EXTERNAL_INTR_CNTL__AzaliaIntrMask_MASK 0x40 +#define ACP_EXTERNAL_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6 +#define ACP_EXTERNAL_INTR_CNTL__DSP0TimeoutMask_MASK 0x100 +#define ACP_EXTERNAL_INTR_CNTL__DSP0TimeoutMask__SHIFT 0x8 +#define ACP_EXTERNAL_INTR_CNTL__DSP1TimeoutMask_MASK 0x200 +#define ACP_EXTERNAL_INTR_CNTL__DSP1TimeoutMask__SHIFT 0x9 +#define ACP_EXTERNAL_INTR_CNTL__DSP2TimeoutMask_MASK 0x400 +#define ACP_EXTERNAL_INTR_CNTL__DSP2TimeoutMask__SHIFT 0xa +#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x800 +#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xb +#define ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK 0xffff0000 +#define ACP_EXTERNAL_INTR_CNTL__DMAIOCMask__SHIFT 0x10 +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErr_MASK 0x1 +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErr__SHIFT 0x0 +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSource_MASK 0xe +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSource__SHIFT 0x1 +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSourceOver_MASK 0x10 +#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSourceOver__SHIFT 0x4 +#define ACP_ERROR_SOURCE_STS__BRBAddrErr_MASK 0x20 +#define ACP_ERROR_SOURCE_STS__BRBAddrErr__SHIFT 0x5 +#define ACP_ERROR_SOURCE_STS__BRBAddrErrSource_MASK 0x3c0 +#define ACP_ERROR_SOURCE_STS__BRBAddrErrSource__SHIFT 0x6 +#define ACP_ERROR_SOURCE_STS__BRBAddrErrSourceOver_MASK 0x400 +#define ACP_ERROR_SOURCE_STS__BRBAddrErrSourceOver__SHIFT 0xa +#define ACP_ERROR_SOURCE_STS__I2SMicOverFlowErr_MASK 0x800 +#define ACP_ERROR_SOURCE_STS__I2SMicOverFlowErr__SHIFT 0xb +#define ACP_ERROR_SOURCE_STS__I2SSpeaker0OverFlowErr_MASK 0x1000 +#define ACP_ERROR_SOURCE_STS__I2SSpeaker0OverFlowErr__SHIFT 0xc +#define ACP_ERROR_SOURCE_STS__I2SSpeaker1OverFlowErr_MASK 0x2000 +#define ACP_ERROR_SOURCE_STS__I2SSpeaker1OverFlowErr__SHIFT 0xd +#define ACP_ERROR_SOURCE_STS__I2SBTRxFifoOverFlowErr_MASK 0x4000 +#define ACP_ERROR_SOURCE_STS__I2SBTRxFifoOverFlowErr__SHIFT 0xe +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErr_MASK 0x8000 +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErr__SHIFT 0xf +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSource_MASK 0x70000 +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSource__SHIFT 0x10 +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSourceOver_MASK 0x80000 +#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSourceOver__SHIFT 0x13 +#define ACP_ERROR_SOURCE_STS__DAGBErr_MASK 0x100000 +#define ACP_ERROR_SOURCE_STS__DAGBErr__SHIFT 0x14 +#define ACP_ERROR_SOURCE_STS__DAGBErrSource_MASK 0x1e00000 +#define ACP_ERROR_SOURCE_STS__DAGBErrSource__SHIFT 0x15 +#define ACP_ERROR_SOURCE_STS__DAGBErrSourceOver_MASK 0x2000000 +#define ACP_ERROR_SOURCE_STS__DAGBErrSourceOver__SHIFT 0x19 +#define ACP_ERROR_SOURCE_STS__DMATermOnErr_MASK 0x4000000 +#define ACP_ERROR_SOURCE_STS__DMATermOnErr__SHIFT 0x1a +#define ACP_ERROR_SOURCE_STS__I2SBTTxFifoOverFlowErr_MASK 0x10000000 +#define ACP_ERROR_SOURCE_STS__I2SBTTxFifoOverFlowErr__SHIFT 0x1c +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP0_MASK 0x1 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP0__SHIFT 0x0 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP1_MASK 0x2 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP1__SHIFT 0x1 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP2_MASK 0x4 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP2__SHIFT 0x2 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP0_MASK 0x100 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP0__SHIFT 0x8 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP1_MASK 0x200 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP1__SHIFT 0x9 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP2_MASK 0x400 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP2__SHIFT 0xa +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP0Host_MASK 0x10000 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP0Host__SHIFT 0x10 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP1Host_MASK 0x20000 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP1Host__SHIFT 0x11 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP2Host_MASK 0x40000 +#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP2Host__SHIFT 0x12 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP0_MASK 0x1 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP0__SHIFT 0x0 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP1_MASK 0x2 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP1__SHIFT 0x1 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP2_MASK 0x4 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP2__SHIFT 0x2 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP0_MASK 0x100 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP0__SHIFT 0x8 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP1_MASK 0x200 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP1__SHIFT 0x9 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP2_MASK 0x400 +#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP2__SHIFT 0xa +#define ACP_DSP_SW_INTR_CNTL__EnbKernelIntrDSP0Mask_MASK 0x10000 +#define ACP_DSP_SW_INTR_CNTL__EnbKernelIntrDSP0Mask__SHIFT 0x10 +#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP1Mask_MASK 0x20000 +#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP1Mask__SHIFT 0x11 +#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP2Mask_MASK 0x40000 +#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP2Mask__SHIFT 0x12 +#define ACP_DAGBG_TIMEOUT_CNTL__DAGBGTimeoutValue_MASK 0x3ffff +#define ACP_DAGBG_TIMEOUT_CNTL__DAGBGTimeoutValue__SHIFT 0x0 +#define ACP_DAGBG_TIMEOUT_CNTL__CntEn_MASK 0x80000000 +#define ACP_DAGBG_TIMEOUT_CNTL__CntEn__SHIFT 0x1f +#define ACP_DAGBO_TIMEOUT_CNTL__DAGBOTimeoutValue_MASK 0x3ffff +#define ACP_DAGBO_TIMEOUT_CNTL__DAGBOTimeoutValue__SHIFT 0x0 +#define ACP_DAGBO_TIMEOUT_CNTL__CntEn_MASK 0x80000000 +#define ACP_DAGBO_TIMEOUT_CNTL__CntEn__SHIFT 0x1f +#define ACP_EXTERNAL_INTR_STAT__ACPErrStat_MASK 0x1 +#define ACP_EXTERNAL_INTR_STAT__ACPErrStat__SHIFT 0x0 +#define ACP_EXTERNAL_INTR_STAT__ACPErrAck_MASK 0x1 +#define ACP_EXTERNAL_INTR_STAT__ACPErrAck__SHIFT 0x0 +#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvStat_MASK 0x2 +#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1 +#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvAck_MASK 0x2 +#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8 +#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvStat_MASK 0x10 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvAck_MASK 0x10 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4 +#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrStat_MASK 0x40 +#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrStat__SHIFT 0x6 +#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrAck_MASK 0x40 +#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrAck__SHIFT 0x6 +#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutStat_MASK 0x100 +#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutStat__SHIFT 0x8 +#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutAck_MASK 0x100 +#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutAck__SHIFT 0x8 +#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutStat_MASK 0x200 +#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutStat__SHIFT 0x9 +#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutAck_MASK 0x200 +#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutAck__SHIFT 0x9 +#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutStat_MASK 0x400 +#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutStat__SHIFT 0xa +#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutAck_MASK 0x400 +#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutAck__SHIFT 0xa +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyStat_MASK 0x800 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xb +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyAck_MASK 0x800 +#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xb +#define ACP_EXTERNAL_INTR_STAT__DMAIOCStat_MASK 0xffff0000 +#define ACP_EXTERNAL_INTR_STAT__DMAIOCStat__SHIFT 0x10 +#define ACP_EXTERNAL_INTR_STAT__DMAIOCAck_MASK 0xffff0000 +#define ACP_EXTERNAL_INTR_STAT__DMAIOCAck__SHIFT 0x10 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Stat_MASK 0x1 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Stat__SHIFT 0x0 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Ack_MASK 0x1 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Ack__SHIFT 0x0 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Stat_MASK 0x2 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Stat__SHIFT 0x1 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Ack_MASK 0x2 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Ack__SHIFT 0x1 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Stat_MASK 0x4 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Stat__SHIFT 0x2 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Ack_MASK 0x4 +#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Ack__SHIFT 0x2 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Stat_MASK 0x100 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Stat__SHIFT 0x8 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Ack_MASK 0x100 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Ack__SHIFT 0x8 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Stat_MASK 0x200 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Stat__SHIFT 0x9 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Ack_MASK 0x200 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Ack__SHIFT 0x9 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Stat_MASK 0x400 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Stat__SHIFT 0xa +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Ack_MASK 0x400 +#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Ack__SHIFT 0xa +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Stat_MASK 0x10000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Stat__SHIFT 0x10 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Ack_MASK 0x10000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Ack__SHIFT 0x10 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Stat_MASK 0x20000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Stat__SHIFT 0x11 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Ack_MASK 0x20000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Ack__SHIFT 0x11 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Stat_MASK 0x40000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Stat__SHIFT 0x12 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Ack_MASK 0x40000 +#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Ack__SHIFT 0x12 +#define ACP_DSP0_INTR_CNTL__ACPErrMask_MASK 0x1 +#define ACP_DSP0_INTR_CNTL__ACPErrMask__SHIFT 0x0 +#define ACP_DSP0_INTR_CNTL__I2SMicDataAvMask_MASK 0x2 +#define ACP_DSP0_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1 +#define ACP_DSP0_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4 +#define ACP_DSP0_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2 +#define ACP_DSP0_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8 +#define ACP_DSP0_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3 +#define ACP_DSP0_INTR_CNTL__I2SBTDataAvMask_MASK 0x10 +#define ACP_DSP0_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4 +#define ACP_DSP0_INTR_CNTL__AzaliaIntrMask_MASK 0x40 +#define ACP_DSP0_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6 +#define ACP_DSP0_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100 +#define ACP_DSP0_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8 +#define ACP_DSP0_INTR_CNTL__SMUStutterStatusMask_MASK 0x200 +#define ACP_DSP0_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9 +#define ACP_DSP0_INTR_CNTL__MCStutterStatusMask_MASK 0x400 +#define ACP_DSP0_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa +#define ACP_DSP0_INTR_CNTL__DSPExtTimerMask_MASK 0x800 +#define ACP_DSP0_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb +#define ACP_DSP0_INTR_CNTL__DSPSemRespMask_MASK 0x1000 +#define ACP_DSP0_INTR_CNTL__DSPSemRespMask__SHIFT 0xc +#define ACP_DSP0_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000 +#define ACP_DSP0_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd +#define ACP_DSP0_INTR_CNTL__DMAIOCMask_MASK 0xffff0000 +#define ACP_DSP0_INTR_CNTL__DMAIOCMask__SHIFT 0x10 +#define ACP_DSP0_INTR_STAT__ACPErrStat_MASK 0x1 +#define ACP_DSP0_INTR_STAT__ACPErrStat__SHIFT 0x0 +#define ACP_DSP0_INTR_STAT__ACPErrAck_MASK 0x1 +#define ACP_DSP0_INTR_STAT__ACPErrAck__SHIFT 0x0 +#define ACP_DSP0_INTR_STAT__I2SMicDataAvStat_MASK 0x2 +#define ACP_DSP0_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1 +#define ACP_DSP0_INTR_STAT__I2SMicDataAvAck_MASK 0x2 +#define ACP_DSP0_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1 +#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4 +#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2 +#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4 +#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2 +#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8 +#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3 +#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8 +#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3 +#define ACP_DSP0_INTR_STAT__I2SBTDataAvStat_MASK 0x10 +#define ACP_DSP0_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4 +#define ACP_DSP0_INTR_STAT__I2SBTDataAvAck_MASK 0x10 +#define ACP_DSP0_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4 +#define ACP_DSP0_INTR_STAT__AzaliaIntrStat_MASK 0x40 +#define ACP_DSP0_INTR_STAT__AzaliaIntrStat__SHIFT 0x6 +#define ACP_DSP0_INTR_STAT__AzaliaIntrAck_MASK 0x40 +#define ACP_DSP0_INTR_STAT__AzaliaIntrAck__SHIFT 0x6 +#define ACP_DSP0_INTR_STAT__SMUMailboxWriteStat_MASK 0x100 +#define ACP_DSP0_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8 +#define ACP_DSP0_INTR_STAT__SMUMailboxWriteAck_MASK 0x100 +#define ACP_DSP0_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8 +#define ACP_DSP0_INTR_STAT__SMUStutterStatusStat_MASK 0x200 +#define ACP_DSP0_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9 +#define ACP_DSP0_INTR_STAT__SMUStutterStatusAck_MASK 0x200 +#define ACP_DSP0_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9 +#define ACP_DSP0_INTR_STAT__MCStutterStatusStat_MASK 0x400 +#define ACP_DSP0_INTR_STAT__MCStutterStatusStat__SHIFT 0xa +#define ACP_DSP0_INTR_STAT__MCStutterStatusAck_MASK 0x400 +#define ACP_DSP0_INTR_STAT__MCStutterStatusAck__SHIFT 0xa +#define ACP_DSP0_INTR_STAT__DSPExtTimerStat_MASK 0x800 +#define ACP_DSP0_INTR_STAT__DSPExtTimerStat__SHIFT 0xb +#define ACP_DSP0_INTR_STAT__DSPExtTimerAck_MASK 0x800 +#define ACP_DSP0_INTR_STAT__DSPExtTimerAck__SHIFT 0xb +#define ACP_DSP0_INTR_STAT__DSPSemRespStat_MASK 0x1000 +#define ACP_DSP0_INTR_STAT__DSPSemRespStat__SHIFT 0xc +#define ACP_DSP0_INTR_STAT__DSPSemRespAck_MASK 0x1000 +#define ACP_DSP0_INTR_STAT__DSPSemRespAck__SHIFT 0xc +#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000 +#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd +#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000 +#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd +#define ACP_DSP0_INTR_STAT__DMAIOCStat_MASK 0xffff0000 +#define ACP_DSP0_INTR_STAT__DMAIOCStat__SHIFT 0x10 +#define ACP_DSP0_INTR_STAT__DMAIOCAck_MASK 0xffff0000 +#define ACP_DSP0_INTR_STAT__DMAIOCAck__SHIFT 0x10 +#define ACP_DSP0_TIMEOUT_CNTL__DSP0TimeoutValue_MASK 0x3ffff +#define ACP_DSP0_TIMEOUT_CNTL__DSP0TimeoutValue__SHIFT 0x0 +#define ACP_DSP0_TIMEOUT_CNTL__CntEn_MASK 0x80000000 +#define ACP_DSP0_TIMEOUT_CNTL__CntEn__SHIFT 0x1f +#define ACP_DSP1_INTR_CNTL__ACPErrMask_MASK 0x1 +#define ACP_DSP1_INTR_CNTL__ACPErrMask__SHIFT 0x0 +#define ACP_DSP1_INTR_CNTL__I2SMicDataAvMask_MASK 0x2 +#define ACP_DSP1_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1 +#define ACP_DSP1_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4 +#define ACP_DSP1_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2 +#define ACP_DSP1_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8 +#define ACP_DSP1_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3 +#define ACP_DSP1_INTR_CNTL__I2SBTDataAvMask_MASK 0x10 +#define ACP_DSP1_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4 +#define ACP_DSP1_INTR_CNTL__AzaliaIntrMask_MASK 0x40 +#define ACP_DSP1_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6 +#define ACP_DSP1_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100 +#define ACP_DSP1_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8 +#define ACP_DSP1_INTR_CNTL__SMUStutterStatusMask_MASK 0x200 +#define ACP_DSP1_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9 +#define ACP_DSP1_INTR_CNTL__MCStutterStatusMask_MASK 0x400 +#define ACP_DSP1_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa +#define ACP_DSP1_INTR_CNTL__DSPExtTimerMask_MASK 0x800 +#define ACP_DSP1_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb +#define ACP_DSP1_INTR_CNTL__DSPSemRespMask_MASK 0x1000 +#define ACP_DSP1_INTR_CNTL__DSPSemRespMask__SHIFT 0xc +#define ACP_DSP1_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000 +#define ACP_DSP1_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd +#define ACP_DSP1_INTR_CNTL__DMAIOCMask_MASK 0xffff0000 +#define ACP_DSP1_INTR_CNTL__DMAIOCMask__SHIFT 0x10 +#define ACP_DSP1_INTR_STAT__ACPErrStat_MASK 0x1 +#define ACP_DSP1_INTR_STAT__ACPErrStat__SHIFT 0x0 +#define ACP_DSP1_INTR_STAT__ACPErrAck_MASK 0x1 +#define ACP_DSP1_INTR_STAT__ACPErrAck__SHIFT 0x0 +#define ACP_DSP1_INTR_STAT__I2SMicDataAvStat_MASK 0x2 +#define ACP_DSP1_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1 +#define ACP_DSP1_INTR_STAT__I2SMicDataAvAck_MASK 0x2 +#define ACP_DSP1_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1 +#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4 +#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2 +#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4 +#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2 +#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8 +#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3 +#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8 +#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3 +#define ACP_DSP1_INTR_STAT__I2SBTDataAvStat_MASK 0x10 +#define ACP_DSP1_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4 +#define ACP_DSP1_INTR_STAT__I2SBTDataAvAck_MASK 0x10 +#define ACP_DSP1_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4 +#define ACP_DSP1_INTR_STAT__AzaliaIntrStat_MASK 0x40 +#define ACP_DSP1_INTR_STAT__AzaliaIntrStat__SHIFT 0x6 +#define ACP_DSP1_INTR_STAT__AzaliaIntrAck_MASK 0x40 +#define ACP_DSP1_INTR_STAT__AzaliaIntrAck__SHIFT 0x6 +#define ACP_DSP1_INTR_STAT__SMUMailboxWriteStat_MASK 0x100 +#define ACP_DSP1_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8 +#define ACP_DSP1_INTR_STAT__SMUMailboxWriteAck_MASK 0x100 +#define ACP_DSP1_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8 +#define ACP_DSP1_INTR_STAT__SMUStutterStatusStat_MASK 0x200 +#define ACP_DSP1_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9 +#define ACP_DSP1_INTR_STAT__SMUStutterStatusAck_MASK 0x200 +#define ACP_DSP1_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9 +#define ACP_DSP1_INTR_STAT__MCStutterStatusStat_MASK 0x400 +#define ACP_DSP1_INTR_STAT__MCStutterStatusStat__SHIFT 0xa +#define ACP_DSP1_INTR_STAT__MCStutterStatusAck_MASK 0x400 +#define ACP_DSP1_INTR_STAT__MCStutterStatusAck__SHIFT 0xa +#define ACP_DSP1_INTR_STAT__DSPExtTimerStat_MASK 0x800 +#define ACP_DSP1_INTR_STAT__DSPExtTimerStat__SHIFT 0xb +#define ACP_DSP1_INTR_STAT__DSPExtTimerAck_MASK 0x800 +#define ACP_DSP1_INTR_STAT__DSPExtTimerAck__SHIFT 0xb +#define ACP_DSP1_INTR_STAT__DSPSemRespStat_MASK 0x1000 +#define ACP_DSP1_INTR_STAT__DSPSemRespStat__SHIFT 0xc +#define ACP_DSP1_INTR_STAT__DSPSemRespAck_MASK 0x1000 +#define ACP_DSP1_INTR_STAT__DSPSemRespAck__SHIFT 0xc +#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000 +#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd +#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000 +#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd +#define ACP_DSP1_INTR_STAT__DMAIOCStat_MASK 0xffff0000 +#define ACP_DSP1_INTR_STAT__DMAIOCStat__SHIFT 0x10 +#define ACP_DSP1_INTR_STAT__DMAIOCAck_MASK 0xffff0000 +#define ACP_DSP1_INTR_STAT__DMAIOCAck__SHIFT 0x10 +#define ACP_DSP1_TIMEOUT_CNTL__DSP1TimeoutValue_MASK 0x3ffff +#define ACP_DSP1_TIMEOUT_CNTL__DSP1TimeoutValue__SHIFT 0x0 +#define ACP_DSP1_TIMEOUT_CNTL__CntEn_MASK 0x80000000 +#define ACP_DSP1_TIMEOUT_CNTL__CntEn__SHIFT 0x1f +#define ACP_DSP2_INTR_CNTL__ACPErrMask_MASK 0x1 +#define ACP_DSP2_INTR_CNTL__ACPErrMask__SHIFT 0x0 +#define ACP_DSP2_INTR_CNTL__I2SMicDataAvMask_MASK 0x2 +#define ACP_DSP2_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1 +#define ACP_DSP2_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4 +#define ACP_DSP2_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2 +#define ACP_DSP2_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8 +#define ACP_DSP2_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3 +#define ACP_DSP2_INTR_CNTL__I2SBTDataAvMask_MASK 0x10 +#define ACP_DSP2_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4 +#define ACP_DSP2_INTR_CNTL__AzaliaIntrMask_MASK 0x40 +#define ACP_DSP2_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6 +#define ACP_DSP2_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100 +#define ACP_DSP2_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8 +#define ACP_DSP2_INTR_CNTL__SMUStutterStatusMask_MASK 0x200 +#define ACP_DSP2_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9 +#define ACP_DSP2_INTR_CNTL__MCStutterStatusMask_MASK 0x400 +#define ACP_DSP2_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa +#define ACP_DSP2_INTR_CNTL__DSPExtTimerMask_MASK 0x800 +#define ACP_DSP2_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb +#define ACP_DSP2_INTR_CNTL__DSPSemRespMask_MASK 0x1000 +#define ACP_DSP2_INTR_CNTL__DSPSemRespMask__SHIFT 0xc +#define ACP_DSP2_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000 +#define ACP_DSP2_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd +#define ACP_DSP2_INTR_CNTL__DMAIOCMask_MASK 0xffff0000 +#define ACP_DSP2_INTR_CNTL__DMAIOCMask__SHIFT 0x10 +#define ACP_DSP2_INTR_STAT__ACPErrStat_MASK 0x1 +#define ACP_DSP2_INTR_STAT__ACPErrStat__SHIFT 0x0 +#define ACP_DSP2_INTR_STAT__ACPErrAck_MASK 0x1 +#define ACP_DSP2_INTR_STAT__ACPErrAck__SHIFT 0x0 +#define ACP_DSP2_INTR_STAT__I2SMicDataAvStat_MASK 0x2 +#define ACP_DSP2_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1 +#define ACP_DSP2_INTR_STAT__I2SMicDataAvAck_MASK 0x2 +#define ACP_DSP2_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1 +#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4 +#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2 +#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4 +#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2 +#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8 +#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3 +#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8 +#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3 +#define ACP_DSP2_INTR_STAT__I2SBTDataAvStat_MASK 0x10 +#define ACP_DSP2_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4 +#define ACP_DSP2_INTR_STAT__I2SBTDataAvAck_MASK 0x10 +#define ACP_DSP2_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4 +#define ACP_DSP2_INTR_STAT__AzaliaIntrStat_MASK 0x40 +#define ACP_DSP2_INTR_STAT__AzaliaIntrStat__SHIFT 0x6 +#define ACP_DSP2_INTR_STAT__AzaliaIntrAck_MASK 0x40 +#define ACP_DSP2_INTR_STAT__AzaliaIntrAck__SHIFT 0x6 +#define ACP_DSP2_INTR_STAT__SMUMailboxWriteStat_MASK 0x100 +#define ACP_DSP2_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8 +#define ACP_DSP2_INTR_STAT__SMUMailboxWriteAck_MASK 0x100 +#define ACP_DSP2_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8 +#define ACP_DSP2_INTR_STAT__SMUStutterStatusStat_MASK 0x200 +#define ACP_DSP2_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9 +#define ACP_DSP2_INTR_STAT__SMUStutterStatusAck_MASK 0x200 +#define ACP_DSP2_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9 +#define ACP_DSP2_INTR_STAT__MCStutterStatusStat_MASK 0x400 +#define ACP_DSP2_INTR_STAT__MCStutterStatusStat__SHIFT 0xa +#define ACP_DSP2_INTR_STAT__MCStutterStatusAck_MASK 0x400 +#define ACP_DSP2_INTR_STAT__MCStutterStatusAck__SHIFT 0xa +#define ACP_DSP2_INTR_STAT__DSPExtTimerStat_MASK 0x800 +#define ACP_DSP2_INTR_STAT__DSPExtTimerStat__SHIFT 0xb +#define ACP_DSP2_INTR_STAT__DSPExtTimerAck_MASK 0x800 +#define ACP_DSP2_INTR_STAT__DSPExtTimerAck__SHIFT 0xb +#define ACP_DSP2_INTR_STAT__DSPSemRespStat_MASK 0x1000 +#define ACP_DSP2_INTR_STAT__DSPSemRespStat__SHIFT 0xc +#define ACP_DSP2_INTR_STAT__DSPSemRespAck_MASK 0x1000 +#define ACP_DSP2_INTR_STAT__DSPSemRespAck__SHIFT 0xc +#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000 +#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd +#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000 +#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd +#define ACP_DSP2_INTR_STAT__DMAIOCStat_MASK 0xffff0000 +#define ACP_DSP2_INTR_STAT__DMAIOCStat__SHIFT 0x10 +#define ACP_DSP2_INTR_STAT__DMAIOCAck_MASK 0xffff0000 +#define ACP_DSP2_INTR_STAT__DMAIOCAck__SHIFT 0x10 +#define ACP_DSP2_TIMEOUT_CNTL__DSP2TimeoutValue_MASK 0x3ffff +#define ACP_DSP2_TIMEOUT_CNTL__DSP2TimeoutValue__SHIFT 0x0 +#define ACP_DSP2_TIMEOUT_CNTL__CntEn_MASK 0x80000000 +#define ACP_DSP2_TIMEOUT_CNTL__CntEn__SHIFT 0x1f +#define ACP_DSP0_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff +#define ACP_DSP0_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0 +#define ACP_DSP0_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000 +#define ACP_DSP0_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e +#define ACP_DSP1_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff +#define ACP_DSP1_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0 +#define ACP_DSP1_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000 +#define ACP_DSP1_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e +#define ACP_DSP2_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff +#define ACP_DSP2_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0 +#define ACP_DSP2_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000 +#define ACP_DSP2_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e +#define ACP_AXI2DAGB_SEM_0__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_0__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_1__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_1__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_2__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_2__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_3__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_3__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_4__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_4__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_5__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_5__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_6__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_6__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_7__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_7__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_8__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_8__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_9__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_9__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_10__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_10__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_11__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_11__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_12__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_12__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_13__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_13__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_14__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_14__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_15__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_15__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_16__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_16__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_17__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_17__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_18__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_18__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_19__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_19__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_20__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_20__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_21__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_21__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_22__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_22__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_23__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_23__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_24__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_24__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_25__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_25__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_26__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_26__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_27__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_27__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_28__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_28__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_29__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_29__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_30__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_30__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_31__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_31__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_32__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_32__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_33__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_33__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_34__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_34__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_35__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_35__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_36__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_36__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_37__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_37__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_38__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_38__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_39__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_39__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_40__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_40__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_41__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_41__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_42__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_42__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_43__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_43__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_44__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_44__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_45__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_45__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_46__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_46__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_AXI2DAGB_SEM_47__AXI2DAGBGblSemReg_MASK 0x1 +#define ACP_AXI2DAGB_SEM_47__AXI2DAGBGblSemReg__SHIFT 0x0 +#define ACP_SRBM_Client_Base_Addr__SRBM_Client_base_addr_MASK 0xff +#define ACP_SRBM_Client_Base_Addr__SRBM_Client_base_addr__SHIFT 0x0 +#define ACP_SRBM_Client_RDDATA__ReadData_MASK 0xffffffff +#define ACP_SRBM_Client_RDDATA__ReadData__SHIFT 0x0 +#define ACP_SRBM_Cycle_Sts__SRBM_Client_Sts_MASK 0x1 +#define ACP_SRBM_Cycle_Sts__SRBM_Client_Sts__SHIFT 0x0 +#define ACP_SRBM_Targ_Idx_Addr__SRBM_Targ_Idx_addr_MASK 0x7ffffff +#define ACP_SRBM_Targ_Idx_Addr__SRBM_Targ_Idx_addr__SHIFT 0x0 +#define ACP_SRBM_Targ_Idx_Data__SRBM_Targ_Idx_Data_MASK 0xffffffff +#define ACP_SRBM_Targ_Idx_Data__SRBM_Targ_Idx_Data__SHIFT 0x0 +#define ACP_SEMA_ADDR_LOW__ADDR_9_3_MASK 0x7f +#define ACP_SEMA_ADDR_LOW__ADDR_9_3__SHIFT 0x0 +#define ACP_SEMA_ADDR_HIGH__ADDR_39_10_MASK 0x3fffffff +#define ACP_SEMA_ADDR_HIGH__ADDR_39_10__SHIFT 0x0 +#define ACP_SEMA_CMD__REQ_CMD_MASK 0xf +#define ACP_SEMA_CMD__REQ_CMD__SHIFT 0x0 +#define ACP_SEMA_CMD__WR_PHASE_MASK 0x30 +#define ACP_SEMA_CMD__WR_PHASE__SHIFT 0x4 +#define ACP_SEMA_CMD__VMID_EN_MASK 0x80 +#define ACP_SEMA_CMD__VMID_EN__SHIFT 0x7 +#define ACP_SEMA_CMD__VMID_MASK 0xf00 +#define ACP_SEMA_CMD__VMID__SHIFT 0x8 +#define ACP_SEMA_CMD__ATC_MASK 0x1000 +#define ACP_SEMA_CMD__ATC__SHIFT 0xc +#define ACP_SEMA_STS__REQ_STS_MASK 0x3 +#define ACP_SEMA_STS__REQ_STS__SHIFT 0x0 +#define ACP_SEMA_STS__REQ_RESP_AVAIL_MASK 0x100 +#define ACP_SEMA_STS__REQ_RESP_AVAIL__SHIFT 0x8 +#define ACP_SEMA_REQ__ISSUE_POLL_REQ_MASK 0x1 +#define ACP_SEMA_REQ__ISSUE_POLL_REQ__SHIFT 0x0 +#define ACP_FW_STATUS__RUN_MASK 0x1 +#define ACP_FW_STATUS__RUN__SHIFT 0x0 +#define ACP_FUTURE_REG_ACLK_0__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_ACLK_0__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_ACLK_1__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_ACLK_1__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_ACLK_2__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_ACLK_2__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_ACLK_3__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_ACLK_3__ACPFutureReg__SHIFT 0x0 +#define ACP_FUTURE_REG_ACLK_4__ACPFutureReg_MASK 0xffffffff +#define ACP_FUTURE_REG_ACLK_4__ACPFutureReg__SHIFT 0x0 +#define ACP_TIMER__ACP_Timer_count_MASK 0xffffffff +#define ACP_TIMER__ACP_Timer_count__SHIFT 0x0 +#define ACP_TIMER_CNTL__ACP_Timer_control_MASK 0x1 +#define ACP_TIMER_CNTL__ACP_Timer_control__SHIFT 0x0 +#define ACP_DSP0_TIMER__ACP_DSP0_timer_MASK 0xffffff +#define ACP_DSP0_TIMER__ACP_DSP0_timer__SHIFT 0x0 +#define ACP_DSP1_TIMER__ACP_DSP1_timer_MASK 0xffffff +#define ACP_DSP1_TIMER__ACP_DSP1_timer__SHIFT 0x0 +#define ACP_DSP2_TIMER__ACP_DSP2_timer_MASK 0xffffff +#define ACP_DSP2_TIMER__ACP_DSP2_timer__SHIFT 0x0 +#define ACP_I2S_TRANSMIT_BYTE_CNT_HIGH__i2s_sp_tx_byte_cnt_high_MASK 0xffffffff +#define ACP_I2S_TRANSMIT_BYTE_CNT_HIGH__i2s_sp_tx_byte_cnt_high__SHIFT 0x0 +#define ACP_I2S_TRANSMIT_BYTE_CNT_LOW__i2s_sp_tx_byte_cnt_low_MASK 0xffffffff +#define ACP_I2S_TRANSMIT_BYTE_CNT_LOW__i2s_sp_tx_byte_cnt_low__SHIFT 0x0 +#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH__i2s_bt_tx_byte_cnt_high_MASK 0xffffffff +#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH__i2s_bt_tx_byte_cnt_high__SHIFT 0x0 +#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW__i2s_bt_tx_byte_cnt_low_MASK 0xffffffff +#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW__i2s_bt_tx_byte_cnt_low__SHIFT 0x0 +#define ACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH__i2s_bt_rx_byte_cnt_high_MASK 0xffffffff +#define ACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH__i2s_bt_rx_byte_cnt_high__SHIFT 0x0 +#define ACP_I2S_BT_RECEIVE_BYTE_CNT_LOW__i2s_bt_rx_byte_cnt_low_MASK 0xffffffff +#define ACP_I2S_BT_RECEIVE_BYTE_CNT_LOW__i2s_bt_rx_byte_cnt_low__SHIFT 0x0 +#define ACP_DSP0_CS_STATE__DSP0_CS_state_MASK 0x1 +#define ACP_DSP0_CS_STATE__DSP0_CS_state__SHIFT 0x0 +#define ACP_DSP1_CS_STATE__DSP1_CS_state_MASK 0x1 +#define ACP_DSP1_CS_STATE__DSP1_CS_state__SHIFT 0x0 +#define ACP_DSP2_CS_STATE__DSP2_CS_state_MASK 0x1 +#define ACP_DSP2_CS_STATE__DSP2_CS_state__SHIFT 0x0 +#define ACP_SCRATCH_REG_BASE_ADDR__SCRATCH_REG_BASE_ADDR_MASK 0x7ffff +#define ACP_SCRATCH_REG_BASE_ADDR__SCRATCH_REG_BASE_ADDR__SHIFT 0x0 +#define CC_ACP_EFUSE__DSP0_DISABLE_MASK 0x2 +#define CC_ACP_EFUSE__DSP0_DISABLE__SHIFT 0x1 +#define CC_ACP_EFUSE__DSP1_DISABLE_MASK 0x4 +#define CC_ACP_EFUSE__DSP1_DISABLE__SHIFT 0x2 +#define CC_ACP_EFUSE__DSP2_DISABLE_MASK 0x8 +#define CC_ACP_EFUSE__DSP2_DISABLE__SHIFT 0x3 +#define CC_ACP_EFUSE__ACP_DISABLE_MASK 0x10 +#define CC_ACP_EFUSE__ACP_DISABLE__SHIFT 0x4 +#define ACP_PGFSM_RETAIN_REG__ACP_P1_ON_OFF_MASK 0x1 +#define ACP_PGFSM_RETAIN_REG__ACP_P1_ON_OFF__SHIFT 0x0 +#define ACP_PGFSM_RETAIN_REG__ACP_P2_ON_OFF_MASK 0x2 +#define ACP_PGFSM_RETAIN_REG__ACP_P2_ON_OFF__SHIFT 0x1 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP0_ON_OFF_MASK 0x4 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP0_ON_OFF__SHIFT 0x2 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP1_ON_OFF_MASK 0x8 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP1_ON_OFF__SHIFT 0x3 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP2_ON_OFF_MASK 0x10 +#define ACP_PGFSM_RETAIN_REG__ACP_DSP2_ON_OFF__SHIFT 0x4 +#define ACP_PGFSM_RETAIN_REG__ACP_AZ_ON_OFF_MASK 0x20 +#define ACP_PGFSM_RETAIN_REG__ACP_AZ_ON_OFF__SHIFT 0x5 +#define ACP_PGFSM_CONFIG_REG__FSM_ADDR_MASK 0xff +#define ACP_PGFSM_CONFIG_REG__FSM_ADDR__SHIFT 0x0 +#define ACP_PGFSM_CONFIG_REG__Power_Down_MASK 0x100 +#define ACP_PGFSM_CONFIG_REG__Power_Down__SHIFT 0x8 +#define ACP_PGFSM_CONFIG_REG__Power_Up_MASK 0x200 +#define ACP_PGFSM_CONFIG_REG__Power_Up__SHIFT 0x9 +#define ACP_PGFSM_CONFIG_REG__P1_Select_MASK 0x400 +#define ACP_PGFSM_CONFIG_REG__P1_Select__SHIFT 0xa +#define ACP_PGFSM_CONFIG_REG__P2_Select_MASK 0x800 +#define ACP_PGFSM_CONFIG_REG__P2_Select__SHIFT 0xb +#define ACP_PGFSM_CONFIG_REG__Wr_MASK 0x1000 +#define ACP_PGFSM_CONFIG_REG__Wr__SHIFT 0xc +#define ACP_PGFSM_CONFIG_REG__Rd_MASK 0x2000 +#define ACP_PGFSM_CONFIG_REG__Rd__SHIFT 0xd +#define ACP_PGFSM_CONFIG_REG__RdData_Reset_MASK 0x4000 +#define ACP_PGFSM_CONFIG_REG__RdData_Reset__SHIFT 0xe +#define ACP_PGFSM_CONFIG_REG__Short_Format_MASK 0x8000 +#define ACP_PGFSM_CONFIG_REG__Short_Format__SHIFT 0xf +#define ACP_PGFSM_CONFIG_REG__BPM_CG_MG_FGCG_MASK 0x3ff0000 +#define ACP_PGFSM_CONFIG_REG__BPM_CG_MG_FGCG__SHIFT 0x10 +#define ACP_PGFSM_CONFIG_REG__SRBM_override_MASK 0x4000000 +#define ACP_PGFSM_CONFIG_REG__SRBM_override__SHIFT 0x1a +#define ACP_PGFSM_CONFIG_REG__Rsvd_BPM_Addr_MASK 0x8000000 +#define ACP_PGFSM_CONFIG_REG__Rsvd_BPM_Addr__SHIFT 0x1b +#define ACP_PGFSM_CONFIG_REG__REG_ADDR_MASK 0xf0000000 +#define ACP_PGFSM_CONFIG_REG__REG_ADDR__SHIFT 0x1c +#define ACP_PGFSM_WRITE_REG__Write_value_MASK 0xffffffff +#define ACP_PGFSM_WRITE_REG__Write_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_0__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_0__Read_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_1__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_1__Read_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_2__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_2__Read_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_3__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_3__Read_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_4__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_4__Read_value__SHIFT 0x0 +#define ACP_PGFSM_READ_REG_5__Read_value_MASK 0xffffff +#define ACP_PGFSM_READ_REG_5__Read_value__SHIFT 0x0 +#define ACP_IP_PGFSM_ENABLE__ACP_IP_ACCESS_MASK 0x1 +#define ACP_IP_PGFSM_ENABLE__ACP_IP_ACCESS__SHIFT 0x0 +#define ACP_I2S_PIN_CONFIG__ACP_I2S_PIN_CONFIG_MASK 0x3 +#define ACP_I2S_PIN_CONFIG__ACP_I2S_PIN_CONFIG__SHIFT 0x0 +#define ACP_AZALIA_I2S_SELECT__AZ_I2S_SELECT_MASK 0x1 +#define ACP_AZALIA_I2S_SELECT__AZ_I2S_SELECT__SHIFT 0x0 +#define ACP_CHIP_PKG_FOR_PAD_ISOLATION__external_fch_package_MASK 0x1 +#define ACP_CHIP_PKG_FOR_PAD_ISOLATION__external_fch_package__SHIFT 0x0 +#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pullup_disable_MASK 0x7ff +#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pullup_disable__SHIFT 0x0 +#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pulldown_enable_MASK 0x7ff0000 +#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pulldown_enable__SHIFT 0x10 +#define ACP_BT_UART_PAD_SEL__ACP_BT_UART_PAD_SEL_MASK 0x1 +#define ACP_BT_UART_PAD_SEL__ACP_BT_UART_PAD_SEL__SHIFT 0x0 +#define ACP_SCRATCH_REG_0__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_0__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_1__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_1__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_2__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_2__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_3__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_3__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_4__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_4__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_5__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_5__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_6__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_6__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_7__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_7__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_8__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_8__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_9__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_9__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_10__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_10__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_11__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_11__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_12__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_12__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_13__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_13__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_14__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_14__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_15__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_15__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_16__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_16__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_17__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_17__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_18__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_18__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_19__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_19__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_20__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_20__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_21__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_21__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_22__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_22__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_23__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_23__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_24__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_24__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_25__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_25__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_26__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_26__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_27__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_27__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_28__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_28__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_29__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_29__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_30__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_30__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_31__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_31__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_32__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_32__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_33__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_33__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_34__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_34__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_35__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_35__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_36__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_36__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_37__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_37__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_38__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_38__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_39__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_39__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_40__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_40__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_41__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_41__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_42__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_42__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_43__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_43__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_44__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_44__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_45__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_45__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_46__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_46__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_SCRATCH_REG_47__ACP_SCRATCH_REG_MASK 0xffffffff +#define ACP_SCRATCH_REG_47__ACP_SCRATCH_REG__SHIFT 0x0 +#define ACP_VOICE_WAKEUP_ENABLE__voice_wakeup_enable_MASK 0x1 +#define ACP_VOICE_WAKEUP_ENABLE__voice_wakeup_enable__SHIFT 0x0 +#define ACP_VOICE_WAKEUP_STATUS__voice_wakeup_status_MASK 0x1 +#define ACP_VOICE_WAKEUP_STATUS__voice_wakeup_status__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_LOWER_THRESHOLD__i2s_voice_wakeup_lower_threshold_MASK 0xffffffff +#define I2S_VOICE_WAKEUP_LOWER_THRESHOLD__i2s_voice_wakeup_lower_threshold__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_HIGHER_THRESHOLD__i2s_voice_wakeup_higher_threshold_MASK 0xffffffff +#define I2S_VOICE_WAKEUP_HIGHER_THRESHOLD__i2s_voice_wakeup_higher_threshold__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_NO_OF_SAMPLES__i2s_voice_wakeup_no_of_samples_MASK 0xffff +#define I2S_VOICE_WAKEUP_NO_OF_SAMPLES__i2s_voice_wakeup_no_of_samples__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_NO_OF_PEAKS__i2s_voice_wakeup_no_of_peaks_MASK 0xffff +#define I2S_VOICE_WAKEUP_NO_OF_PEAKS__i2s_voice_wakeup_no_of_peaks__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS__i2s_voice_wakeup_duration_of_n_peaks_MASK 0xffffffff +#define I2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS__i2s_voice_wakeup_duration_of_n_peaks__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION__i2s_voice_wakeup_bitclk_toggle_wakeup_en_MASK 0x1 +#define I2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION__i2s_voice_wakeup_bitclk_toggle_wakeup_en__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_req_MASK 0x1 +#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_req__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_ack_MASK 0x2 +#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_ack__SHIFT 0x1 +#define I2S_VOICE_WAKEUP_DATA_POINTER__i2s_voice_wakeup_data_pointer_MASK 0xffffffff +#define I2S_VOICE_WAKEUP_DATA_POINTER__i2s_voice_wakeup_data_pointer__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_valid_MASK 0x1 +#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_valid__SHIFT 0x0 +#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_match_MASK 0x2 +#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_match__SHIFT 0x1 +#define I2S_VOICE_WAKEUP_8KB_WRAP__i2s_voice_wakeup_8kb_wrap_MASK 0x1 +#define I2S_VOICE_WAKEUP_8KB_WRAP__i2s_voice_wakeup_8kb_wrap__SHIFT 0x0 +#define ACP_I2S_RECEIVED_BYTE_CNT_HIGH__i2s_mic_rx_byte_cnt_high_MASK 0xffffffff +#define ACP_I2S_RECEIVED_BYTE_CNT_HIGH__i2s_mic_rx_byte_cnt_high__SHIFT 0x0 +#define ACP_I2S_RECEIVED_BYTE_CNT_LOW__i2s_mic_rx_byte_cnt_low_MASK 0xffffffff +#define ACP_I2S_RECEIVED_BYTE_CNT_LOW__i2s_mic_rx_byte_cnt_low__SHIFT 0x0 +#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH__i2s_micsp_tx_byte_cnt_high_MASK 0xffffffff +#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH__i2s_micsp_tx_byte_cnt_high__SHIFT 0x0 +#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW__i2s_micsp_tx_byte_cnt_low_MASK 0xffffffff +#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW__i2s_micsp_tx_byte_cnt_low__SHIFT 0x0 +#define ACP_MEM_SHUT_DOWN_REQ_LO__ACP_ShutDownReq_RAML_MASK 0xffffffff +#define ACP_MEM_SHUT_DOWN_REQ_LO__ACP_ShutDownReq_RAML__SHIFT 0x0 +#define ACP_MEM_SHUT_DOWN_REQ_HI__ACP_ShutDownReq_RAMH_MASK 0xffff +#define ACP_MEM_SHUT_DOWN_REQ_HI__ACP_ShutDownReq_RAMH__SHIFT 0x0 +#define ACP_MEM_SHUT_DOWN_STS_LO__ACP_ShutDownSts_RAML_MASK 0xffffffff +#define ACP_MEM_SHUT_DOWN_STS_LO__ACP_ShutDownSts_RAML__SHIFT 0x0 +#define ACP_MEM_SHUT_DOWN_STS_HI__ACP_ShutDownSts_RAMH_MASK 0xffff +#define ACP_MEM_SHUT_DOWN_STS_HI__ACP_ShutDownSts_RAMH__SHIFT 0x0 +#define ACP_MEM_DEEP_SLEEP_REQ_LO__ACP_DeepSleepReq_RAML_MASK 0xffffffff +#define ACP_MEM_DEEP_SLEEP_REQ_LO__ACP_DeepSleepReq_RAML__SHIFT 0x0 +#define ACP_MEM_DEEP_SLEEP_REQ_HI__ACP_DeepSleepReq_RAMH_MASK 0xffff +#define ACP_MEM_DEEP_SLEEP_REQ_HI__ACP_DeepSleepReq_RAMH__SHIFT 0x0 +#define ACP_MEM_DEEP_SLEEP_STS_LO__ACP_DeepSleepSts_RAML_MASK 0xffffffff +#define ACP_MEM_DEEP_SLEEP_STS_LO__ACP_DeepSleepSts_RAML__SHIFT 0x0 +#define ACP_MEM_DEEP_SLEEP_STS_HI__ACP_DeepSleepSts_RAMH_MASK 0xffff +#define ACP_MEM_DEEP_SLEEP_STS_HI__ACP_DeepSleepSts_RAMH__SHIFT 0x0 +#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO__acp_mem_wakeup_from_shut_down_lo_MASK 0xffffffff +#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO__acp_mem_wakeup_from_shut_down_lo__SHIFT 0x0 +#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI__acp_mem_wakeup_from_shut_down_hi_MASK 0xffff +#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI__acp_mem_wakeup_from_shut_down_hi__SHIFT 0x0 +#define ACP_MEM_WAKEUP_FROM_SLEEP_LO__acp_mem_wakeup_from_sleep_lo_MASK 0xffffffff +#define ACP_MEM_WAKEUP_FROM_SLEEP_LO__acp_mem_wakeup_from_sleep_lo__SHIFT 0x0 +#define ACP_MEM_WAKEUP_FROM_SLEEP_HI__acp_mem_wakeup_from_sleep_hi_MASK 0xffff +#define ACP_MEM_WAKEUP_FROM_SLEEP_HI__acp_mem_wakeup_from_sleep_hi__SHIFT 0x0 +#define ACP_I2SSP_IER__I2SSP_IEN_MASK 0x1 +#define ACP_I2SSP_IER__I2SSP_IEN__SHIFT 0x0 +#define ACP_I2SSP_IRER__I2SSP_RXEN_MASK 0x1 +#define ACP_I2SSP_IRER__I2SSP_RXEN__SHIFT 0x0 +#define ACP_I2SSP_ITER__I2SSP_TXEN_MASK 0x1 +#define ACP_I2SSP_ITER__I2SSP_TXEN__SHIFT 0x0 +#define ACP_I2SSP_CER__I2SSP_CLKEN_MASK 0x1 +#define ACP_I2SSP_CER__I2SSP_CLKEN__SHIFT 0x0 +#define ACP_I2SSP_CCR__I2SSP_SCLKG_MASK 0x7 +#define ACP_I2SSP_CCR__I2SSP_SCLKG__SHIFT 0x0 +#define ACP_I2SSP_CCR__I2SSP_WSS_MASK 0x18 +#define ACP_I2SSP_CCR__I2SSP_WSS__SHIFT 0x3 +#define ACP_I2SSP_RXFFR__I2SSP_RXFFR_MASK 0x1 +#define ACP_I2SSP_RXFFR__I2SSP_RXFFR__SHIFT 0x0 +#define ACP_I2SSP_TXFFR__I2SSP_TXFFR_MASK 0x1 +#define ACP_I2SSP_TXFFR__I2SSP_TXFFR__SHIFT 0x0 +#define ACP_I2SSP_LRBR0__I2SSP_LRBR0_MASK 0xffffffff +#define ACP_I2SSP_LRBR0__I2SSP_LRBR0__SHIFT 0x0 +#define ACP_I2SSP_RRBR0__I2SSP_RRBR0_MASK 0xffffffff +#define ACP_I2SSP_RRBR0__I2SSP_RRBR0__SHIFT 0x0 +#define ACP_I2SSP_RER0__I2SSP_RXCHEN0_MASK 0x1 +#define ACP_I2SSP_RER0__I2SSP_RXCHEN0__SHIFT 0x0 +#define ACP_I2SSP_TER0__I2SSP_TXCHEN0_MASK 0x1 +#define ACP_I2SSP_TER0__I2SSP_TXCHEN0__SHIFT 0x0 +#define ACP_I2SSP_RCR0__I2SSP_WLEN_MASK 0x7 +#define ACP_I2SSP_RCR0__I2SSP_WLEN__SHIFT 0x0 +#define ACP_I2SSP_TCR0__I2SSP_WLEN_MASK 0x7 +#define ACP_I2SSP_TCR0__I2SSP_WLEN__SHIFT 0x0 +#define ACP_I2SSP_ISR0__I2SSP_RXDA_MASK 0x1 +#define ACP_I2SSP_ISR0__I2SSP_RXDA__SHIFT 0x0 +#define ACP_I2SSP_ISR0__I2SSP_RXFO_MASK 0x2 +#define ACP_I2SSP_ISR0__I2SSP_RXFO__SHIFT 0x1 +#define ACP_I2SSP_ISR0__I2SSP_TXFE_MASK 0x10 +#define ACP_I2SSP_ISR0__I2SSP_TXFE__SHIFT 0x4 +#define ACP_I2SSP_ISR0__I2SSP_TXFO_MASK 0x20 +#define ACP_I2SSP_ISR0__I2SSP_TXFO__SHIFT 0x5 +#define ACP_I2SSP_IMR0__I2SSP_RXDAM_MASK 0x1 +#define ACP_I2SSP_IMR0__I2SSP_RXDAM__SHIFT 0x0 +#define ACP_I2SSP_IMR0__I2SSP_RXFOM_MASK 0x2 +#define ACP_I2SSP_IMR0__I2SSP_RXFOM__SHIFT 0x1 +#define ACP_I2SSP_IMR0__I2SSP_TXFEM_MASK 0x10 +#define ACP_I2SSP_IMR0__I2SSP_TXFEM__SHIFT 0x4 +#define ACP_I2SSP_IMR0__I2SSP_TXFOM_MASK 0x20 +#define ACP_I2SSP_IMR0__I2SSP_TXFOM__SHIFT 0x5 +#define ACP_I2SSP_ROR0__I2SSP_RXCHO_MASK 0x1 +#define ACP_I2SSP_ROR0__I2SSP_RXCHO__SHIFT 0x0 +#define ACP_I2SSP_TOR0__I2SSP_TXCHO_MASK 0x1 +#define ACP_I2SSP_TOR0__I2SSP_TXCHO__SHIFT 0x0 +#define ACP_I2SSP_RFCR0__I2SSP_RXCHDT_MASK 0xf +#define ACP_I2SSP_RFCR0__I2SSP_RXCHDT__SHIFT 0x0 +#define ACP_I2SSP_TFCR0__I2SSP_TXCHET_MASK 0xf +#define ACP_I2SSP_TFCR0__I2SSP_TXCHET__SHIFT 0x0 +#define ACP_I2SSP_RFF0__I2SSP_RXCHFR_MASK 0x1 +#define ACP_I2SSP_RFF0__I2SSP_RXCHFR__SHIFT 0x0 +#define ACP_I2SSP_TFF0__I2SSP_TXCHFR_MASK 0x1 +#define ACP_I2SSP_TFF0__I2SSP_TXCHFR__SHIFT 0x0 +#define ACP_I2SSP_RXDMA__I2SSP_RXDMA_MASK 0xffffffff +#define ACP_I2SSP_RXDMA__I2SSP_RXDMA__SHIFT 0x0 +#define ACP_I2SSP_RRXDMA__I2SSP_RRXDMA_MASK 0x1 +#define ACP_I2SSP_RRXDMA__I2SSP_RRXDMA__SHIFT 0x0 +#define ACP_I2SSP_TXDMA__I2SSP_TXDMA_MASK 0xffffffff +#define ACP_I2SSP_TXDMA__I2SSP_TXDMA__SHIFT 0x0 +#define ACP_I2SSP_RTXDMA__I2SSP_RTXDMA_MASK 0x1 +#define ACP_I2SSP_RTXDMA__I2SSP_RTXDMA__SHIFT 0x0 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_0_MASK 0x7 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_0__SHIFT 0x0 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_1_MASK 0x38 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_1__SHIFT 0x3 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_2_MASK 0x380 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_2__SHIFT 0x7 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_3_MASK 0x1c00 +#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_3__SHIFT 0xa +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_APB_DATA_WIDTH_MASK 0x3 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_FIFO_DEPTH_GLOBAL_MASK 0xc +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_FIFO_DEPTH_GLOBAL__SHIFT 0x2 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_MODE_EN_MASK 0x10 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_MODE_EN__SHIFT 0x4 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TRANSMITTER_BLOCK_MASK 0x20 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TRANSMITTER_BLOCK__SHIFT 0x5 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RECEIVER_BLOCK_MASK 0x40 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RECEIVER_BLOCK__SHIFT 0x6 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RX_CHANNLES_MASK 0x180 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RX_CHANNLES__SHIFT 0x7 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_CHANNLES_MASK 0x600 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_CHANNLES__SHIFT 0x9 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_0_MASK 0x70000 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_0__SHIFT 0x10 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_1_MASK 0x380000 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_1__SHIFT 0x13 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_2_MASK 0x1c00000 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_2__SHIFT 0x16 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_3_MASK 0xe000000 +#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_3__SHIFT 0x19 +#define ACP_I2SSP_COMP_VERSION__I2SSP_APB_DATA_WIDTH_MASK 0xffffffff +#define ACP_I2SSP_COMP_VERSION__I2SSP_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SSP_COMP_TYPE__I2SSP_COMP_TYPE_MASK 0xffffffff +#define ACP_I2SSP_COMP_TYPE__I2SSP_COMP_TYPE__SHIFT 0x0 +#define ACP_I2SMICSP_IER__I2SMICSP_IEN_MASK 0x1 +#define ACP_I2SMICSP_IER__I2SMICSP_IEN__SHIFT 0x0 +#define ACP_I2SMICSP_IRER__I2SMICSP_RXEN_MASK 0x1 +#define ACP_I2SMICSP_IRER__I2SMICSP_RXEN__SHIFT 0x0 +#define ACP_I2SMICSP_ITER__I2SMICSP_TXEN_MASK 0x1 +#define ACP_I2SMICSP_ITER__I2SMICSP_TXEN__SHIFT 0x0 +#define ACP_I2SMICSP_CER__I2SMICSP_CLKEN_MASK 0x1 +#define ACP_I2SMICSP_CER__I2SMICSP_CLKEN__SHIFT 0x0 +#define ACP_I2SMICSP_CCR__I2SMICSP_SCLKG_MASK 0x7 +#define ACP_I2SMICSP_CCR__I2SMICSP_SCLKG__SHIFT 0x0 +#define ACP_I2SMICSP_CCR__I2SMICSP_WSS_MASK 0x18 +#define ACP_I2SMICSP_CCR__I2SMICSP_WSS__SHIFT 0x3 +#define ACP_I2SMICSP_RXFFR__I2SMICSP_RXFFR_MASK 0x1 +#define ACP_I2SMICSP_RXFFR__I2SMICSP_RXFFR__SHIFT 0x0 +#define ACP_I2SMICSP_TXFFR__I2SMICSP_TXFFR_MASK 0x1 +#define ACP_I2SMICSP_TXFFR__I2SMICSP_TXFFR__SHIFT 0x0 +#define ACP_I2SMICSP_LRBR0__I2SMICSP_LRBR0_MASK 0xffffffff +#define ACP_I2SMICSP_LRBR0__I2SMICSP_LRBR0__SHIFT 0x0 +#define ACP_I2SMICSP_RRBR0__I2SMICSP_RRBR0_MASK 0xffffffff +#define ACP_I2SMICSP_RRBR0__I2SMICSP_RRBR0__SHIFT 0x0 +#define ACP_I2SMICSP_RER0__I2SMICSP_RXCHEN0_MASK 0x1 +#define ACP_I2SMICSP_RER0__I2SMICSP_RXCHEN0__SHIFT 0x0 +#define ACP_I2SMICSP_TER0__I2SMICSP_TXCHEN0_MASK 0x1 +#define ACP_I2SMICSP_TER0__I2SMICSP_TXCHEN0__SHIFT 0x0 +#define ACP_I2SMICSP_RCR0__I2SMICSP_WLEN_MASK 0x7 +#define ACP_I2SMICSP_RCR0__I2SMICSP_WLEN__SHIFT 0x0 +#define ACP_I2SMICSP_TCR0__I2SMICSP_WLEN_MASK 0x7 +#define ACP_I2SMICSP_TCR0__I2SMICSP_WLEN__SHIFT 0x0 +#define ACP_I2SMICSP_ISR0__I2SMICSP_RXDA_MASK 0x1 +#define ACP_I2SMICSP_ISR0__I2SMICSP_RXDA__SHIFT 0x0 +#define ACP_I2SMICSP_ISR0__I2SMICSP_RXFO_MASK 0x2 +#define ACP_I2SMICSP_ISR0__I2SMICSP_RXFO__SHIFT 0x1 +#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFE_MASK 0x10 +#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFE__SHIFT 0x4 +#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFO_MASK 0x20 +#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFO__SHIFT 0x5 +#define ACP_I2SMICSP_IMR0__I2SMICSP_RXDAM_MASK 0x1 +#define ACP_I2SMICSP_IMR0__I2SMICSP_RXDAM__SHIFT 0x0 +#define ACP_I2SMICSP_IMR0__I2SMICSP_RXFOM_MASK 0x2 +#define ACP_I2SMICSP_IMR0__I2SMICSP_RXFOM__SHIFT 0x1 +#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFEM_MASK 0x10 +#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFEM__SHIFT 0x4 +#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFOM_MASK 0x20 +#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFOM__SHIFT 0x5 +#define ACP_I2SMICSP_ROR0__I2SMICSP_RXCHO_MASK 0x1 +#define ACP_I2SMICSP_ROR0__I2SMICSP_RXCHO__SHIFT 0x0 +#define ACP_I2SMICSP_TOR0__I2SMICSP_TXCHO_MASK 0x1 +#define ACP_I2SMICSP_TOR0__I2SMICSP_TXCHO__SHIFT 0x0 +#define ACP_I2SMICSP_RFCR0__I2SMICSP_RXCHDT_MASK 0xf +#define ACP_I2SMICSP_RFCR0__I2SMICSP_RXCHDT__SHIFT 0x0 +#define ACP_I2SMICSP_TFCR0__I2SMICSP_TXCHET_MASK 0xf +#define ACP_I2SMICSP_TFCR0__I2SMICSP_TXCHET__SHIFT 0x0 +#define ACP_I2SMICSP_RFF0__I2SMICSP_RXCHFR_MASK 0x1 +#define ACP_I2SMICSP_RFF0__I2SMICSP_RXCHFR__SHIFT 0x0 +#define ACP_I2SMICSP_TFF0__I2SMICSP_TXCHFR_MASK 0x1 +#define ACP_I2SMICSP_TFF0__I2SMICSP_TXCHFR__SHIFT 0x0 +#define ACP_I2SMICSP_LRBR1__I2SMICSP_LRBR1_MASK 0xffffffff +#define ACP_I2SMICSP_LRBR1__I2SMICSP_LRBR1__SHIFT 0x0 +#define ACP_I2SMICSP_RRBR1__I2SMICSP_RRBR1_MASK 0xffffffff +#define ACP_I2SMICSP_RRBR1__I2SMICSP_RRBR1__SHIFT 0x0 +#define ACP_I2SMICSP_RER1__I2SMICSP_RXCHEN1_MASK 0x1 +#define ACP_I2SMICSP_RER1__I2SMICSP_RXCHEN1__SHIFT 0x0 +#define ACP_I2SMICSP_TER1__I2SMICSP_TXCHEN1_MASK 0x1 +#define ACP_I2SMICSP_TER1__I2SMICSP_TXCHEN1__SHIFT 0x0 +#define ACP_I2SMICSP_RCR1__I2SMICSP_WLEN_MASK 0x7 +#define ACP_I2SMICSP_RCR1__I2SMICSP_WLEN__SHIFT 0x0 +#define ACP_I2SMICSP_TCR1__I2SMICSP_WLEN_MASK 0x7 +#define ACP_I2SMICSP_TCR1__I2SMICSP_WLEN__SHIFT 0x0 +#define ACP_I2SMICSP_ISR1__I2SMICSP_RXDA_MASK 0x1 +#define ACP_I2SMICSP_ISR1__I2SMICSP_RXDA__SHIFT 0x0 +#define ACP_I2SMICSP_ISR1__I2SMICSP_RXFO_MASK 0x2 +#define ACP_I2SMICSP_ISR1__I2SMICSP_RXFO__SHIFT 0x1 +#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFE_MASK 0x10 +#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFE__SHIFT 0x4 +#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFO_MASK 0x20 +#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFO__SHIFT 0x5 +#define ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK 0x1 +#define ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM__SHIFT 0x0 +#define ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK 0x2 +#define ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM__SHIFT 0x1 +#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFEM_MASK 0x10 +#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFEM__SHIFT 0x4 +#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFOM_MASK 0x20 +#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFOM__SHIFT 0x5 +#define ACP_I2SMICSP_ROR1__I2SMICSP_RXCHO_MASK 0x1 +#define ACP_I2SMICSP_ROR1__I2SMICSP_RXCHO__SHIFT 0x0 +#define ACP_I2SMICSP_TOR1__I2SMICSP_TXCHO_MASK 0x1 +#define ACP_I2SMICSP_TOR1__I2SMICSP_TXCHO__SHIFT 0x0 +#define ACP_I2SMICSP_RFCR1__I2SMICSP_RXCHDT_MASK 0xf +#define ACP_I2SMICSP_RFCR1__I2SMICSP_RXCHDT__SHIFT 0x0 +#define ACP_I2SMICSP_TFCR1__I2SMICSP_TXCHET_MASK 0xf +#define ACP_I2SMICSP_TFCR1__I2SMICSP_TXCHET__SHIFT 0x0 +#define ACP_I2SMICSP_RFF1__I2SMICSP_RXCHFR_MASK 0x1 +#define ACP_I2SMICSP_RFF1__I2SMICSP_RXCHFR__SHIFT 0x0 +#define ACP_I2SMICSP_TFF1__I2SMICSP_TXCHFR_MASK 0x1 +#define ACP_I2SMICSP_TFF1__I2SMICSP_TXCHFR__SHIFT 0x0 +#define ACP_I2SMICSP_RXDMA__I2SMICSP_RXDMA_MASK 0xffffffff +#define ACP_I2SMICSP_RXDMA__I2SMICSP_RXDMA__SHIFT 0x0 +#define ACP_I2SMICSP_RRXDMA__I2SMICSP_RRXDMA_MASK 0x1 +#define ACP_I2SMICSP_RRXDMA__I2SMICSP_RRXDMA__SHIFT 0x0 +#define ACP_I2SMICSP_TXDMA__I2SMICSP_TXDMA_MASK 0xffffffff +#define ACP_I2SMICSP_TXDMA__I2SMICSP_TXDMA__SHIFT 0x0 +#define ACP_I2SMICSP_RTXDMA__I2SMICSP_RTXDMA_MASK 0x1 +#define ACP_I2SMICSP_RTXDMA__I2SMICSP_RTXDMA__SHIFT 0x0 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_0_MASK 0x7 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_0__SHIFT 0x0 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_1_MASK 0x38 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_1__SHIFT 0x3 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_2_MASK 0x380 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_2__SHIFT 0x7 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_3_MASK 0x1c00 +#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_3__SHIFT 0xa +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_APB_DATA_WIDTH_MASK 0x3 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_FIFO_DEPTH_GLOBAL_MASK 0xc +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_FIFO_DEPTH_GLOBAL__SHIFT 0x2 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_MODE_EN_MASK 0x10 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_MODE_EN__SHIFT 0x4 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TRANSMITTER_BLOCK_MASK 0x20 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TRANSMITTER_BLOCK__SHIFT 0x5 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RECEIVER_BLOCK_MASK 0x40 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RECEIVER_BLOCK__SHIFT 0x6 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RX_CHANNLES_MASK 0x180 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RX_CHANNLES__SHIFT 0x7 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_CHANNLES_MASK 0x600 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_CHANNLES__SHIFT 0x9 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_0_MASK 0x70000 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_0__SHIFT 0x10 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_1_MASK 0x380000 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_1__SHIFT 0x13 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_2_MASK 0x1c00000 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_2__SHIFT 0x16 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_3_MASK 0xe000000 +#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_3__SHIFT 0x19 +#define ACP_I2SMICSP_COMP_VERSION__I2SMICSP_APB_DATA_WIDTH_MASK 0xffffffff +#define ACP_I2SMICSP_COMP_VERSION__I2SMICSP_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SMICSP_COMP_TYPE__I2SMICSP_COMP_TYPE_MASK 0xffffffff +#define ACP_I2SMICSP_COMP_TYPE__I2SMICSP_COMP_TYPE__SHIFT 0x0 +#define ACP_I2SBT_IER__I2SBT_IEN_MASK 0x1 +#define ACP_I2SBT_IER__I2SBT_IEN__SHIFT 0x0 +#define ACP_I2SBT_IRER__I2SBT_RXEN_MASK 0x1 +#define ACP_I2SBT_IRER__I2SBT_RXEN__SHIFT 0x0 +#define ACP_I2SBT_ITER__I2SBT_TXEN_MASK 0x1 +#define ACP_I2SBT_ITER__I2SBT_TXEN__SHIFT 0x0 +#define ACP_I2SBT_CER__I2SBT_CLKEN_MASK 0x1 +#define ACP_I2SBT_CER__I2SBT_CLKEN__SHIFT 0x0 +#define ACP_I2SBT_CCR__I2SBT_SCLKG_MASK 0x7 +#define ACP_I2SBT_CCR__I2SBT_SCLKG__SHIFT 0x0 +#define ACP_I2SBT_CCR__I2SBT_WSS_MASK 0x18 +#define ACP_I2SBT_CCR__I2SBT_WSS__SHIFT 0x3 +#define ACP_I2SBT_RXFFR__I2SBT_RXFFR_MASK 0x1 +#define ACP_I2SBT_RXFFR__I2SBT_RXFFR__SHIFT 0x0 +#define ACP_I2SBT_TXFFR__I2SBT_TXFFR_MASK 0x1 +#define ACP_I2SBT_TXFFR__I2SBT_TXFFR__SHIFT 0x0 +#define ACP_I2SBT_LRBR0__I2SBT_LRBR0_MASK 0xffffffff +#define ACP_I2SBT_LRBR0__I2SBT_LRBR0__SHIFT 0x0 +#define ACP_I2SBT_RRBR0__I2SBT_RRBR0_MASK 0xffffffff +#define ACP_I2SBT_RRBR0__I2SBT_RRBR0__SHIFT 0x0 +#define ACP_I2SBT_RER0__I2SBT_RXCHEN0_MASK 0x1 +#define ACP_I2SBT_RER0__I2SBT_RXCHEN0__SHIFT 0x0 +#define ACP_I2SBT_TER0__I2SBT_TXCHEN0_MASK 0x1 +#define ACP_I2SBT_TER0__I2SBT_TXCHEN0__SHIFT 0x0 +#define ACP_I2SBT_RCR0__I2SBT_WLEN_MASK 0x7 +#define ACP_I2SBT_RCR0__I2SBT_WLEN__SHIFT 0x0 +#define ACP_I2SBT_TCR0__I2SBT_WLEN_MASK 0x7 +#define ACP_I2SBT_TCR0__I2SBT_WLEN__SHIFT 0x0 +#define ACP_I2SBT_ISR0__I2SBT_RXDA_MASK 0x1 +#define ACP_I2SBT_ISR0__I2SBT_RXDA__SHIFT 0x0 +#define ACP_I2SBT_ISR0__I2SBT_RXFO_MASK 0x2 +#define ACP_I2SBT_ISR0__I2SBT_RXFO__SHIFT 0x1 +#define ACP_I2SBT_ISR0__I2SBT_TXFE_MASK 0x10 +#define ACP_I2SBT_ISR0__I2SBT_TXFE__SHIFT 0x4 +#define ACP_I2SBT_ISR0__I2SBT_TXFO_MASK 0x20 +#define ACP_I2SBT_ISR0__I2SBT_TXFO__SHIFT 0x5 +#define ACP_I2SBT_IMR0__I2SBT_RXDAM_MASK 0x1 +#define ACP_I2SBT_IMR0__I2SBT_RXDAM__SHIFT 0x0 +#define ACP_I2SBT_IMR0__I2SBT_RXFOM_MASK 0x2 +#define ACP_I2SBT_IMR0__I2SBT_RXFOM__SHIFT 0x1 +#define ACP_I2SBT_IMR0__I2SBT_TXFEM_MASK 0x10 +#define ACP_I2SBT_IMR0__I2SBT_TXFEM__SHIFT 0x4 +#define ACP_I2SBT_IMR0__I2SBT_TXFOM_MASK 0x20 +#define ACP_I2SBT_IMR0__I2SBT_TXFOM__SHIFT 0x5 +#define ACP_I2SBT_ROR0__I2SBT_RXCHO_MASK 0x1 +#define ACP_I2SBT_ROR0__I2SBT_RXCHO__SHIFT 0x0 +#define ACP_I2SBT_TOR0__I2SBT_TXCHO_MASK 0x1 +#define ACP_I2SBT_TOR0__I2SBT_TXCHO__SHIFT 0x0 +#define ACP_I2SBT_RFCR0__I2SBT_RXCHDT_MASK 0xf +#define ACP_I2SBT_RFCR0__I2SBT_RXCHDT__SHIFT 0x0 +#define ACP_I2SBT_TFCR0__I2SBT_TXCHET_MASK 0xf +#define ACP_I2SBT_TFCR0__I2SBT_TXCHET__SHIFT 0x0 +#define ACP_I2SBT_RFF0__I2SBT_RXCHFR_MASK 0x1 +#define ACP_I2SBT_RFF0__I2SBT_RXCHFR__SHIFT 0x0 +#define ACP_I2SBT_TFF0__I2SBT_TXCHFR_MASK 0x1 +#define ACP_I2SBT_TFF0__I2SBT_TXCHFR__SHIFT 0x0 +#define ACP_I2SBT_LRBR1__I2SBT_LRBR1_MASK 0xffffffff +#define ACP_I2SBT_LRBR1__I2SBT_LRBR1__SHIFT 0x0 +#define ACP_I2SBT_RRBR1__I2SBT_RRBR1_MASK 0xffffffff +#define ACP_I2SBT_RRBR1__I2SBT_RRBR1__SHIFT 0x0 +#define ACP_I2SBT_RER1__I2SBT_RXCHEN1_MASK 0x1 +#define ACP_I2SBT_RER1__I2SBT_RXCHEN1__SHIFT 0x0 +#define ACP_I2SBT_TER1__I2SBT_TXCHEN1_MASK 0x1 +#define ACP_I2SBT_TER1__I2SBT_TXCHEN1__SHIFT 0x0 +#define ACP_I2SBT_RCR1__I2SBT_WLEN_MASK 0x7 +#define ACP_I2SBT_RCR1__I2SBT_WLEN__SHIFT 0x0 +#define ACP_I2SBT_TCR1__I2SBT_WLEN_MASK 0x7 +#define ACP_I2SBT_TCR1__I2SBT_WLEN__SHIFT 0x0 +#define ACP_I2SBT_ISR1__I2SBT_RXDA_MASK 0x1 +#define ACP_I2SBT_ISR1__I2SBT_RXDA__SHIFT 0x0 +#define ACP_I2SBT_ISR1__I2SBT_RXFO_MASK 0x2 +#define ACP_I2SBT_ISR1__I2SBT_RXFO__SHIFT 0x1 +#define ACP_I2SBT_ISR1__I2SBT_TXFE_MASK 0x10 +#define ACP_I2SBT_ISR1__I2SBT_TXFE__SHIFT 0x4 +#define ACP_I2SBT_ISR1__I2SBT_TXFO_MASK 0x20 +#define ACP_I2SBT_ISR1__I2SBT_TXFO__SHIFT 0x5 +#define ACP_I2SBT_IMR1__I2SBT_RXDAM_MASK 0x1 +#define ACP_I2SBT_IMR1__I2SBT_RXDAM__SHIFT 0x0 +#define ACP_I2SBT_IMR1__I2SBT_RXFOM_MASK 0x2 +#define ACP_I2SBT_IMR1__I2SBT_RXFOM__SHIFT 0x1 +#define ACP_I2SBT_IMR1__I2SBT_TXFEM_MASK 0x10 +#define ACP_I2SBT_IMR1__I2SBT_TXFEM__SHIFT 0x4 +#define ACP_I2SBT_IMR1__I2SBT_TXFOM_MASK 0x20 +#define ACP_I2SBT_IMR1__I2SBT_TXFOM__SHIFT 0x5 +#define ACP_I2SBT_ROR1__I2SBT_RXCHO_MASK 0x1 +#define ACP_I2SBT_ROR1__I2SBT_RXCHO__SHIFT 0x0 +#define ACP_I2SBT_TOR1__I2SBT_TXCHO_MASK 0x1 +#define ACP_I2SBT_TOR1__I2SBT_TXCHO__SHIFT 0x0 +#define ACP_I2SBT_RFCR1__I2SBT_RXCHDT_MASK 0xf +#define ACP_I2SBT_RFCR1__I2SBT_RXCHDT__SHIFT 0x0 +#define ACP_I2SBT_TFCR1__I2SBT_TXCHET_MASK 0xf +#define ACP_I2SBT_TFCR1__I2SBT_TXCHET__SHIFT 0x0 +#define ACP_I2SBT_RFF1__I2SBT_RXCHFR_MASK 0x1 +#define ACP_I2SBT_RFF1__I2SBT_RXCHFR__SHIFT 0x0 +#define ACP_I2SBT_TFF1__I2SBT_TXCHFR_MASK 0x1 +#define ACP_I2SBT_TFF1__I2SBT_TXCHFR__SHIFT 0x0 +#define ACP_I2SBT_RXDMA__I2SBT_RXDMA_MASK 0xffffffff +#define ACP_I2SBT_RXDMA__I2SBT_RXDMA__SHIFT 0x0 +#define ACP_I2SBT_RRXDMA__I2SBT_RRXDMA_MASK 0x1 +#define ACP_I2SBT_RRXDMA__I2SBT_RRXDMA__SHIFT 0x0 +#define ACP_I2SBT_TXDMA__I2SBT_TXDMA_MASK 0xffffffff +#define ACP_I2SBT_TXDMA__I2SBT_TXDMA__SHIFT 0x0 +#define ACP_I2SBT_RTXDMA__I2SBT_RTXDMA_MASK 0x1 +#define ACP_I2SBT_RTXDMA__I2SBT_RTXDMA__SHIFT 0x0 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_0_MASK 0x7 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_0__SHIFT 0x0 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_1_MASK 0x38 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_1__SHIFT 0x3 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_2_MASK 0x380 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_2__SHIFT 0x7 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_3_MASK 0x1c00 +#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_3__SHIFT 0xa +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_APB_DATA_WIDTH_MASK 0x3 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_FIFO_DEPTH_GLOBAL_MASK 0xc +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_FIFO_DEPTH_GLOBAL__SHIFT 0x2 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_MODE_EN_MASK 0x10 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_MODE_EN__SHIFT 0x4 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TRANSMITTER_BLOCK_MASK 0x20 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TRANSMITTER_BLOCK__SHIFT 0x5 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RECEIVER_BLOCK_MASK 0x40 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RECEIVER_BLOCK__SHIFT 0x6 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RX_CHANNLES_MASK 0x180 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RX_CHANNLES__SHIFT 0x7 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_CHANNLES_MASK 0x600 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_CHANNLES__SHIFT 0x9 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_0_MASK 0x70000 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_0__SHIFT 0x10 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_1_MASK 0x380000 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_1__SHIFT 0x13 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_2_MASK 0x1c00000 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_2__SHIFT 0x16 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_3_MASK 0xe000000 +#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_3__SHIFT 0x19 +#define ACP_I2SBT_COMP_VERSION__I2SBT_APB_DATA_WIDTH_MASK 0xffffffff +#define ACP_I2SBT_COMP_VERSION__I2SBT_APB_DATA_WIDTH__SHIFT 0x0 +#define ACP_I2SBT_COMP_TYPE__I2SBT_COMP_TYPE_MASK 0xffffffff +#define ACP_I2SBT_COMP_TYPE__I2SBT_COMP_TYPE__SHIFT 0x0 + +#endif /* ACP_2_2_SH_MASK_H */ diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h new file mode 100644 index 000000000..b602a983f --- /dev/null +++ b/sound/soc/amd/mach-config.h @@ -0,0 +1,39 @@ +/* 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) 2021 Advanced Micro Devices, Inc. All rights reserved. + * + * Author: Ajit Kumar Pandey + */ +#ifndef __AMD_MACH_CONFIG_H +#define __AMD_MACH_CONFIG_H + +#include + +#define FLAG_AMD_SOF BIT(1) +#define FLAG_AMD_SOF_ONLY_DMIC BIT(2) +#define FLAG_AMD_LEGACY BIT(3) +#define FLAG_AMD_LEGACY_ONLY_DMIC BIT(4) + +#define ACP_PCI_DEV_ID 0x15E2 + +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[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp7x_sof_machines[]; + +struct config_entry { + u32 flags; + u16 device; + const struct dmi_system_id *dmi_table; +}; + +#endif diff --git a/sound/soc/amd/ps/Makefile b/sound/soc/amd/ps/Makefile new file mode 100644 index 000000000..778ee4726 --- /dev/null +++ b/sound/soc/amd/ps/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Pink Sardine platform Support +snd-pci-ps-y := pci-ps.o ps-common.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 +obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-sdw-dma.o +obj-$(CONFIG_SND_SOC_AMD_PS_MACH) += snd-soc-ps-mach.o diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h new file mode 100644 index 000000000..62cb6bef1 --- /dev/null +++ b/sound/soc/amd/ps/acp63.h @@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD Common ACP header file for ACP6.3, ACP7.0 & ACP7.1 platforms + * + * Copyright (C) 2022, 2023, 2025 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include +#include + +#define ACP_DEVICE_ID 0x15E2 +#define ACP63_REG_START 0x1240000 +#define ACP63_REG_END 0x125C000 +#define ACP63_PCI_REV 0x63 +#define ACP70_PCI_REV 0x70 +#define ACP71_PCI_REV 0x71 +#define ACP72_PCI_REV 0x72 + +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 +#define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 +#define ACP63_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP63_PGFSM_STATUS_MASK 3 +#define ACP63_POWERED_ON 0 +#define ACP63_POWER_ON_IN_PROGRESS 1 +#define ACP63_POWERED_OFF 2 +#define ACP63_POWER_OFF_IN_PROGRESS 3 + +#define ACP_ERROR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF +#define PDM_DMA_STAT 0x10 + +#define PDM_DMA_INTR_MASK 0x10000 +#define ACP_ERROR_STAT 29 +#define PDM_DECIMATION_FACTOR 2 +#define ACP_PDM_CLK_FREQ_MASK 7 +#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3) +#define ACP_PDM_ENABLE 1 +#define ACP_PDM_DISABLE 0 +#define ACP_PDM_DMA_EN_STATUS 2 +#define TWO_CH 2 +#define DELAY_US 5 +#define ACP_COUNTER 20000 + +#define ACP_SRAM_PTE_OFFSET 0x03800000 +#define PAGE_SIZE_4K_ENABLE 2 +#define PDM_PTE_OFFSET 0 +#define PDM_MEM_WINDOW_START 0x4000000 + +#define CAPTURE_MIN_NUM_PERIODS 4 +#define CAPTURE_MAX_NUM_PERIODS 4 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 4096 + +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER + +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 + +#define ACP_DMIC_DEV 2 + +#define ACP63_DMIC_ADDR 2 +#define ACP63_SDW_ADDR 5 +#define AMD_SDW_MAX_MANAGERS 2 + +/* time in ms for acp timeout */ +#define ACP63_TIMEOUT 500 + +#define ACP_SDW0_STAT BIT(21) +#define ACP_SDW1_STAT BIT(2) +#define ACP_ERROR_IRQ BIT(29) + +#define ACP_AUDIO0_TX_THRESHOLD 0x1c +#define ACP_AUDIO1_TX_THRESHOLD 0x1a +#define ACP_AUDIO2_TX_THRESHOLD 0x18 +#define ACP_AUDIO0_RX_THRESHOLD 0x1b +#define ACP_AUDIO1_RX_THRESHOLD 0x19 +#define ACP_AUDIO2_RX_THRESHOLD 0x17 +#define ACP63_P1_AUDIO1_TX_THRESHOLD BIT(6) +#define ACP63_P1_AUDIO1_RX_THRESHOLD BIT(5) +#define ACP63_SDW_DMA_IRQ_MASK 0x1F800000 +#define ACP63_P1_SDW_DMA_IRQ_MASK 0x60 +#define ACP63_SDW0_DMA_MAX_STREAMS 6 +#define ACP63_SDW1_DMA_MAX_STREAMS 2 +#define ACP63_P1_AUDIO_TX_THRESHOLD 6 + +/* + * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping + * in ACP_EXTENAL_INTR_CNTL register. + * Stream id IRQ Bit + * 0 (SDW0_AUDIO0_TX) 28 + * 1 (SDW0_AUDIO1_TX) 26 + * 2 (SDW0_AUDIO2_TX) 24 + * 3 (SDW0_AUDIO0_RX) 27 + * 4 (SDW0_AUDIO1_RX) 25 + * 5 (SDW0_AUDIO2_RX) 23 + */ +#define ACP63_SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP63_SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) + +/* + * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping + * in ACP_EXTENAL_INTR_CNTL1 register. + * Stream id IRQ Bit + * 0 (SDW1_AUDIO1_TX) 6 + * 1 (SDW1_AUDIO1_RX) 5 + */ +#define ACP63_SDW1_DMA_IRQ_MASK(i) (ACP63_P1_AUDIO_TX_THRESHOLD - (i)) + +#define ACP_DELAY_US 5 +#define ACP_SDW_RING_BUFF_ADDR_OFFSET (128 * 1024) +#define SDW0_MEM_WINDOW_START 0x4800000 +#define ACP_SDW_SRAM_PTE_OFFSET 0x03800400 +#define SDW0_PTE_OFFSET 0x400 +#define SDW_FIFO_SIZE 0x100 +#define SDW_DMA_SIZE 0x40 +#define ACP_SDW0_FIFO_OFFSET 0x100 +#define ACP_SDW_PTE_OFFSET 0x100 +#define SDW_FIFO_OFFSET 0x100 +#define SDW_PTE_OFFSET(i) (SDW0_PTE_OFFSET + ((i) * 0x600)) +#define ACP_SDW_FIFO_OFFSET(i) (ACP_SDW0_FIFO_OFFSET + ((i) * 0x500)) +#define SDW_MEM_WINDOW_START(i) (SDW0_MEM_WINDOW_START + ((i) * 0xC0000)) + +#define SDW_PLAYBACK_MIN_NUM_PERIODS 2 +#define SDW_PLAYBACK_MAX_NUM_PERIODS 8 +#define SDW_PLAYBACK_MAX_PERIOD_SIZE 8192 +#define SDW_PLAYBACK_MIN_PERIOD_SIZE 1024 +#define SDW_CAPTURE_MIN_NUM_PERIODS 2 +#define SDW_CAPTURE_MAX_NUM_PERIODS 8 +#define SDW_CAPTURE_MAX_PERIOD_SIZE 8192 +#define SDW_CAPTURE_MIN_PERIOD_SIZE 1024 + +#define SDW_MAX_BUFFER (SDW_PLAYBACK_MAX_PERIOD_SIZE * SDW_PLAYBACK_MAX_NUM_PERIODS) +#define SDW_MIN_BUFFER SDW_MAX_BUFFER + +#define ACP_HW_OPS(acp_data, cb) ((acp_data)->hw_ops->cb) + +#define ACP70_PGFSM_CNTL_POWER_ON_MASK 0x1F +#define ACP70_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP70_PGFSM_STATUS_MASK 0xFF +#define ACP70_TIMEOUT 2000 +#define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 +#define ACP70_SDW0_HOST_WAKE_STAT BIT(24) +#define ACP70_SDW1_HOST_WAKE_STAT BIT(25) +#define ACP70_SDW0_PME_STAT BIT(26) +#define ACP70_SDW1_PME_STAT BIT(27) + +#define ACP70_SDW0_DMA_MAX_STREAMS 6 +#define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS +#define ACP70_SDW_DMA_IRQ_MASK 0x1F800000 +#define ACP70_P1_SDW_DMA_IRQ_MASK 0x1F8 + +#define ACP70_P1_AUDIO0_TX_THRESHOLD 0x8 +#define ACP70_P1_AUDIO1_TX_THRESHOLD 0x6 +#define ACP70_P1_AUDIO2_TX_THRESHOLD 0x4 +#define ACP70_P1_AUDIO0_RX_THRESHOLD 0x7 +#define ACP70_P1_AUDIO1_RX_THRESHOLD 0x5 +#define ACP70_P1_AUDIO2_RX_THRESHOLD 0x3 + +#define ACP70_SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP70_SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) + +/* + * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping + * in ACP_EXTENAL_INTR_CNTL1 register for ACP70/ACP71 platforms + * Stream id IRQ Bit + * 0 (SDW1_AUDIO0_TX) 8 + * 1 (SDW1_AUDIO1_TX) 6 + * 2 (SDW1_AUDIO2_TX) 4 + * 3 (SDW1_AUDIO0_RX) 7 + * 4 (SDW1_AUDIO1_RX) 5 + * 5 (SDW1_AUDIO2_RX) 3 + */ +#define ACP70_SDW1_DMA_TX_IRQ_MASK(i) (ACP70_P1_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP70_SDW1_DMA_RX_IRQ_MASK(i) (ACP70_P1_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) + +#define ACP70_SW0_AUDIO0_TX_EN ACP_SW0_AUDIO0_TX_EN +#define ACP70_SW0_AUDIO1_TX_EN ACP_SW0_AUDIO1_TX_EN +#define ACP70_SW0_AUDIO2_TX_EN ACP_SW0_AUDIO2_TX_EN +#define ACP70_SW0_AUDIO0_RX_EN ACP_SW0_AUDIO0_RX_EN +#define ACP70_SW0_AUDIO1_RX_EN ACP_SW0_AUDIO1_RX_EN +#define ACP70_SW0_AUDIO2_RX_EN ACP_SW0_AUDIO2_RX_EN + +#define ACP70_SW1_AUDIO0_TX_EN 0x0003C10 +#define ACP70_SW1_AUDIO1_TX_EN 0x0003C50 +#define ACP70_SW1_AUDIO2_TX_EN 0x0003C6C +#define ACP70_SW1_AUDIO0_RX_EN 0x0003C88 +#define ACP70_SW1_AUDIO1_RX_EN 0x0003D28 +#define ACP70_SW1_AUDIO2_RX_EN 0x0003D44 + +enum acp_config { + ACP_CONFIG_0 = 0, + ACP_CONFIG_1, + ACP_CONFIG_2, + ACP_CONFIG_3, + ACP_CONFIG_4, + ACP_CONFIG_5, + ACP_CONFIG_6, + ACP_CONFIG_7, + ACP_CONFIG_8, + ACP_CONFIG_9, + ACP_CONFIG_10, + ACP_CONFIG_11, + ACP_CONFIG_12, + ACP_CONFIG_13, + ACP_CONFIG_14, + ACP_CONFIG_15, + ACP_CONFIG_16, + ACP_CONFIG_17, + ACP_CONFIG_18, + ACP_CONFIG_19, + ACP_CONFIG_20, +}; + +enum amd_acp63_sdw0_channel { + ACP63_SDW0_AUDIO0_TX = 0, + ACP63_SDW0_AUDIO1_TX, + ACP63_SDW0_AUDIO2_TX, + ACP63_SDW0_AUDIO0_RX, + ACP63_SDW0_AUDIO1_RX, + ACP63_SDW0_AUDIO2_RX, +}; + +enum amd_acp63_sdw1_channel { + ACP63_SDW1_AUDIO1_TX, + ACP63_SDW1_AUDIO1_RX, +}; + +enum amd_acp70_sdw_channel { + ACP70_SDW_AUDIO0_TX = 0, + ACP70_SDW_AUDIO1_TX, + ACP70_SDW_AUDIO2_TX, + ACP70_SDW_AUDIO0_RX, + ACP70_SDW_AUDIO1_RX, + ACP70_SDW_AUDIO2_RX, +}; + +struct pdm_stream_instance { + u16 num_pages; + u16 channels; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp63_base; +}; + +struct pdm_dev_data { + u32 pdm_irq; + void __iomem *acp63_base; + struct mutex *acp_lock; + struct snd_pcm_substream *capture_stream; +}; + +struct sdw_dma_dev_data { + void __iomem *acp_base; + struct mutex *acp_lock; /* used to protect acp common register access */ + u32 acp_rev; + struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp70_sdw0_dma_stream[ACP70_SDW0_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp70_sdw1_dma_stream[ACP70_SDW1_DMA_MAX_STREAMS]; +}; + +struct acp_sdw_dma_stream { + u16 num_pages; + u16 channels; + u32 stream_id; + u32 instance; + dma_addr_t dma_addr; + u64 bytescount; +}; + +union acp_sdw_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +struct sdw_dma_ring_buf_reg { + u32 reg_dma_size; + u32 reg_fifo_addr; + u32 reg_fifo_size; + u32 reg_ring_buf_size; + u32 reg_ring_buf_addr; + u32 water_mark_size_reg; + u32 pos_low_reg; + u32 pos_high_reg; +}; + +struct acp63_dev_data; + +/** + * struct acp_hw_ops - ACP PCI driver platform specific ops + * @acp_init: ACP initialization + * @acp_deinit: ACP de-initialization + * @acp_get_config: function to read the acp pin configuration + * @acp_sdw_dma_irq_thread: ACP SoundWire DMA interrupt thread + * acp_suspend: ACP system level suspend callback + * acp_resume: ACP system level resume callback + * acp_suspend_runtime: ACP runtime suspend callback + * acp_resume_runtime: ACP runtime resume callback + */ +struct acp_hw_ops { + int (*acp_init)(void __iomem *acp_base, struct device *dev); + int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + void (*acp_get_config)(struct pci_dev *pci, struct acp63_dev_data *acp_data); + void (*acp_sdw_dma_irq_thread)(struct acp63_dev_data *acp_data); + int (*acp_suspend)(struct device *dev); + int (*acp_resume)(struct device *dev); + int (*acp_suspend_runtime)(struct device *dev); + int (*acp_resume_runtime)(struct device *dev); +}; + +/** + * struct acp63_dev_data - acp pci driver context + * @acp63_base: acp mmio base + * @res: resource + * @hw_ops: ACP pci driver platform-specific ops + * @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 + * @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 + * @acp70_sdw0_wake_event: flag set to true when wake irq asserted for SW0 instance + * @acp70_sdw1_wake_event: flag set to true when wake irq asserted for SW1 instance + * @addr: pci ioremap address + * @reg_range: ACP reigister range + * @acp_rev: ACP PCI revision id + * @acp_sw_pad_keeper_en: store acp SoundWire pad keeper enable register value + * @acp_pad_pulldown_ctrl: store acp pad pulldown control register value + * @acp63_sdw0-dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW0 instance + * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW1 instance + * @acp70_sdw0-dma_intr_stat: DMA interrupt status array for ACP7.0 platform SoundWire + * manager-SW0 instance + * @acp70_sdw_dma_intr_stat: DMA interrupt status array for ACP7.0 platform SoundWire + * manager-SW1 instance + */ + +struct acp63_dev_data { + void __iomem *acp63_base; + struct resource *res; + struct acp_hw_ops *hw_ops; + 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 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; + bool acp70_sdw0_wake_event; + bool acp70_sdw1_wake_event; + u32 addr; + u32 reg_range; + u32 acp_rev; + u32 subsystem_vendor; + u32 subsystem_device; + u32 acp_sw_pad_keeper_en; + u32 acp_pad_pulldown_ctrl; + u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; + u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; + u16 acp70_sdw0_dma_intr_stat[ACP70_SDW0_DMA_MAX_STREAMS]; + u16 acp70_sdw1_dma_intr_stat[ACP70_SDW1_DMA_MAX_STREAMS]; +}; + +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops); +void acp70_hw_init_ops(struct acp_hw_ops *hw_ops); + +static inline int acp_hw_init(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_init) + return ACP_HW_OPS(adata, acp_init)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_deinit) + return ACP_HW_OPS(adata, acp_deinit)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + +static inline void acp_hw_get_config(struct pci_dev *pci, struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_get_config) + ACP_HW_OPS(adata, acp_get_config)(pci, adata); +} + +static inline void acp_hw_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_sdw_dma_irq_thread) + ACP_HW_OPS(adata, acp_sdw_dma_irq_thread)(adata); +} + +static inline int acp_hw_suspend(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend) + return ACP_HW_OPS(adata, acp_suspend)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume) + return ACP_HW_OPS(adata, acp_resume)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend_runtime(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime) + return ACP_HW_OPS(adata, acp_suspend_runtime)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime) + return ACP_HW_OPS(adata, acp_resume_runtime)(dev); + return -EOPNOTSUPP; +} + +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 new file mode 100644 index 000000000..729f9aaba --- /dev/null +++ b/sound/soc/amd/ps/pci-ps.c @@ -0,0 +1,785 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD common ACP PCI driver for ACP6.3, ACP7.0 & ACP7.1 platforms. + * + * Copyright 2022, 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../mach-config.h" + +#include "acp63.h" + +static void handle_acp70_sdw_wake_event(struct acp63_dev_data *adata) +{ + struct amd_sdw_manager *amd_manager; + + if (adata->acp70_sdw0_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw0_wake_event = 0; + } + + if (adata->acp70_sdw1_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw1_wake_event = 0; + } +} + +static short int check_and_handle_acp70_sdw_wake_irq(struct acp63_dev_data *adata) +{ + u32 ext_intr_stat1; + int irq_flag = 0; + bool sdw_wake_irq = false; + + ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) { + writel(ACP70_SDW0_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) { + writel(ACP70_SDW1_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) { + writel(0, adata->acp63_base + ACP_SW0_WAKE_EN); + writel(ACP70_SDW0_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) { + writel(0, adata->acp63_base + ACP_SW1_WAKE_EN); + writel(ACP70_SDW1_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (sdw_wake_irq) { + handle_acp70_sdw_wake_event(adata); + irq_flag = 1; + } + return irq_flag; +} + +static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat, + u32 ext_intr_stat1) +{ + u32 stream_id = 0; + u16 sdw_dma_irq_flag = 0; + u16 index; + + if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { + for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { + if (ext_intr_stat & BIT(index)) { + writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); + switch (index) { + case ACP_AUDIO0_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_TX; + break; + case ACP_AUDIO1_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_TX; + break; + case ACP_AUDIO2_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_TX; + break; + case ACP_AUDIO0_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_RX; + break; + case ACP_AUDIO1_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_RX; + break; + case ACP_AUDIO2_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_RX; + break; + } + switch (adata->acp_rev) { + case ACP63_PCI_REV: + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + adata->acp70_sdw0_dma_intr_stat[stream_id] = 1; + break; + } + sdw_dma_irq_flag = 1; + } + } + } + switch (adata->acp_rev) { + case ACP63_PCI_REV: + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; + sdw_dma_irq_flag = 1; + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; + sdw_dma_irq_flag = 1; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + if (ext_intr_stat1 & ACP70_P1_SDW_DMA_IRQ_MASK) { + for (index = ACP70_P1_AUDIO2_RX_THRESHOLD; + index <= ACP70_P1_AUDIO0_TX_THRESHOLD; index++) { + if (ext_intr_stat1 & BIT(index)) { + writel(BIT(index), + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + switch (index) { + case ACP70_P1_AUDIO0_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO0_TX; + break; + case ACP70_P1_AUDIO1_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO1_TX; + break; + case ACP70_P1_AUDIO2_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO2_TX; + break; + case ACP70_P1_AUDIO0_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO0_RX; + break; + case ACP70_P1_AUDIO1_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO1_RX; + break; + case ACP70_P1_AUDIO2_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO2_RX; + break; + } + + adata->acp70_sdw1_dma_intr_stat[stream_id] = 1; + sdw_dma_irq_flag = 1; + } + } + } + break; + } + return sdw_dma_irq_flag; +} + +static irqreturn_t acp63_irq_thread(int irq, void *context) +{ + struct acp63_dev_data *adata = context; + + acp_hw_sdw_dma_irq_thread(adata); + return IRQ_HANDLED; +} + +static irqreturn_t acp63_irq_handler(int irq, void *dev_id) +{ + struct acp63_dev_data *adata; + struct pdm_dev_data *ps_pdm_data; + struct amd_sdw_manager *amd_manager; + u32 ext_intr_stat, ext_intr_stat1; + u16 irq_flag = 0; + u16 wake_irq_flag = 0; + u16 sdw_dma_irq_flag = 0; + + adata = dev_id; + if (!adata) + return IRQ_NONE; + /* ACP interrupts will be cleared by reading particular bit and writing + * same value to the status register. writing zero's doesn't have any + * effect. + * Bit by bit checking of IRQ field is implemented. + */ + 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); + amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev); + if (amd_manager) + schedule_work(&amd_manager->amd_sdw_irq_thread); + irq_flag = 1; + } + + 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); + amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev); + if (amd_manager) + schedule_work(&amd_manager->amd_sdw_irq_thread); + irq_flag = 1; + } + + if (ext_intr_stat & ACP_ERROR_IRQ) { + writel(ACP_ERROR_IRQ, adata->acp63_base + ACP_EXTERNAL_INTR_STAT); + /* TODO: Report SoundWire Manager instance errors */ + writel(0, adata->acp63_base + ACP_SW0_I2S_ERROR_REASON); + writel(0, adata->acp63_base + ACP_SW1_I2S_ERROR_REASON); + writel(0, adata->acp63_base + ACP_ERROR_STATUS); + irq_flag = 1; + } + + if (adata->acp_rev >= ACP70_PCI_REV) + wake_irq_flag = check_and_handle_acp70_sdw_wake_irq(adata); + + if (ext_intr_stat & BIT(PDM_DMA_STAT)) { + 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); + irq_flag = 1; + } + + sdw_dma_irq_flag = check_and_handle_sdw_dma_irq(adata, ext_intr_stat, ext_intr_stat1); + if (sdw_dma_irq_flag) + return IRQ_WAKE_THREAD; + + if (irq_flag || wake_irq_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +#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; + + 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); + 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; +} + +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) + if (!mach->machine_check || mach->machine_check(acp_data->sdw)) + 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; + mach->mach_params.subsystem_vendor = acp_data->subsystem_vendor; + mach->mach_params.subsystem_device = acp_data->subsystem_device; + mach->mach_params.subsystem_id_set = true; + + dev_dbg(dev, "SSID %x%04x\n", mach->mach_params.subsystem_vendor, + mach->mach_params.subsystem_device); + 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; +} + +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(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + struct acpi_device *pdm_dev; + const union acpi_object *obj; + acpi_handle handle; + acpi_integer dmic_status; + bool is_dmic_dev = false; + bool is_sdw_dev = false; + bool wov_en, dmic_en; + int ret; + + /* IF WOV entry not found, enable dmic based on acp-audio-device-type entry*/ + wov_en = true; + dmic_en = false; + + acp_hw_get_config(pci, acp_data); + + 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; +} + +static void acp63_fill_platform_dev_info(struct platform_device_info *pdevinfo, + struct device *parent, + struct fwnode_handle *fw_node, + char *name, unsigned int id, + const struct resource *res, + unsigned int num_res, + const void *data, + size_t size_data) +{ + pdevinfo->name = name; + pdevinfo->id = id; + pdevinfo->parent = parent; + pdevinfo->num_res = num_res; + pdevinfo->res = res; + pdevinfo->data = data; + pdevinfo->size_data = size_data; + pdevinfo->fwnode = fw_node; +} + +static int create_acp63_platform_devs(struct pci_dev *pci, struct acp63_dev_data *adata, u32 addr) +{ + struct platform_device_info pdevinfo; + struct device *parent; + int ret; + + parent = &pci->dev; + + 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; + goto de_init; + } + adata->res->flags = IORESOURCE_MEM; + adata->res->start = addr; + adata->res->end = addr + (ACP63_REG_END - ACP63_REG_START); + memset(&pdevinfo, 0, sizeof(pdevinfo)); + } + + 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); + + 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; + } + 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; + } + } + 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); + + 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.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_dmic_codec_dev: + platform_device_unregister(adata->dmic_codec_dev); +unregister_pdm_dev: + platform_device_unregister(adata->pdm_dev); +de_init: + if (acp_hw_deinit(adata, &pci->dev)) + dev_err(&pci->dev, "ACP de-init failed\n"); + return ret; +} + +static int acp_hw_init_ops(struct acp63_dev_data *adata, struct pci_dev *pci) +{ + adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops), + GFP_KERNEL); + if (!adata->hw_ops) + return -ENOMEM; + + switch (adata->acp_rev) { + case ACP63_PCI_REV: + acp63_hw_init_ops(adata->hw_ops); + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + acp70_hw_init_ops(adata->hw_ops); + break; + default: + dev_err(&pci->dev, "ACP device not found\n"); + return -ENODEV; + } + return 0; +} + +static int snd_acp63_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp63_dev_data *adata; + u32 addr; + u32 irqflags, flag; + int ret; + + irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + + /* ACP PCI revision id check for ACP6.3, ACP7.0 & ACP7.1 platforms */ + switch (pci->revision) { + case ACP63_PCI_REV: + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + break; + default: + dev_dbg(&pci->dev, "acp63/acp70/acp71 pci device not found\n"); + return -ENODEV; + } + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + adata = devm_kzalloc(&pci->dev, sizeof(struct acp63_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + + addr = pci_resource_start(pci, 0); + adata->acp63_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp63_base) { + ret = -ENOMEM; + goto release_regions; + } + adata->addr = addr; + adata->reg_range = ACP63_REG_END - ACP63_REG_START; + adata->acp_rev = pci->revision; + adata->subsystem_vendor = pci->subsystem_vendor; + adata->subsystem_device = pci->subsystem_device; + + pci_set_master(pci); + pci_set_drvdata(pci, adata); + mutex_init(&adata->acp_lock); + ret = acp_hw_init_ops(adata, pci); + if (ret) { + dev_err(&pci->dev, "ACP hw ops init failed\n"); + goto release_regions; + } + ret = acp_hw_init(adata, &pci->dev); + if (ret) + goto release_regions; + ret = devm_request_threaded_irq(&pci->dev, pci->irq, acp63_irq_handler, + acp63_irq_thread, irqflags, "ACP_PCI_IRQ", adata); + if (ret) { + dev_err(&pci->dev, "ACP PCI IRQ request failed\n"); + goto de_init; + } + 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); + goto skip_pdev_creation; + } + ret = create_acp63_platform_devs(pci, adata, addr); + if (ret < 0) { + dev_err(&pci->dev, "ACP platform devices creation failed\n"); + goto de_init; + } + if (adata->acp_rev >= ACP70_PCI_REV) + adata->machines = snd_soc_acpi_amd_acp70_sdw_machines; + else + 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); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; +de_init: + if (acp_hw_deinit(adata, &pci->dev)) + dev_err(&pci->dev, "ACP de-init failed\n"); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int snd_acp_suspend(struct device *dev) +{ + return acp_hw_suspend(dev); +} + +static int snd_acp_runtime_resume(struct device *dev) +{ + return acp_hw_runtime_resume(dev); +} + +static void acp_disable_msi_on_resume(struct pci_dev *pdev) +{ + u16 control; + + if (!pdev->msi_cap) + return; + + pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &control); + if (control & PCI_MSI_FLAGS_ENABLE) { + dev_warn(&pdev->dev, + "ACP: MSI unexpectedly enabled after resume (flags=0x%04x), disabling\n", + control); + control &= ~PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, control); + } +} + +static int snd_acp_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + /* + * BIOS/firmware may re-enable MSI in PCI config space during + * system resume even though this driver only uses legacy INTx + * interrupts. If MSI is left enabled with stale address/data + * registers, the device will write interrupts to a bogus address + * causing IOMMU IO_PAGE_FAULT and interrupt delivery failure. + * Explicitly clear the MSI Enable bit before reinitializing + * the ACP hardware. + */ + acp_disable_msi_on_resume(pdev); + return acp_hw_resume(dev); +} + +static const struct dev_pm_ops acp63_pm_ops = { + RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) +}; + +static void snd_acp63_remove(struct pci_dev *pci) +{ + struct acp63_dev_data *adata; + int ret; + + adata = pci_get_drvdata(pci); + 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 = acp_hw_deinit(adata, &pci->dev); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp63_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp63_ids); + +static struct pci_driver ps_acp63_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp63_ids, + .probe = snd_acp63_probe, + .remove = snd_acp63_remove, + .driver = { + .pm = pm_ptr(&acp63_pm_ops), + } +}; + +module_pci_driver(ps_acp63_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_AUTHOR("Syed.SabaKareem@amd.com"); +MODULE_DESCRIPTION("AMD common ACP PCI driver for ACP6.3, ACP7.0 & ACP7.1 platforms"); +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-common.c b/sound/soc/amd/ps/ps-common.c new file mode 100644 index 000000000..7b4966b75 --- /dev/null +++ b/sound/soc/amd/ps/ps-common.c @@ -0,0 +1,493 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1 + * platforms. + * + * Copyright 2025 Advanced Micro Devices, Inc. + * Authors: Vijendar Mukunda + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp63.h" + +static int acp63_power_on(void __iomem *acp_base) +{ + u32 val; + + val = readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return val; + + if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) + writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static int acp63_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP63_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static void acp63_enable_interrupts(void __iomem *acp_base) +{ + writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void acp63_disable_interrupts(void __iomem *acp_base) +{ + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); + writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); + writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp63_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp63_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + acp63_enable_interrupts(acp_base); + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int acp63_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + acp63_disable_interrupts(acp_base); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_CONTROL); + writel(1, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + u32 config; + + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); + dev_dbg(&pci->dev, "ACP config value: %d\n", config); + switch (config) { + case ACP_CONFIG_4: + case ACP_CONFIG_5: + case ACP_CONFIG_10: + case ACP_CONFIG_11: + acp_data->is_pdm_config = true; + break; + case ACP_CONFIG_2: + case ACP_CONFIG_3: + acp_data->is_sdw_config = true; + break; + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_12: + case ACP_CONFIG_8: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + acp_data->is_pdm_config = true; + acp_data->is_sdw_config = true; + break; + default: + break; + } +} + +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; + + adata = dev_get_drvdata(dev); + if (adata->is_sdw_dev) { + adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); + 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 = acp_hw_deinit(adata, 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 = acp_hw_init(adata, 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; + u32 acp_sw_pad_keeper_en; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en); + if (!acp_sw_pad_keeper_en) { + writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); + } + return ret; +} + +static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + struct sdw_dma_dev_data *sdw_data; + u32 stream_id; + + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + + for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); + adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; + } + } + for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); + adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; + } + } +} + +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp63_init; + hw_ops->acp_deinit = acp63_deinit; + hw_ops->acp_get_config = acp63_get_config; + hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread; + hw_ops->acp_suspend = snd_acp63_suspend; + hw_ops->acp_resume = snd_acp63_resume; + hw_ops->acp_suspend_runtime = snd_acp63_suspend; + hw_ops->acp_resume_runtime = snd_acp63_runtime_resume; +} + +static int acp70_power_on(void __iomem *acp_base) +{ + u32 val = 0; + + val = readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return 0; + if (val & ACP70_PGFSM_STATUS_MASK) + writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT); +} + +static int acp70_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP70_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT); +} + +static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base) +{ + u32 ext_intr_cntl1; + + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK; + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); +} + +static void acp70_enable_interrupts(void __iomem *acp_base) +{ + u32 sdw0_wake_en, sdw1_wake_en; + + writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); + sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN); + sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN); + if (sdw0_wake_en || sdw1_wake_en) + acp70_enable_sdw_host_wake_interrupts(acp_base); +} + +static void acp70_disable_interrupts(void __iomem *acp_base) +{ + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); + writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); + writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp70_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp70_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp70_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + acp70_enable_interrupts(acp_base); + writel(0x1, acp_base + ACP_PME_EN); + return 0; +} + +static int acp70_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + acp70_disable_interrupts(acp_base); + ret = acp70_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + u32 config; + + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); + dev_dbg(&pci->dev, "ACP config value: %d\n", config); + switch (config) { + case ACP_CONFIG_4: + case ACP_CONFIG_5: + case ACP_CONFIG_10: + case ACP_CONFIG_11: + case ACP_CONFIG_20: + acp_data->is_pdm_config = true; + break; + case ACP_CONFIG_2: + case ACP_CONFIG_3: + case ACP_CONFIG_16: + acp_data->is_sdw_config = true; + break; + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_12: + case ACP_CONFIG_8: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + case ACP_CONFIG_17: + case ACP_CONFIG_18: + case ACP_CONFIG_19: + acp_data->is_pdm_config = true; + acp_data->is_sdw_config = true; + break; + default: + break; + } +} + +static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + struct sdw_dma_dev_data *sdw_data; + u32 stream_id; + + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + + for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp70_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp70_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]); + adata->acp70_sdw0_dma_intr_stat[stream_id] = 0; + } + } + for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp70_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp70_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]); + adata->acp70_sdw1_dma_intr_stat[stream_id] = 0; + } + } +} + +static int __maybe_unused snd_acp70_suspend(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->is_sdw_dev) { + adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); + 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 = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + + return ret; +} + +static int __maybe_unused snd_acp70_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); + writel(1, adata->acp63_base + ACP_PME_EN); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static int __maybe_unused snd_acp70_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + u32 acp_sw_pad_keeper_en; + int ret; + + adata = dev_get_drvdata(dev); + + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + writel(1, adata->acp63_base + ACP_PME_EN); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en); + if (!acp_sw_pad_keeper_en) { + writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); + writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); + } + return ret; +} + +void acp70_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp70_init; + hw_ops->acp_deinit = acp70_deinit; + hw_ops->acp_get_config = acp70_get_config; + hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread; + hw_ops->acp_suspend = snd_acp70_suspend; + hw_ops->acp_resume = snd_acp70_resume; + hw_ops->acp_suspend_runtime = snd_acp70_suspend; + hw_ops->acp_resume_runtime = snd_acp70_runtime_resume; +} diff --git a/sound/soc/amd/ps/ps-mach.c b/sound/soc/amd/ps/ps-mach.c new file mode 100644 index 000000000..3e49c255c --- /dev/null +++ b/sound/soc/amd/ps/ps-mach.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Machine driver for AMD Pink Sardine platform using DMIC + * + * Copyright 2022 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acp63.h" + +#define DRV_NAME "acp_ps_mach" + +SND_SOC_DAILINK_DEF(acp63_pdm, + DAILINK_COMP_ARRAY(COMP_CPU("acp_ps_pdm_dma.0"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0", + "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(pdm_platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_ps_pdm_dma.0"))); + +static struct snd_soc_dai_link acp63_dai_pdm[] = { + { + .name = "acp63-dmic-capture", + .stream_name = "DMIC capture", + .capture_only = 1, + SND_SOC_DAILINK_REG(acp63_pdm, dmic_codec, pdm_platform), + }, +}; + +static struct snd_soc_card acp63_card = { + .name = "acp63", + .owner = THIS_MODULE, + .dai_link = acp63_dai_pdm, + .num_links = 1, +}; + +static int acp63_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card; + int ret; + + platform_set_drvdata(pdev, &acp63_card); + card = platform_get_drvdata(pdev); + acp63_card.dev = &pdev->dev; + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "snd_soc_register_card(%s) failed\n", + card->name); + } + + return 0; +} + +static struct platform_driver acp63_mach_driver = { + .driver = { + .name = "acp_ps_mach", + .pm = &snd_soc_pm_ops, + }, + .probe = acp63_probe, +}; + +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 new file mode 100644 index 000000000..04c014349 --- /dev/null +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ALSA SoC common PDM Driver for ACP6.3, ACP7.0 & ACP7.1 platforms. + * + * Copyright 2022, 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp63.h" + +#define DRV_NAME "acp_ps_pdm_dma" + +static int pdm_gain = 3; +module_param(pdm_gain, int, 0644); +MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)"); + +static const struct snd_pcm_hardware acp63_pdm_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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .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, +}; + +static void acp63_init_pdm_ring_buffer(u32 physical_addr, u32 buffer_size, + u32 watermark_size, void __iomem *acp_base) +{ + writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR); + writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE); + writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); +} + +static void acp63_enable_pdm_clock(void __iomem *acp_base) +{ + u32 pdm_clk_enable, pdm_ctrl; + + pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; + pdm_ctrl = 0x00; + + writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); + pdm_ctrl = readl(acp_base + ACP_WOV_MISC_CTRL); + pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL; + pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3)); + writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL); +} + +static void acp63_enable_pdm_interrupts(struct pdm_dev_data *adata) +{ + u32 ext_int_ctrl; + + mutex_lock(adata->acp_lock); + ext_int_ctrl = readl(adata->acp63_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + writel(ext_int_ctrl, adata->acp63_base + ACP_EXTERNAL_INTR_CNTL); + mutex_unlock(adata->acp_lock); +} + +static void acp63_disable_pdm_interrupts(struct pdm_dev_data *adata) +{ + u32 ext_int_ctrl; + + mutex_lock(adata->acp_lock); + ext_int_ctrl = readl(adata->acp63_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl &= ~PDM_DMA_INTR_MASK; + writel(ext_int_ctrl, adata->acp63_base + ACP_EXTERNAL_INTR_CNTL); + mutex_unlock(adata->acp_lock); +} + +static bool acp63_check_pdm_dma_status(void __iomem *acp_base) +{ + bool pdm_dma_status; + u32 pdm_enable, pdm_dma_enable; + + pdm_dma_status = false; + pdm_enable = readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & ACP_PDM_DMA_EN_STATUS)) + pdm_dma_status = true; + + return pdm_dma_status; +} + +static int acp63_start_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable; + u32 pdm_dma_enable; + int timeout; + + pdm_enable = 0x01; + pdm_dma_enable = 0x01; + + acp63_enable_pdm_clock(acp_base); + writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS) + return 0; + udelay(DELAY_US); + } + return -ETIMEDOUT; +} + +static int acp63_stop_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable, pdm_dma_enable; + int timeout; + + pdm_enable = 0x00; + pdm_dma_enable = 0x00; + + pdm_enable = readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if (pdm_dma_enable & 0x01) { + pdm_dma_enable = 0x02; + writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == 0x00) + break; + udelay(DELAY_US); + } + if (timeout == ACP_COUNTER) + return -ETIMEDOUT; + } + if (pdm_enable == ACP_PDM_ENABLE) { + pdm_enable = ACP_PDM_DISABLE; + writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + } + writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH); + return 0; +} + +static void acp63_config_dma(struct pdm_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val; + dma_addr_t addr; + + addr = rtd->dma_addr; + val = PDM_PTE_OFFSET; + + /* Group Enable */ + writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp63_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + writel(PAGE_SIZE_4K_ENABLE, rtd->acp63_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + writel(low, rtd->acp63_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + writel(high, rtd->acp63_base + ACP_SCRATCH_REG_0 + val + 4); + val += 8; + addr += PAGE_SIZE; + } +} + +static int acp63_pdm_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct pdm_dev_data *adata; + struct pdm_stream_instance *pdm_data; + int ret; + + runtime = substream->runtime; + adata = dev_get_drvdata(component->dev); + pdm_data = kzalloc_obj(*pdm_data); + if (!pdm_data) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw = acp63_pdm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(pdm_data); + return ret; + } + + acp63_enable_pdm_interrupts(adata); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + adata->capture_stream = substream; + + pdm_data->acp63_base = adata->acp63_base; + runtime->private_data = pdm_data; + return ret; +} + +static int acp63_pdm_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct pdm_stream_instance *rtd; + size_t size, period_bytes; + + rtd = substream->runtime->private_data; + if (!rtd) + return -EINVAL; + size = params_buffer_bytes(params); + period_bytes = params_period_bytes(params); + rtd->dma_addr = substream->runtime->dma_addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + acp63_config_dma(rtd, substream->stream); + acp63_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, size, + period_bytes, rtd->acp63_base); + return 0; +} + +static u64 acp63_pdm_get_byte_count(struct pdm_stream_instance *rtd, + int direction) +{ + u32 high, low; + u64 byte_count; + + high = readl(rtd->acp63_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + byte_count = high; + low = readl(rtd->acp63_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + byte_count = (byte_count << 32) | low; + return byte_count; +} + +static snd_pcm_uframes_t acp63_pdm_dma_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *stream) +{ + struct pdm_stream_instance *rtd; + u32 pos, buffersize; + u64 bytescount; + + rtd = stream->runtime->private_data; + buffersize = frames_to_bytes(stream->runtime, + stream->runtime->buffer_size); + bytescount = acp63_pdm_get_byte_count(rtd, stream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(stream->runtime, pos); +} + +static int acp63_pdm_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp63_pdm_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); + struct snd_pcm_runtime *runtime = substream->runtime; + + acp63_disable_pdm_interrupts(adata); + adata->capture_stream = NULL; + kfree(runtime->private_data); + return 0; +} + +static int acp63_pdm_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct pdm_stream_instance *rtd; + int ret; + bool pdm_status; + unsigned int ch_mask; + + rtd = substream->runtime->private_data; + ret = 0; + switch (substream->runtime->channels) { + case TWO_CH: + ch_mask = 0x00; + break; + default: + return -EINVAL; + } + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + writel(ch_mask, rtd->acp63_base + ACP_WOV_PDM_NO_OF_CHANNELS); + writel(PDM_DECIMATION_FACTOR, rtd->acp63_base + ACP_WOV_PDM_DECIMATION_FACTOR); + rtd->bytescount = acp63_pdm_get_byte_count(rtd, substream->stream); + pdm_status = acp63_check_pdm_dma_status(rtd->acp63_base); + if (!pdm_status) + ret = acp63_start_pdm_dma(rtd->acp63_base); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pdm_status = acp63_check_pdm_dma_status(rtd->acp63_base); + if (pdm_status) + ret = acp63_stop_pdm_dma(rtd->acp63_base); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static const struct snd_soc_dai_ops acp63_pdm_dai_ops = { + .trigger = acp63_pdm_dai_trigger, +}; + +static struct snd_soc_dai_driver acp63_pdm_dai_driver = { + .name = "acp_ps_pdm_dma.0", + .capture = { + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 48000, + .rate_max = 48000, + }, + .ops = &acp63_pdm_dai_ops, +}; + +static const struct snd_soc_component_driver acp63_pdm_component = { + .name = DRV_NAME, + .open = acp63_pdm_dma_open, + .close = acp63_pdm_dma_close, + .hw_params = acp63_pdm_dma_hw_params, + .pointer = acp63_pdm_dma_pointer, + .pcm_new = acp63_pdm_dma_new, + .use_dai_pcm_id = true, +}; + +static int acp63_pdm_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct pdm_dev_data *adata; + struct acp63_dev_data *acp_data; + struct device *parent; + int status; + + parent = pdev->dev.parent; + acp_data = dev_get_drvdata(parent); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp63_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!adata->acp63_base) + return -ENOMEM; + + adata->capture_stream = NULL; + adata->acp_lock = &acp_data->acp_lock; + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp63_pdm_component, + &acp63_pdm_dai_driver, 1); + if (status) { + dev_err(&pdev->dev, "Fail to register acp pdm dai\n"); + + return -ENODEV; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp63_pdm_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp63_pdm_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + struct snd_pcm_runtime *runtime; + struct pdm_stream_instance *rtd; + u32 period_bytes, buffer_len; + + adata = dev_get_drvdata(dev); + if (adata->capture_stream && adata->capture_stream->runtime) { + runtime = adata->capture_stream->runtime; + rtd = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + acp63_config_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + acp63_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, buffer_len, + period_bytes, adata->acp63_base); + } + acp63_enable_pdm_interrupts(adata); + return 0; +} + +static int acp63_pdm_suspend(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp63_disable_pdm_interrupts(adata); + return 0; +} + +static int acp63_pdm_runtime_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp63_enable_pdm_interrupts(adata); + return 0; +} + +static const struct dev_pm_ops acp63_pdm_pm_ops = { + RUNTIME_PM_OPS(acp63_pdm_suspend, acp63_pdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp63_pdm_suspend, acp63_pdm_resume) +}; + +static struct platform_driver acp63_pdm_dma_driver = { + .probe = acp63_pdm_audio_probe, + .remove = acp63_pdm_audio_remove, + .driver = { + .name = "acp_ps_pdm_dma", + .pm = pm_ptr(&acp63_pdm_pm_ops), + }, +}; + +module_platform_driver(acp63_pdm_dma_driver); + +MODULE_AUTHOR("Syed.SabaKareem@amd.com"); +MODULE_DESCRIPTION("AMD common PDM Driver for ACP6.3, ACP7,0 & ACP7.1 platforms"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c new file mode 100644 index 000000000..f27ebbd21 --- /dev/null +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -0,0 +1,804 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ALSA SoC common SoundWire DMA Driver for ACP6.3, ACP7.0 and ACP7.1 + * platforms. + * + * Copyright 2023, 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acp63.h" + +#define DRV_NAME "amd_ps_sdw_dma" + +static struct sdw_dma_ring_buf_reg acp63_sdw0_dma_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { + {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, + ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE, + ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE, + ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE, + ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE, + ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE, + ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} +}; + +/* + * SDW1 instance supports one TX stream and one RX stream. + * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register + * set as per hardware register documentation + */ +static struct sdw_dma_ring_buf_reg acp63_sdw1_dma_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { + {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, + ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, + ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE, + ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR, + ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, +}; + +static u32 acp63_sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { + ACP_SW0_AUDIO0_TX_EN, + ACP_SW0_AUDIO1_TX_EN, + ACP_SW0_AUDIO2_TX_EN, + ACP_SW0_AUDIO0_RX_EN, + ACP_SW0_AUDIO1_RX_EN, + ACP_SW0_AUDIO2_RX_EN, +}; + +/* + * SDW1 instance supports one TX stream and one RX stream. + * For TX/RX streams DMA enable register programming for SDW1 instance, + * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers + * as per hardware register documentation. + */ +static u32 acp63_sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { + ACP_SW1_AUDIO1_TX_EN, + ACP_SW1_AUDIO1_RX_EN, +}; + +static struct sdw_dma_ring_buf_reg acp70_sdw0_dma_reg[ACP70_SDW0_DMA_MAX_STREAMS] = { + {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, + ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE, + ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE, + ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE, + ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE, + ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE, + ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} +}; + +static struct sdw_dma_ring_buf_reg acp70_sdw1_dma_reg[ACP70_SDW1_DMA_MAX_STREAMS] = { + {ACP_P1_AUDIO0_TX_DMA_SIZE, ACP_P1_AUDIO0_TX_FIFOADDR, ACP_P1_AUDIO0_TX_FIFOSIZE, + ACP_P1_AUDIO0_TX_RINGBUFSIZE, ACP_P1_AUDIO0_TX_RINGBUFADDR, + ACP_P1_AUDIO0_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, + ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, + ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO2_TX_DMA_SIZE, ACP_P1_AUDIO2_TX_FIFOADDR, ACP_P1_AUDIO2_TX_FIFOSIZE, + ACP_P1_AUDIO2_TX_RINGBUFSIZE, ACP_P1_AUDIO2_TX_RINGBUFADDR, + ACP_P1_AUDIO2_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO0_RX_DMA_SIZE, ACP_P1_AUDIO0_RX_FIFOADDR, ACP_P1_AUDIO0_RX_FIFOSIZE, + ACP_P1_AUDIO0_RX_RINGBUFSIZE, ACP_P1_AUDIO0_RX_RINGBUFADDR, + ACP_P1_AUDIO0_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE, + ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR, + ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO2_RX_DMA_SIZE, ACP_P1_AUDIO2_RX_FIFOADDR, ACP_P1_AUDIO2_RX_FIFOSIZE, + ACP_P1_AUDIO2_RX_RINGBUFSIZE, ACP_P1_AUDIO2_RX_RINGBUFADDR, + ACP_P1_AUDIO2_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} +}; + +static u32 acp70_sdw0_dma_enable_reg[ACP70_SDW0_DMA_MAX_STREAMS] = { + ACP70_SW0_AUDIO0_TX_EN, + ACP70_SW0_AUDIO1_TX_EN, + ACP70_SW0_AUDIO2_TX_EN, + ACP70_SW0_AUDIO0_RX_EN, + ACP70_SW0_AUDIO1_RX_EN, + ACP70_SW0_AUDIO2_RX_EN, +}; + +static u32 acp70_sdw1_dma_enable_reg[ACP70_SDW1_DMA_MAX_STREAMS] = { + ACP70_SW1_AUDIO0_TX_EN, + ACP70_SW1_AUDIO1_TX_EN, + ACP70_SW1_AUDIO2_TX_EN, + ACP70_SW1_AUDIO0_RX_EN, + ACP70_SW1_AUDIO1_RX_EN, + ACP70_SW1_AUDIO2_RX_EN, +}; + +static const struct snd_pcm_hardware acp63_sdw_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 = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .buffer_bytes_max = SDW_PLAYBACK_MAX_NUM_PERIODS * SDW_PLAYBACK_MAX_PERIOD_SIZE, + .period_bytes_min = SDW_PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = SDW_PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = SDW_PLAYBACK_MIN_NUM_PERIODS, + .periods_max = SDW_PLAYBACK_MAX_NUM_PERIODS, +}; + +static const struct snd_pcm_hardware acp63_sdw_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 = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .buffer_bytes_max = SDW_CAPTURE_MAX_NUM_PERIODS * SDW_CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = SDW_CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = SDW_CAPTURE_MAX_PERIOD_SIZE, + .periods_min = SDW_CAPTURE_MIN_NUM_PERIODS, + .periods_max = SDW_CAPTURE_MAX_NUM_PERIODS, +}; + +static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, u32 irq_mask, + u32 irq_mask1, bool enable) +{ + u32 ext_intr_cntl, ext_intr_cntl1; + + if (enable) { + ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl |= irq_mask; + writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 |= irq_mask1; + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); + } else { + ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl &= ~irq_mask; + writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 &= ~irq_mask1; + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); + } +} + +static void acp63_config_dma(struct acp_sdw_dma_stream *stream, void __iomem *acp_base, + u32 stream_id) +{ + u16 page_idx; + u32 low, high, val; + u32 sdw_dma_pte_offset; + dma_addr_t addr; + + addr = stream->dma_addr; + sdw_dma_pte_offset = SDW_PTE_OFFSET(stream->instance); + val = sdw_dma_pte_offset + (stream_id * ACP_SDW_PTE_OFFSET); + + /* Group Enable */ + writel(ACP_SDW_SRAM_PTE_OFFSET | BIT(31), acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); + writel(PAGE_SIZE_4K_ENABLE, acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); + for (page_idx = 0; page_idx < stream->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + writel(low, acp_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + writel(high, acp_base + ACP_SCRATCH_REG_0 + val + 4); + val += 8; + addr += PAGE_SIZE; + } + writel(0x1, acp_base + ACPAXI2AXI_ATU_CTRL); +} + +static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 size, + u32 manager_instance, u32 acp_rev) +{ + u32 reg_dma_size; + u32 reg_fifo_addr; + u32 reg_fifo_size; + u32 reg_ring_buf_size; + u32 reg_ring_buf_addr; + u32 sdw_fifo_addr; + u32 sdw_fifo_offset; + u32 sdw_ring_buf_addr; + u32 sdw_ring_buf_size; + u32 sdw_mem_window_offset; + + switch (acp_rev) { + case ACP63_PCI_REV: + switch (manager_instance) { + case ACP_SDW0: + reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr; + break; + case ACP_SDW1: + reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr; + break; + default: + return -EINVAL; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + switch (manager_instance) { + case ACP_SDW0: + reg_dma_size = acp70_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp70_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp70_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_addr; + break; + case ACP_SDW1: + reg_dma_size = acp70_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp70_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp70_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_addr; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + sdw_fifo_offset = ACP_SDW_FIFO_OFFSET(manager_instance); + sdw_mem_window_offset = SDW_MEM_WINDOW_START(manager_instance); + sdw_fifo_addr = sdw_fifo_offset + (stream_id * SDW_FIFO_OFFSET); + sdw_ring_buf_addr = sdw_mem_window_offset + (stream_id * ACP_SDW_RING_BUFF_ADDR_OFFSET); + sdw_ring_buf_size = size; + writel(sdw_ring_buf_size, acp_base + reg_ring_buf_size); + writel(sdw_ring_buf_addr, acp_base + reg_ring_buf_addr); + writel(sdw_fifo_addr, acp_base + reg_fifo_addr); + writel(SDW_DMA_SIZE, acp_base + reg_dma_size); + writel(SDW_FIFO_SIZE, acp_base + reg_fifo_size); + return 0; +} + +static int acp63_sdw_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct acp_sdw_dma_stream *stream; + struct snd_soc_dai *cpu_dai; + struct amd_sdw_manager *amd_manager; + struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream); + int ret; + + runtime = substream->runtime; + cpu_dai = snd_soc_rtd_to_cpu(prtd, 0); + amd_manager = snd_soc_dai_get_drvdata(cpu_dai); + stream = kzalloc_obj(*stream); + if (!stream) + return -ENOMEM; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp63_sdw_hardware_playback; + else + runtime->hw = acp63_sdw_hardware_capture; + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(stream); + return ret; + } + + stream->stream_id = cpu_dai->id; + stream->instance = amd_manager->instance; + runtime->private_data = stream; + return ret; +} + +static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct acp_sdw_dma_stream *stream; + struct sdw_dma_dev_data *sdw_data; + u32 period_bytes; + u32 water_mark_size_reg; + u32 irq_mask, ext_intr_ctrl; + u64 size; + u32 stream_id; + u32 acp_ext_intr_cntl_reg; + int ret; + + sdw_data = dev_get_drvdata(component->dev); + stream = substream->runtime->private_data; + if (!stream) + return -EINVAL; + stream_id = stream->stream_id; + switch (sdw_data->acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp63_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id)); + break; + case ACP_SDW1: + sdw_data->acp63_sdw1_dma_stream[stream_id] = substream; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; + water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg; + irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id)); + break; + default: + return -EINVAL; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp70_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp70_sdw0_dma_reg[stream_id].water_mark_size_reg; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP70_SDW0_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP70_SDW0_DMA_RX_IRQ_MASK(stream_id)); + break; + case ACP_SDW1: + sdw_data->acp70_sdw1_dma_stream[stream_id] = substream; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; + water_mark_size_reg = acp70_sdw1_dma_reg[stream_id].water_mark_size_reg; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP70_SDW1_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP70_SDW1_DMA_RX_IRQ_MASK(stream_id)); + + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + size = params_buffer_bytes(params); + period_bytes = params_period_bytes(params); + stream->dma_addr = substream->runtime->dma_addr; + stream->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + acp63_config_dma(stream, sdw_data->acp_base, stream_id); + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, stream_id, size, + stream->instance, sdw_data->acp_rev); + if (ret) { + dev_err(component->dev, "Invalid DMA channel\n"); + return -EINVAL; + } + ext_intr_ctrl = readl(sdw_data->acp_base + acp_ext_intr_cntl_reg); + ext_intr_ctrl |= irq_mask; + writel(ext_intr_ctrl, sdw_data->acp_base + acp_ext_intr_cntl_reg); + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); + return 0; +} + +static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base, + u32 acp_rev) +{ + union acp_sdw_dma_count byte_count; + u32 pos_low_reg, pos_high_reg; + + byte_count.bytescount = 0; + switch (acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg; + break; + case ACP_SDW1: + pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg; + break; + default: + goto POINTER_RETURN_BYTES; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + pos_low_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_high_reg; + break; + case ACP_SDW1: + pos_low_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_high_reg; + break; + default: + goto POINTER_RETURN_BYTES; + } + break; + default: + goto POINTER_RETURN_BYTES; + } + if (pos_low_reg) { + byte_count.bcount.high = readl(acp_base + pos_high_reg); + byte_count.bcount.low = readl(acp_base + pos_low_reg); + } +POINTER_RETURN_BYTES: + return byte_count.bytescount; +} + +static snd_pcm_uframes_t acp63_sdw_dma_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct sdw_dma_dev_data *sdw_data; + struct acp_sdw_dma_stream *stream; + u32 pos, buffersize; + u64 bytescount; + + sdw_data = dev_get_drvdata(comp->dev); + stream = substream->runtime->private_data; + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base, sdw_data->acp_rev); + if (bytescount > stream->bytescount) + bytescount -= stream->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(substream->runtime, pos); +} + +static int acp63_sdw_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, SDW_MIN_BUFFER, SDW_MAX_BUFFER); + return 0; +} + +static int acp63_sdw_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct sdw_dma_dev_data *sdw_data; + struct acp_sdw_dma_stream *stream; + + sdw_data = dev_get_drvdata(component->dev); + stream = substream->runtime->private_data; + if (!stream) + return -EINVAL; + switch (sdw_data->acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL; + break; + case ACP_SDW1: + sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL; + break; + default: + return -EINVAL; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp70_sdw0_dma_stream[stream->stream_id] = NULL; + break; + case ACP_SDW1: + sdw_data->acp70_sdw1_dma_stream[stream->stream_id] = NULL; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + kfree(stream); + return 0; +} + +static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, + void __iomem *acp_base, u32 acp_rev, bool sdw_dma_enable) +{ + struct acp_sdw_dma_stream *stream; + u32 stream_id; + u32 sdw_dma_en_reg; + u32 sdw_dma_en_stat_reg; + u32 sdw_dma_stat; + u32 dma_enable; + + stream = substream->runtime->private_data; + stream_id = stream->stream_id; + switch (acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id]; + break; + case ACP_SDW1: + sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id]; + break; + default: + return -EINVAL; + } + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + case ACP72_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_dma_en_reg = acp70_sdw0_dma_enable_reg[stream_id]; + break; + case ACP_SDW1: + sdw_dma_en_reg = acp70_sdw1_dma_enable_reg[stream_id]; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + sdw_dma_en_stat_reg = sdw_dma_en_reg + 4; + dma_enable = sdw_dma_enable; + writel(dma_enable, acp_base + sdw_dma_en_reg); + return readl_poll_timeout(acp_base + sdw_dma_en_stat_reg, sdw_dma_stat, + (sdw_dma_stat == dma_enable), ACP_DELAY_US, ACP_COUNTER); +} + +static int acp63_sdw_dma_trigger(struct snd_soc_component *comp, + struct snd_pcm_substream *substream, + int cmd) +{ + struct sdw_dma_dev_data *sdw_data; + int ret; + + sdw_data = dev_get_drvdata(comp->dev); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, true); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, false); + break; + default: + ret = -EINVAL; + } + if (ret) + dev_err(comp->dev, "trigger %d failed: %d", cmd, ret); + return ret; +} + +static const struct snd_soc_component_driver acp63_sdw_component = { + .name = DRV_NAME, + .open = acp63_sdw_dma_open, + .close = acp63_sdw_dma_close, + .hw_params = acp63_sdw_dma_hw_params, + .trigger = acp63_sdw_dma_trigger, + .pointer = acp63_sdw_dma_pointer, + .pcm_new = acp63_sdw_dma_new, + .use_dai_pcm_id = true, + +}; + +static int acp63_sdw_platform_probe(struct platform_device *pdev) +{ + struct resource *res; + struct sdw_dma_dev_data *sdw_data; + struct acp63_dev_data *acp_data; + struct device *parent; + int status; + + parent = pdev->dev.parent; + acp_data = dev_get_drvdata(parent); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + sdw_data = devm_kzalloc(&pdev->dev, sizeof(*sdw_data), GFP_KERNEL); + if (!sdw_data) + return -ENOMEM; + + sdw_data->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!sdw_data->acp_base) + return -ENOMEM; + + sdw_data->acp_lock = &acp_data->acp_lock; + sdw_data->acp_rev = acp_data->acp_rev; + dev_set_drvdata(&pdev->dev, sdw_data); + status = devm_snd_soc_register_component(&pdev->dev, + &acp63_sdw_component, + NULL, 0); + if (status) { + dev_err(&pdev->dev, "Fail to register sdw dma component\n"); + return status; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp63_sdw_platform_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp63_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) +{ + struct acp_sdw_dma_stream *stream; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + u32 period_bytes, buf_size, water_mark_size_reg; + u32 stream_count, irq_mask, irq_mask1; + int index, instance, ret; + + irq_mask = ACP63_SDW_DMA_IRQ_MASK; + irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK; + for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) { + if (instance == ACP_SDW0) + stream_count = ACP63_SDW0_DMA_MAX_STREAMS; + else + stream_count = ACP63_SDW1_DMA_MAX_STREAMS; + + for (index = 0; index < stream_count; index++) { + if (instance == ACP_SDW0) { + substream = sdw_data->acp63_sdw0_dma_stream[index]; + water_mark_size_reg = acp63_sdw0_dma_reg[index].water_mark_size_reg; + } else { + substream = sdw_data->acp63_sdw1_dma_stream[index]; + water_mark_size_reg = acp63_sdw1_dma_reg[index].water_mark_size_reg; + } + + if (substream && substream->runtime) { + runtime = substream->runtime; + stream = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buf_size = frames_to_bytes(runtime, runtime->buffer_size); + acp63_config_dma(stream, sdw_data->acp_base, index); + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index, + buf_size, instance, + ACP63_PCI_REV); + if (ret) + return ret; + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); + } + } + } + acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true); + return 0; +} + +static int acp70_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) +{ + struct acp_sdw_dma_stream *stream; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + u32 period_bytes, buf_size, water_mark_size_reg; + u32 stream_count, irq_mask, irq_mask1; + int index, instance, ret; + + irq_mask = ACP70_SDW_DMA_IRQ_MASK; + irq_mask1 = ACP70_P1_SDW_DMA_IRQ_MASK; + stream_count = ACP70_SDW0_DMA_MAX_STREAMS; + for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) { + for (index = 0; index < stream_count; index++) { + if (instance == ACP_SDW0) { + substream = sdw_data->acp70_sdw0_dma_stream[index]; + water_mark_size_reg = acp70_sdw0_dma_reg[index].water_mark_size_reg; + } else { + substream = sdw_data->acp70_sdw1_dma_stream[index]; + water_mark_size_reg = acp70_sdw1_dma_reg[index].water_mark_size_reg; + } + + if (substream && substream->runtime) { + runtime = substream->runtime; + stream = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buf_size = frames_to_bytes(runtime, runtime->buffer_size); + acp63_config_dma(stream, sdw_data->acp_base, index); + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index, + buf_size, instance, + sdw_data->acp_rev); + if (ret) + return ret; + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); + } + } + } + acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true); + return 0; +} + +static int acp63_sdw_pcm_resume(struct device *dev) +{ + struct sdw_dma_dev_data *sdw_data; + + sdw_data = dev_get_drvdata(dev); + if (sdw_data->acp_rev == ACP63_PCI_REV) + return acp63_restore_sdw_dma_config(sdw_data); + else + return acp70_restore_sdw_dma_config(sdw_data); +} + +static const struct dev_pm_ops acp63_pm_ops = { + SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume) +}; + +static struct platform_driver acp63_sdw_dma_driver = { + .probe = acp63_sdw_platform_probe, + .remove = acp63_sdw_platform_remove, + .driver = { + .name = "amd_ps_sdw_dma", + .pm = pm_ptr(&acp63_pm_ops), + }, +}; + +module_platform_driver(acp63_sdw_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD common SDW DMA Driver for ACP6.3, ACP7.0 & ACP7.1 platforms"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile new file mode 100644 index 000000000..b2ea030cb --- /dev/null +++ b/sound/soc/amd/raven/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Raven Ridge platform Support +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-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c new file mode 100644 index 000000000..b0147e88b --- /dev/null +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +//Copyright 2016 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp3x.h" + +#define DRV_NAME "acp3x_i2s_playcap" + +static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct i2s_dev_data *adata; + int mode; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + switch (mode) { + case SND_SOC_DAIFMT_I2S: + adata->tdm_mode = TDM_DISABLE; + break; + case SND_SOC_DAIFMT_DSP_A: + adata->tdm_mode = TDM_ENABLE; + break; + default: + return -EINVAL; + } + return 0; +} + +static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, + u32 tx_mask, u32 rx_mask, int slots, int slot_width) +{ + struct i2s_dev_data *adata; + u32 frm_len; + u16 slot_len; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + + /* These values are as per Hardware Spec */ + switch (slot_width) { + case SLOT_WIDTH_8: + slot_len = 8; + break; + case SLOT_WIDTH_16: + slot_len = 16; + break; + case SLOT_WIDTH_24: + slot_len = 24; + break; + case SLOT_WIDTH_32: + slot_len = 0; + break; + default: + return -EINVAL; + } + frm_len = FRM_LEN | (slots << 15) | (slot_len << 18); + adata->tdm_fmt = frm_len; + return 0; +} + +static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp3x_platform_info *pinfo; + struct i2s_dev_data *adata; + u32 val; + u32 reg_val, frmt_reg; + + prtd = snd_soc_substream_to_rtd(substream); + rtd = substream->runtime->private_data; + card = prtd->card; + adata = snd_soc_dai_get_drvdata(dai); + pinfo = snd_soc_card_get_drvdata(card); + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rtd->i2s_instance = pinfo->play_i2s_instance; + else + rtd->i2s_instance = pinfo->cap_i2s_instance; + } + + /* These values are as per Hardware Spec */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + rtd->xfer_resolution = 0x0; + break; + case SNDRV_PCM_FORMAT_S16_LE: + rtd->xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + rtd->xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + rtd->xfer_resolution = 0x05; + break; + default: + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_ITER; + frmt_reg = mmACP_BTTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_ITER; + frmt_reg = mmACP_I2STDM_TXFRMT; + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_IRER; + frmt_reg = mmACP_BTTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_IRER; + frmt_reg = mmACP_I2STDM_RXFRMT; + } + } + if (adata->tdm_mode) { + val = rv_readl(rtd->acp3x_base + reg_val); + rv_writel(val | 0x2, rtd->acp3x_base + reg_val); + rv_writel(adata->tdm_fmt, rtd->acp3x_base + frmt_reg); + } + val = rv_readl(rtd->acp3x_base + reg_val); + val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK; + val = val | (rtd->xfer_resolution << 3); + rv_writel(val, rtd->acp3x_base + reg_val); + return 0; +} + +static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + u32 val, period_bytes, reg_val, ier_val, water_val; + u32 buf_size, buf_reg; + int ret; + + rtd = substream->runtime->private_data; + period_bytes = frames_to_bytes(substream->runtime, + substream->runtime->period_size); + buf_size = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->bytescount = acp_get_byte_count(rtd, + substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + water_val = + mmACP_BT_TX_INTR_WATERMARK_SIZE; + reg_val = mmACP_BTTDM_ITER; + ier_val = mmACP_BTTDM_IER; + buf_reg = mmACP_BT_TX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + mmACP_I2S_TX_INTR_WATERMARK_SIZE; + reg_val = mmACP_I2STDM_ITER; + ier_val = mmACP_I2STDM_IER; + buf_reg = mmACP_I2S_TX_RINGBUFSIZE; + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + water_val = + mmACP_BT_RX_INTR_WATERMARK_SIZE; + reg_val = mmACP_BTTDM_IRER; + ier_val = mmACP_BTTDM_IER; + buf_reg = mmACP_BT_RX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + mmACP_I2S_RX_INTR_WATERMARK_SIZE; + reg_val = mmACP_I2STDM_IRER; + ier_val = mmACP_I2STDM_IER; + buf_reg = mmACP_I2S_RX_RINGBUFSIZE; + } + } + rv_writel(period_bytes, rtd->acp3x_base + water_val); + rv_writel(buf_size, rtd->acp3x_base + buf_reg); + val = rv_readl(rtd->acp3x_base + reg_val); + val = val | BIT(0); + rv_writel(val, rtd->acp3x_base + reg_val); + rv_writel(1, rtd->acp3x_base + ier_val); + ret = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_ITER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_ITER; + } + + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_IRER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_IRER; + } + } + val = rv_readl(rtd->acp3x_base + reg_val); + val = val & ~BIT(0); + rv_writel(val, rtd->acp3x_base + reg_val); + + if (!(rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER) & BIT(0)) && + !(rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER) & BIT(0))) + rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER); + if (!(rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER) & BIT(0)) && + !(rv_readl(rtd->acp3x_base + mmACP_I2STDM_IRER) & BIT(0))) + rv_writel(0, rtd->acp3x_base + mmACP_I2STDM_IER); + ret = 0; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const u64 acp3x_i2s_selectable_formats = + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_DSP_A; + +static const struct snd_soc_dai_ops acp3x_i2s_dai_ops = { + .hw_params = acp3x_i2s_hwparams, + .trigger = acp3x_i2s_trigger, + .set_fmt = acp3x_i2s_set_fmt, + .set_tdm_slot = acp3x_i2s_set_tdm_slot, + .auto_selectable_formats = &acp3x_i2s_selectable_formats, + .num_auto_selectable_formats = 1, +}; + +static const struct snd_soc_component_driver acp3x_dai_component = { + .name = DRV_NAME, + .legacy_dai_naming = 1, +}; + +static struct snd_soc_dai_driver acp3x_i2s_dai = { + .playback = { + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &acp3x_i2s_dai_ops, +}; + +static int acp3x_dai_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + int ret; + + adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data), + GFP_KERNEL); + if (!adata) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENOMEM; + } + adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp3x_base) + return -ENOMEM; + + adata->i2s_irq = res->start; + dev_set_drvdata(&pdev->dev, adata); + ret = devm_snd_soc_register_component(&pdev->dev, + &acp3x_dai_component, &acp3x_i2s_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Fail to register acp i2s dai\n"); + return -ENODEV; + } + return 0; +} + +static struct platform_driver acp3x_dai_driver = { + .probe = acp3x_dai_probe, + .driver = { + .name = "acp3x_i2s_playcap", + }, +}; + +module_platform_driver(acp3x_dai_driver); + +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c new file mode 100644 index 000000000..37ea5c572 --- /dev/null +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +//Copyright 2016 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp3x.h" + +#define DRV_NAME "acp3x_rv_i2s_dma" + +static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH | + 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_S32_LE, + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .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 acp3x_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH | + 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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .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, +}; + +static irqreturn_t i2s_irq_handler(int irq, void *dev_id) +{ + struct i2s_dev_data *rv_i2s_data; + u16 play_flag, cap_flag; + u32 val; + + rv_i2s_data = dev_id; + if (!rv_i2s_data) + return IRQ_NONE; + + play_flag = 0; + cap_flag = 0; + val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT); + if ((val & BIT(BT_TX_THRESHOLD)) && rv_i2s_data->play_stream) { + rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base + + mmACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rv_i2s_data->play_stream); + play_flag = 1; + } + if ((val & BIT(I2S_TX_THRESHOLD)) && + rv_i2s_data->i2ssp_play_stream) { + rv_writel(BIT(I2S_TX_THRESHOLD), + rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rv_i2s_data->i2ssp_play_stream); + play_flag = 1; + } + + if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) { + rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base + + mmACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rv_i2s_data->capture_stream); + cap_flag = 1; + } + if ((val & BIT(I2S_RX_THRESHOLD)) && + rv_i2s_data->i2ssp_capture_stream) { + rv_writel(BIT(I2S_RX_THRESHOLD), + rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rv_i2s_data->i2ssp_capture_stream); + cap_flag = 1; + } + + if (play_flag | cap_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val, acp_fifo_addr, reg_fifo_addr; + u32 reg_dma_size, reg_fifo_size; + dma_addr_t addr; + + addr = rtd->dma_addr; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + val = ACP_SRAM_BT_PB_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_PB_PTE_OFFSET; + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + val = ACP_SRAM_BT_CP_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_CP_PTE_OFFSET; + } + } + /* Group Enable */ + rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base + + mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base + + mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val); + high |= BIT(31); + rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val + + 4); + /* Move to next physically contiguous page */ + val += 8; + addr += PAGE_SIZE; + } + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_dma_size = mmACP_BT_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + BT_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = mmACP_BT_TX_FIFOADDR; + reg_fifo_size = mmACP_BT_TX_FIFOSIZE; + rv_writel(I2S_BT_TX_MEM_WINDOW_START, + rtd->acp3x_base + mmACP_BT_TX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = mmACP_I2S_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = mmACP_I2S_TX_FIFOADDR; + reg_fifo_size = mmACP_I2S_TX_FIFOSIZE; + rv_writel(I2S_SP_TX_MEM_WINDOW_START, + rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR); + } + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_dma_size = mmACP_BT_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + BT_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = mmACP_BT_RX_FIFOADDR; + reg_fifo_size = mmACP_BT_RX_FIFOSIZE; + rv_writel(I2S_BT_RX_MEM_WINDOW_START, + rtd->acp3x_base + mmACP_BT_RX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = mmACP_I2S_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = mmACP_I2S_RX_FIFOADDR; + reg_fifo_size = mmACP_I2S_RX_FIFOSIZE; + rv_writel(I2S_SP_RX_MEM_WINDOW_START, + rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR); + } + } + rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size); + rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr); + rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size); + rv_writel(BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD) + | BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD), + rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL); +} + +static int acp3x_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *i2s_data; + int ret; + + runtime = substream->runtime; + prtd = snd_soc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + i2s_data = kzalloc_obj(*i2s_data); + if (!i2s_data) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp3x_pcm_hardware_playback; + else + runtime->hw = acp3x_pcm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(i2s_data); + return ret; + } + + i2s_data->acp3x_base = adata->acp3x_base; + runtime->private_data = i2s_data; + return ret; +} + + +static int acp3x_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp3x_platform_info *pinfo; + struct i2s_dev_data *adata; + u64 size; + + prtd = snd_soc_substream_to_rtd(substream); + card = prtd->card; + pinfo = snd_soc_card_get_drvdata(card); + adata = dev_get_drvdata(component->dev); + rtd = substream->runtime->private_data; + if (!rtd) + return -EINVAL; + + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + rtd->i2s_instance = pinfo->play_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->play_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = substream; + } + } else { + rtd->i2s_instance = pinfo->cap_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + adata->capture_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = substream; + } + } + } else { + pr_err("pinfo failed\n"); + } + size = params_buffer_bytes(params); + rtd->dma_addr = substream->runtime->dma_addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + config_acp3x_dma(rtd, substream->stream); + return 0; +} + +static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct i2s_stream_instance *rtd; + u32 pos; + u32 buffersize; + u64 bytescount; + + rtd = substream->runtime->private_data; + + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + bytescount = acp_get_byte_count(rtd, substream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(substream->runtime, pos); +} + +static int acp3x_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp3x_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *ins; + + prtd = snd_soc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + ins = substream->runtime->private_data; + if (!ins) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (ins->i2s_instance) { + case I2S_BT_INSTANCE: + adata->play_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = NULL; + } + } else { + switch (ins->i2s_instance) { + case I2S_BT_INSTANCE: + adata->capture_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = NULL; + } + } + + return 0; +} + +static const struct snd_soc_component_driver acp3x_i2s_component = { + .name = DRV_NAME, + .open = acp3x_dma_open, + .close = acp3x_dma_close, + .hw_params = acp3x_dma_hw_params, + .pointer = acp3x_dma_pointer, + .pcm_new = acp3x_dma_new, +}; + +static int acp3x_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + unsigned int irqflags; + int status; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "platform_data not retrieved\n"); + return -ENODEV; + } + irqflags = *((unsigned int *)(pdev->dev.platform_data)); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp3x_base) + return -ENOMEM; + + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->i2s_irq = status; + + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp3x_i2s_component, + NULL, 0); + if (status) { + dev_err(&pdev->dev, "Fail to register acp i2s component\n"); + return -ENODEV; + } + status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler, + irqflags, "ACP3x_I2S_IRQ", adata); + if (status) { + dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n"); + return -ENODEV; + } + + pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp3x_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp3x_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + u32 val, reg_val, frmt_val; + + reg_val = 0; + frmt_val = 0; + adata = dev_get_drvdata(dev); + + if (adata->play_stream && adata->play_stream->runtime) { + struct i2s_stream_instance *rtd = + adata->play_stream->runtime->private_data; + config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK); + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_ITER; + frmt_val = mmACP_BTTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_ITER; + frmt_val = mmACP_I2STDM_TXFRMT; + } + rv_writel((rtd->xfer_resolution << 3), + rtd->acp3x_base + reg_val); + } + if (adata->capture_stream && adata->capture_stream->runtime) { + struct i2s_stream_instance *rtd = + adata->capture_stream->runtime->private_data; + config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + reg_val = mmACP_BTTDM_IRER; + frmt_val = mmACP_BTTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = mmACP_I2STDM_IRER; + frmt_val = mmACP_I2STDM_RXFRMT; + } + rv_writel((rtd->xfer_resolution << 3), + rtd->acp3x_base + reg_val); + } + if (adata->tdm_mode == TDM_ENABLE) { + rv_writel(adata->tdm_fmt, adata->acp3x_base + frmt_val); + val = rv_readl(adata->acp3x_base + reg_val); + rv_writel(val | 0x2, adata->acp3x_base + reg_val); + } + rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); + return 0; +} + + +static int acp3x_pcm_runtime_suspend(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + + rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); + + return 0; +} + +static int acp3x_pcm_runtime_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + + rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); + return 0; +} + +static const struct dev_pm_ops acp3x_pm_ops = { + .runtime_suspend = acp3x_pcm_runtime_suspend, + .runtime_resume = acp3x_pcm_runtime_resume, + .resume = acp3x_resume, +}; + +static struct platform_driver acp3x_dma_driver = { + .probe = acp3x_audio_probe, + .remove = acp3x_audio_remove, + .driver = { + .name = "acp3x_rv_i2s_dma", + .pm = &acp3x_pm_ops, + }, +}; + +module_platform_driver(acp3x_dma_driver); + +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h new file mode 100644 index 000000000..7702f628e --- /dev/null +++ b/sound/soc/amd/raven/acp3x.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PCM Driver + * + * Copyright 2016 Advanced Micro Devices, Inc. + */ + +#include "chip_offset_byte.h" +#include +#define I2S_SP_INSTANCE 0x01 +#define I2S_BT_INSTANCE 0x02 + +#define TDM_ENABLE 1 +#define TDM_DISABLE 0 + +#define ACP3x_DEVS 4 +#define ACP3x_PHY_BASE_ADDRESS 0x1240000 +#define ACP3x_I2S_MODE 0 +#define ACP3x_REG_START 0x1240000 +#define ACP3x_REG_END 0x1250200 +#define ACP3x_I2STDM_REG_START 0x1242400 +#define ACP3x_I2STDM_REG_END 0x1242410 +#define ACP3x_BT_TDM_REG_START 0x1242800 +#define ACP3x_BT_TDM_REG_END 0x1242810 +#define I2S_MODE 0x04 +#define I2S_RX_THRESHOLD 27 +#define I2S_TX_THRESHOLD 28 +#define BT_TX_THRESHOLD 26 +#define BT_RX_THRESHOLD 25 +#define ACP_ERR_INTR_MASK 29 +#define ACP3x_POWER_ON 0x00 +#define ACP3x_POWER_ON_IN_PROGRESS 0x01 +#define ACP3x_POWER_OFF 0x02 +#define ACP3x_POWER_OFF_IN_PROGRESS 0x03 +#define ACP3x_SOFT_RESET__SoftResetAudDone_MASK 0x00010001 + +#define ACP_SRAM_PTE_OFFSET 0x02050000 +#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 +#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 +#define ACP_SRAM_BT_PB_PTE_OFFSET 0x200 +#define ACP_SRAM_BT_CP_PTE_OFFSET 0x300 +#define PAGE_SIZE_4K_ENABLE 0x2 +#define I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define I2S_SP_RX_MEM_WINDOW_START 0x4020000 +#define I2S_BT_TX_MEM_WINDOW_START 0x4040000 +#define I2S_BT_RX_MEM_WINDOW_START 0x4060000 + +#define SP_PB_FIFO_ADDR_OFFSET 0x500 +#define SP_CAPT_FIFO_ADDR_OFFSET 0x700 +#define BT_PB_FIFO_ADDR_OFFSET 0x900 +#define BT_CAPT_FIFO_ADDR_OFFSET 0xB00 +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 8 +#define PLAYBACK_MAX_PERIOD_SIZE 8192 +#define PLAYBACK_MIN_PERIOD_SIZE 1024 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 8 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 1024 + +#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER +#define FIFO_SIZE 0x100 +#define DMA_SIZE 0x40 +#define FRM_LEN 0x100 + +#define SLOT_WIDTH_8 0x08 +#define SLOT_WIDTH_16 0x10 +#define SLOT_WIDTH_24 0x18 +#define SLOT_WIDTH_32 0x20 +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF + +struct acp3x_platform_info { + u16 play_i2s_instance; + u16 cap_i2s_instance; + u16 capture_channel; +}; + +struct i2s_dev_data { + bool tdm_mode; + int i2s_irq; + u16 i2s_instance; + u32 tdm_fmt; + u32 substream_type; + void __iomem *acp3x_base; + struct snd_pcm_substream *play_stream; + struct snd_pcm_substream *capture_stream; + struct snd_pcm_substream *i2ssp_play_stream; + struct snd_pcm_substream *i2ssp_capture_stream; +}; + +struct i2s_stream_instance { + u16 num_pages; + u16 i2s_instance; + u16 capture_channel; + u16 direction; + u16 channels; + u32 xfer_resolution; + u32 val; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp3x_base; +}; + +static inline u32 rv_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP3x_PHY_BASE_ADDRESS); +} + +static inline void rv_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS); +} + +static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, + int direction) +{ + u64 byte_count; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + byte_count = rv_readl(rtd->acp3x_base + + mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count = rv_readl(rtd->acp3x_base + + mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW); + } + + } else { + switch (rtd->i2s_instance) { + case I2S_BT_INSTANCE: + byte_count = rv_readl(rtd->acp3x_base + + mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count = rv_readl(rtd->acp3x_base + + mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); + byte_count |= rv_readl(rtd->acp3x_base + + mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW); + } + } + return byte_count; +} diff --git a/sound/soc/amd/raven/chip_offset_byte.h b/sound/soc/amd/raven/chip_offset_byte.h new file mode 100644 index 000000000..9c1fac58f --- /dev/null +++ b/sound/soc/amd/raven/chip_offset_byte.h @@ -0,0 +1,639 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 3.0 Register Documentation + * + * Copyright 2016 Advanced Micro Devices, Inc. + */ + +#ifndef _acp_ip_OFFSET_HEADER +#define _acp_ip_OFFSET_HEADER +// Registers from ACP_DMA block + +#define mmACP_DMA_CNTL_0 0x1240000 +#define mmACP_DMA_CNTL_1 0x1240004 +#define mmACP_DMA_CNTL_2 0x1240008 +#define mmACP_DMA_CNTL_3 0x124000C +#define mmACP_DMA_CNTL_4 0x1240010 +#define mmACP_DMA_CNTL_5 0x1240014 +#define mmACP_DMA_CNTL_6 0x1240018 +#define mmACP_DMA_CNTL_7 0x124001C +#define mmACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define mmACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define mmACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define mmACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define mmACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define mmACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define mmACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define mmACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define mmACP_DMA_DSCR_CNT_0 0x1240040 +#define mmACP_DMA_DSCR_CNT_1 0x1240044 +#define mmACP_DMA_DSCR_CNT_2 0x1240048 +#define mmACP_DMA_DSCR_CNT_3 0x124004C +#define mmACP_DMA_DSCR_CNT_4 0x1240050 +#define mmACP_DMA_DSCR_CNT_5 0x1240054 +#define mmACP_DMA_DSCR_CNT_6 0x1240058 +#define mmACP_DMA_DSCR_CNT_7 0x124005C +#define mmACP_DMA_PRIO_0 0x1240060 +#define mmACP_DMA_PRIO_1 0x1240064 +#define mmACP_DMA_PRIO_2 0x1240068 +#define mmACP_DMA_PRIO_3 0x124006C +#define mmACP_DMA_PRIO_4 0x1240070 +#define mmACP_DMA_PRIO_5 0x1240074 +#define mmACP_DMA_PRIO_6 0x1240078 +#define mmACP_DMA_PRIO_7 0x124007C +#define mmACP_DMA_CUR_DSCR_0 0x1240080 +#define mmACP_DMA_CUR_DSCR_1 0x1240084 +#define mmACP_DMA_CUR_DSCR_2 0x1240088 +#define mmACP_DMA_CUR_DSCR_3 0x124008C +#define mmACP_DMA_CUR_DSCR_4 0x1240090 +#define mmACP_DMA_CUR_DSCR_5 0x1240094 +#define mmACP_DMA_CUR_DSCR_6 0x1240098 +#define mmACP_DMA_CUR_DSCR_7 0x124009C +#define mmACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define mmACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define mmACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define mmACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define mmACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define mmACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define mmACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define mmACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define mmACP_DMA_ERR_STS_0 0x12400C0 +#define mmACP_DMA_ERR_STS_1 0x12400C4 +#define mmACP_DMA_ERR_STS_2 0x12400C8 +#define mmACP_DMA_ERR_STS_3 0x12400CC +#define mmACP_DMA_ERR_STS_4 0x12400D0 +#define mmACP_DMA_ERR_STS_5 0x12400D4 +#define mmACP_DMA_ERR_STS_6 0x12400D8 +#define mmACP_DMA_ERR_STS_7 0x12400DC +#define mmACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define mmACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define mmACP_DMA_CH_STS 0x12400E8 +#define mmACP_DMA_CH_GROUP 0x12400EC +#define mmACP_DMA_CH_RST_STS 0x12400F0 + + +// Registers from ACP_AXI2AXIATU block + +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define mmACPAXI2AXI_ATU_CTRL 0x1240C40 + + +// Registers from ACP_CLKRST block + +#define mmACP_SOFT_RESET 0x1241000 +#define mmACP_CONTROL 0x1241004 +#define mmACP_STATUS 0x1241008 +#define mmACP_DSP0_OCD_HALT_ON_RST 0x124100C +#define mmACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 + + +// Registers from ACP_MISC block + +#define mmACP_EXTERNAL_INTR_ENB 0x1241800 +#define mmACP_EXTERNAL_INTR_CNTL 0x1241804 +#define mmACP_EXTERNAL_INTR_STAT 0x1241808 +#define mmACP_DSP0_INTR_CNTL 0x124180C +#define mmACP_DSP0_INTR_STAT 0x1241810 +#define mmACP_DSP_SW_INTR_CNTL 0x1241814 +#define mmACP_DSP_SW_INTR_STAT 0x1241818 +#define mmACP_SW_INTR_TRIG 0x124181C +#define mmACP_SMU_MAILBOX 0x1241820 +#define mmDSP_INTERRUPT_ROUTING_CTRL 0x1241824 +#define mmACP_DSP0_WATCHDOG_TIMER_CNTL 0x1241828 +#define mmACP_DSP0_EXT_TIMER1_CNTL 0x124182C +#define mmACP_DSP0_EXT_TIMER2_CNTL 0x1241830 +#define mmACP_DSP0_EXT_TIMER3_CNTL 0x1241834 +#define mmACP_DSP0_EXT_TIMER4_CNTL 0x1241838 +#define mmACP_DSP0_EXT_TIMER5_CNTL 0x124183C +#define mmACP_DSP0_EXT_TIMER6_CNTL 0x1241840 +#define mmACP_DSP0_EXT_TIMER1_CURR_VALUE 0x1241844 +#define mmACP_DSP0_EXT_TIMER2_CURR_VALUE 0x1241848 +#define mmACP_DSP0_EXT_TIMER3_CURR_VALUE 0x124184C +#define mmACP_DSP0_EXT_TIMER4_CURR_VALUE 0x1241850 +#define mmACP_DSP0_EXT_TIMER5_CURR_VALUE 0x1241854 +#define mmACP_DSP0_EXT_TIMER6_CURR_VALUE 0x1241858 +#define mmACP_FW_STATUS 0x124185C +#define mmACP_TIMER 0x1241874 +#define mmACP_TIMER_CNTL 0x1241878 +#define mmACP_PGMEM_CTRL 0x12418C0 +#define mmACP_ERROR_STATUS 0x12418C4 +#define mmACP_SW_I2S_ERROR_REASON 0x12418C8 +#define mmACP_MEM_PG_STS 0x12418CC + + +// Registers from ACP_PGFSM block + +#define mmACP_I2S_PIN_CONFIG 0x1241400 +#define mmACP_PAD_PULLUP_PULLDOWN_CTRL 0x1241404 +#define mmACP_PAD_DRIVE_STRENGTH_CTRL 0x1241408 +#define mmACP_SW_PAD_KEEPER_EN 0x124140C +#define mmACP_SW_WAKE_EN 0x1241410 +#define mmACP_I2S_WAKE_EN 0x1241414 +#define mmACP_PME_EN 0x1241418 +#define mmACP_PGFSM_CONTROL 0x124141C +#define mmACP_PGFSM_STATUS 0x1241420 + + +// Registers from ACP_SCRATCH block + +#define mmACP_SCRATCH_REG_0 0x1250000 +#define mmACP_SCRATCH_REG_1 0x1250004 +#define mmACP_SCRATCH_REG_2 0x1250008 +#define mmACP_SCRATCH_REG_3 0x125000C +#define mmACP_SCRATCH_REG_4 0x1250010 +#define mmACP_SCRATCH_REG_5 0x1250014 +#define mmACP_SCRATCH_REG_6 0x1250018 +#define mmACP_SCRATCH_REG_7 0x125001C +#define mmACP_SCRATCH_REG_8 0x1250020 +#define mmACP_SCRATCH_REG_9 0x1250024 +#define mmACP_SCRATCH_REG_10 0x1250028 +#define mmACP_SCRATCH_REG_11 0x125002C +#define mmACP_SCRATCH_REG_12 0x1250030 +#define mmACP_SCRATCH_REG_13 0x1250034 +#define mmACP_SCRATCH_REG_14 0x1250038 +#define mmACP_SCRATCH_REG_15 0x125003C +#define mmACP_SCRATCH_REG_16 0x1250040 +#define mmACP_SCRATCH_REG_17 0x1250044 +#define mmACP_SCRATCH_REG_18 0x1250048 +#define mmACP_SCRATCH_REG_19 0x125004C +#define mmACP_SCRATCH_REG_20 0x1250050 +#define mmACP_SCRATCH_REG_21 0x1250054 +#define mmACP_SCRATCH_REG_22 0x1250058 +#define mmACP_SCRATCH_REG_23 0x125005C +#define mmACP_SCRATCH_REG_24 0x1250060 +#define mmACP_SCRATCH_REG_25 0x1250064 +#define mmACP_SCRATCH_REG_26 0x1250068 +#define mmACP_SCRATCH_REG_27 0x125006C +#define mmACP_SCRATCH_REG_28 0x1250070 +#define mmACP_SCRATCH_REG_29 0x1250074 +#define mmACP_SCRATCH_REG_30 0x1250078 +#define mmACP_SCRATCH_REG_31 0x125007C +#define mmACP_SCRATCH_REG_32 0x1250080 +#define mmACP_SCRATCH_REG_33 0x1250084 +#define mmACP_SCRATCH_REG_34 0x1250088 +#define mmACP_SCRATCH_REG_35 0x125008C +#define mmACP_SCRATCH_REG_36 0x1250090 +#define mmACP_SCRATCH_REG_37 0x1250094 +#define mmACP_SCRATCH_REG_38 0x1250098 +#define mmACP_SCRATCH_REG_39 0x125009C +#define mmACP_SCRATCH_REG_40 0x12500A0 +#define mmACP_SCRATCH_REG_41 0x12500A4 +#define mmACP_SCRATCH_REG_42 0x12500A8 +#define mmACP_SCRATCH_REG_43 0x12500AC +#define mmACP_SCRATCH_REG_44 0x12500B0 +#define mmACP_SCRATCH_REG_45 0x12500B4 +#define mmACP_SCRATCH_REG_46 0x12500B8 +#define mmACP_SCRATCH_REG_47 0x12500BC +#define mmACP_SCRATCH_REG_48 0x12500C0 +#define mmACP_SCRATCH_REG_49 0x12500C4 +#define mmACP_SCRATCH_REG_50 0x12500C8 +#define mmACP_SCRATCH_REG_51 0x12500CC +#define mmACP_SCRATCH_REG_52 0x12500D0 +#define mmACP_SCRATCH_REG_53 0x12500D4 +#define mmACP_SCRATCH_REG_54 0x12500D8 +#define mmACP_SCRATCH_REG_55 0x12500DC +#define mmACP_SCRATCH_REG_56 0x12500E0 +#define mmACP_SCRATCH_REG_57 0x12500E4 +#define mmACP_SCRATCH_REG_58 0x12500E8 +#define mmACP_SCRATCH_REG_59 0x12500EC +#define mmACP_SCRATCH_REG_60 0x12500F0 +#define mmACP_SCRATCH_REG_61 0x12500F4 +#define mmACP_SCRATCH_REG_62 0x12500F8 +#define mmACP_SCRATCH_REG_63 0x12500FC +#define mmACP_SCRATCH_REG_64 0x1250100 +#define mmACP_SCRATCH_REG_65 0x1250104 +#define mmACP_SCRATCH_REG_66 0x1250108 +#define mmACP_SCRATCH_REG_67 0x125010C +#define mmACP_SCRATCH_REG_68 0x1250110 +#define mmACP_SCRATCH_REG_69 0x1250114 +#define mmACP_SCRATCH_REG_70 0x1250118 +#define mmACP_SCRATCH_REG_71 0x125011C +#define mmACP_SCRATCH_REG_72 0x1250120 +#define mmACP_SCRATCH_REG_73 0x1250124 +#define mmACP_SCRATCH_REG_74 0x1250128 +#define mmACP_SCRATCH_REG_75 0x125012C +#define mmACP_SCRATCH_REG_76 0x1250130 +#define mmACP_SCRATCH_REG_77 0x1250134 +#define mmACP_SCRATCH_REG_78 0x1250138 +#define mmACP_SCRATCH_REG_79 0x125013C +#define mmACP_SCRATCH_REG_80 0x1250140 +#define mmACP_SCRATCH_REG_81 0x1250144 +#define mmACP_SCRATCH_REG_82 0x1250148 +#define mmACP_SCRATCH_REG_83 0x125014C +#define mmACP_SCRATCH_REG_84 0x1250150 +#define mmACP_SCRATCH_REG_85 0x1250154 +#define mmACP_SCRATCH_REG_86 0x1250158 +#define mmACP_SCRATCH_REG_87 0x125015C +#define mmACP_SCRATCH_REG_88 0x1250160 +#define mmACP_SCRATCH_REG_89 0x1250164 +#define mmACP_SCRATCH_REG_90 0x1250168 +#define mmACP_SCRATCH_REG_91 0x125016C +#define mmACP_SCRATCH_REG_92 0x1250170 +#define mmACP_SCRATCH_REG_93 0x1250174 +#define mmACP_SCRATCH_REG_94 0x1250178 +#define mmACP_SCRATCH_REG_95 0x125017C +#define mmACP_SCRATCH_REG_96 0x1250180 +#define mmACP_SCRATCH_REG_97 0x1250184 +#define mmACP_SCRATCH_REG_98 0x1250188 +#define mmACP_SCRATCH_REG_99 0x125018C +#define mmACP_SCRATCH_REG_100 0x1250190 +#define mmACP_SCRATCH_REG_101 0x1250194 +#define mmACP_SCRATCH_REG_102 0x1250198 +#define mmACP_SCRATCH_REG_103 0x125019C +#define mmACP_SCRATCH_REG_104 0x12501A0 +#define mmACP_SCRATCH_REG_105 0x12501A4 +#define mmACP_SCRATCH_REG_106 0x12501A8 +#define mmACP_SCRATCH_REG_107 0x12501AC +#define mmACP_SCRATCH_REG_108 0x12501B0 +#define mmACP_SCRATCH_REG_109 0x12501B4 +#define mmACP_SCRATCH_REG_110 0x12501B8 +#define mmACP_SCRATCH_REG_111 0x12501BC +#define mmACP_SCRATCH_REG_112 0x12501C0 +#define mmACP_SCRATCH_REG_113 0x12501C4 +#define mmACP_SCRATCH_REG_114 0x12501C8 +#define mmACP_SCRATCH_REG_115 0x12501CC +#define mmACP_SCRATCH_REG_116 0x12501D0 +#define mmACP_SCRATCH_REG_117 0x12501D4 +#define mmACP_SCRATCH_REG_118 0x12501D8 +#define mmACP_SCRATCH_REG_119 0x12501DC +#define mmACP_SCRATCH_REG_120 0x12501E0 +#define mmACP_SCRATCH_REG_121 0x12501E4 +#define mmACP_SCRATCH_REG_122 0x12501E8 +#define mmACP_SCRATCH_REG_123 0x12501EC +#define mmACP_SCRATCH_REG_124 0x12501F0 +#define mmACP_SCRATCH_REG_125 0x12501F4 +#define mmACP_SCRATCH_REG_126 0x12501F8 +#define mmACP_SCRATCH_REG_127 0x12501FC +#define mmACP_SCRATCH_REG_128 0x1250200 + + +// Registers from ACP_SW_ACLK block + +#define mmSW_CORB_Base_Address 0x1243200 +#define mmSW_CORB_Write_Pointer 0x1243204 +#define mmSW_CORB_Read_Pointer 0x1243208 +#define mmSW_CORB_Control 0x124320C +#define mmSW_CORB_Size 0x1243214 +#define mmSW_RIRB_Base_Address 0x1243218 +#define mmSW_RIRB_Write_Pointer 0x124321C +#define mmSW_RIRB_Response_Interrupt_Count 0x1243220 +#define mmSW_RIRB_Control 0x1243224 +#define mmSW_RIRB_Size 0x1243228 +#define mmSW_RIRB_FIFO_MIN_THDL 0x124322C +#define mmSW_imm_cmd_UPPER_WORD 0x1243230 +#define mmSW_imm_cmd_LOWER_QWORD 0x1243234 +#define mmSW_imm_resp_UPPER_WORD 0x1243238 +#define mmSW_imm_resp_LOWER_QWORD 0x124323C +#define mmSW_imm_cmd_sts 0x1243240 +#define mmSW_BRA_BASE_ADDRESS 0x1243244 +#define mmSW_BRA_TRANSFER_SIZE 0x1243248 +#define mmSW_BRA_DMA_BUSY 0x124324C +#define mmSW_BRA_RESP 0x1243250 +#define mmSW_BRA_RESP_FRAME_ADDR 0x1243254 +#define mmSW_BRA_CURRENT_TRANSFER_SIZE 0x1243258 +#define mmSW_STATE_CHANGE_STATUS_0TO7 0x124325C +#define mmSW_STATE_CHANGE_STATUS_8TO11 0x1243260 +#define mmSW_STATE_CHANGE_STATUS_MASK_0to7 0x1243264 +#define mmSW_STATE_CHANGE_STATUS_MASK_8to11 0x1243268 +#define mmSW_CLK_FREQUENCY_CTRL 0x124326C +#define mmSW_ERROR_INTR_MASK 0x1243270 +#define mmSW_PHY_TEST_MODE_DATA_OFF 0x1243274 + + +// Registers from ACP_SW_SWCLK block + +#define mmACP_SW_EN 0x1243000 +#define mmACP_SW_EN_STATUS 0x1243004 +#define mmACP_SW_FRAMESIZE 0x1243008 +#define mmACP_SW_SSP_Counter 0x124300C +#define mmACP_SW_Audio_TX_EN 0x1243010 +#define mmACP_SW_Audio_TX_EN_STATUS 0x1243014 +#define mmACP_SW_Audio_TX_Frame_Format 0x1243018 +#define mmACP_SW_Audio_TX_SampleInterval 0x124301C +#define mmACP_SW_Audio_TX_Hctrl_DP0 0x1243020 +#define mmACP_SW_Audio_TX_Hctrl_DP1 0x1243024 +#define mmACP_SW_Audio_TX_Hctrl_DP2 0x1243028 +#define mmACP_SW_Audio_TX_Hctrl_DP3 0x124302C +#define mmACP_SW_Audio_TX_offset_DP0 0x1243030 +#define mmACP_SW_Audio_TX_offset_DP1 0x1243034 +#define mmACP_SW_Audio_TX_offset_DP2 0x1243038 +#define mmACP_SW_Audio_TX_offset_DP3 0x124303C +#define mmACP_SW_Audio_TX_Channel_Enable_DP0 0x1243040 +#define mmACP_SW_Audio_TX_Channel_Enable_DP1 0x1243044 +#define mmACP_SW_Audio_TX_Channel_Enable_DP2 0x1243048 +#define mmACP_SW_Audio_TX_Channel_Enable_DP3 0x124304C +#define mmACP_SW_BT_TX_EN 0x1243050 +#define mmACP_SW_BT_TX_EN_STATUS 0x1243054 +#define mmACP_SW_BT_TX_Frame_Format 0x1243058 +#define mmACP_SW_BT_TX_SampleInterval 0x124305C +#define mmACP_SW_BT_TX_Hctrl 0x1243060 +#define mmACP_SW_BT_TX_offset 0x1243064 +#define mmACP_SW_BT_TX_Channel_Enable_DP0 0x1243068 +#define mmACP_SW_Headset_TX_EN 0x124306C +#define mmACP_SW_Headset_TX_EN_STATUS 0x1243070 +#define mmACP_SW_Headset_TX_Frame_Format 0x1243074 +#define mmACP_SW_Headset_TX_SampleInterval 0x1243078 +#define mmACP_SW_Headset_TX_Hctrl 0x124307C +#define mmACP_SW_Headset_TX_offset 0x1243080 +#define mmACP_SW_Headset_TX_Channel_Enable_DP0 0x1243084 +#define mmACP_SW_Audio_RX_EN 0x1243088 +#define mmACP_SW_Audio_RX_EN_STATUS 0x124308C +#define mmACP_SW_Audio_RX_Frame_Format 0x1243090 +#define mmACP_SW_Audio_RX_SampleInterval 0x1243094 +#define mmACP_SW_Audio_RX_Hctrl_DP0 0x1243098 +#define mmACP_SW_Audio_RX_Hctrl_DP1 0x124309C +#define mmACP_SW_Audio_RX_Hctrl_DP2 0x1243100 +#define mmACP_SW_Audio_RX_Hctrl_DP3 0x1243104 +#define mmACP_SW_Audio_RX_offset_DP0 0x1243108 +#define mmACP_SW_Audio_RX_offset_DP1 0x124310C +#define mmACP_SW_Audio_RX_offset_DP2 0x1243110 +#define mmACP_SW_Audio_RX_offset_DP3 0x1243114 +#define mmACP_SW_Audio_RX_Channel_Enable_DP0 0x1243118 +#define mmACP_SW_Audio_RX_Channel_Enable_DP1 0x124311C +#define mmACP_SW_Audio_RX_Channel_Enable_DP2 0x1243120 +#define mmACP_SW_Audio_RX_Channel_Enable_DP3 0x1243124 +#define mmACP_SW_BT_RX_EN 0x1243128 +#define mmACP_SW_BT_RX_EN_STATUS 0x124312C +#define mmACP_SW_BT_RX_Frame_Format 0x1243130 +#define mmACP_SW_BT_RX_SampleInterval 0x1243134 +#define mmACP_SW_BT_RX_Hctrl 0x1243138 +#define mmACP_SW_BT_RX_offset 0x124313C +#define mmACP_SW_BT_RX_Channel_Enable_DP0 0x1243140 +#define mmACP_SW_Headset_RX_EN 0x1243144 +#define mmACP_SW_Headset_RX_EN_STATUS 0x1243148 +#define mmACP_SW_Headset_RX_Frame_Format 0x124314C +#define mmACP_SW_Headset_RX_SampleInterval 0x1243150 +#define mmACP_SW_Headset_RX_Hctrl 0x1243154 +#define mmACP_SW_Headset_RX_offset 0x1243158 +#define mmACP_SW_Headset_RX_Channel_Enable_DP0 0x124315C +#define mmACP_SW_BPT_PORT_EN 0x1243160 +#define mmACP_SW_BPT_PORT_EN_STATUS 0x1243164 +#define mmACP_SW_BPT_PORT_Frame_Format 0x1243168 +#define mmACP_SW_BPT_PORT_SampleInterval 0x124316C +#define mmACP_SW_BPT_PORT_Hctrl 0x1243170 +#define mmACP_SW_BPT_PORT_offset 0x1243174 +#define mmACP_SW_BPT_PORT_Channel_Enable 0x1243178 +#define mmACP_SW_BPT_PORT_First_byte_addr 0x124317C +#define mmACP_SW_CLK_RESUME_CTRL 0x1243180 +#define mmACP_SW_CLK_RESUME_Delay_Cntr 0x1243184 +#define mmACP_SW_BUS_RESET_CTRL 0x1243188 +#define mmACP_SW_PRBS_ERR_STATUS 0x124318C + + +// Registers from ACP_AUDIO_BUFFERS block + +#define mmACP_I2S_RX_RINGBUFADDR 0x1242000 +#define mmACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define mmACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define mmACP_I2S_RX_FIFOADDR 0x124200C +#define mmACP_I2S_RX_FIFOSIZE 0x1242010 +#define mmACP_I2S_RX_DMA_SIZE 0x1242014 +#define mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define mmACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define mmACP_I2S_TX_RINGBUFADDR 0x1242024 +#define mmACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define mmACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define mmACP_I2S_TX_FIFOADDR 0x1242030 +#define mmACP_I2S_TX_FIFOSIZE 0x1242034 +#define mmACP_I2S_TX_DMA_SIZE 0x1242038 +#define mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define mmACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define mmACP_BT_RX_RINGBUFADDR 0x1242048 +#define mmACP_BT_RX_RINGBUFSIZE 0x124204C +#define mmACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define mmACP_BT_RX_FIFOADDR 0x1242054 +#define mmACP_BT_RX_FIFOSIZE 0x1242058 +#define mmACP_BT_RX_DMA_SIZE 0x124205C +#define mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define mmACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define mmACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define mmACP_BT_TX_RINGBUFADDR 0x124206C +#define mmACP_BT_TX_RINGBUFSIZE 0x1242070 +#define mmACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define mmACP_BT_TX_FIFOADDR 0x1242078 +#define mmACP_BT_TX_FIFOSIZE 0x124207C +#define mmACP_BT_TX_DMA_SIZE 0x1242080 +#define mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define mmACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define mmACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define mmACP_HS_RX_RINGBUFADDR 0x1242090 +#define mmACP_HS_RX_RINGBUFSIZE 0x1242094 +#define mmACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define mmACP_HS_RX_FIFOADDR 0x124209C +#define mmACP_HS_RX_FIFOSIZE 0x12420A0 +#define mmACP_HS_RX_DMA_SIZE 0x12420A4 +#define mmACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define mmACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define mmACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define mmACP_HS_TX_RINGBUFADDR 0x12420B4 +#define mmACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define mmACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define mmACP_HS_TX_FIFOADDR 0x12420C0 +#define mmACP_HS_TX_FIFOSIZE 0x12420C4 +#define mmACP_HS_TX_DMA_SIZE 0x12420C8 +#define mmACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define mmACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define mmACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + + +// Registers from ACP_I2S_TDM block + +#define mmACP_I2STDM_IER 0x1242400 +#define mmACP_I2STDM_IRER 0x1242404 +#define mmACP_I2STDM_RXFRMT 0x1242408 +#define mmACP_I2STDM_ITER 0x124240C +#define mmACP_I2STDM_TXFRMT 0x1242410 + + +// Registers from ACP_BT_TDM block + +#define mmACP_BTTDM_IER 0x1242800 +#define mmACP_BTTDM_IRER 0x1242804 +#define mmACP_BTTDM_RXFRMT 0x1242808 +#define mmACP_BTTDM_ITER 0x124280C +#define mmACP_BTTDM_TXFRMT 0x1242810 + + +// Registers from AZALIA_IP block + +#define mmAudio_Az_Global_Capabilities 0x1200000 +#define mmAudio_Az_Minor_Version 0x1200002 +#define mmAudio_Az_Major_Version 0x1200003 +#define mmAudio_Az_Output_Payload_Capability 0x1200004 +#define mmAudio_Az_Input_Payload_Capability 0x1200006 +#define mmAudio_Az_Global_Control 0x1200008 +#define mmAudio_Az_Wake_Enable 0x120000C +#define mmAudio_Az_State_Change_Status 0x120000E +#define mmAudio_Az_Global_Status 0x1200010 +#define mmAudio_Az_Linked_List_Capability_Header 0x1200014 +#define mmAudio_Az_Output_Stream_Payload_Capability 0x1200018 +#define mmAudio_Az_Input_Stream_Payload_Capability 0x120001A +#define mmAudio_Az_Interrupt_Control 0x1200020 +#define mmAudio_Az_Interrupt_Status 0x1200024 +#define mmAudio_Az_Wall_Clock_Counter 0x1200030 +#define mmAudio_Az_Stream_Synchronization 0x1200038 +#define mmAudio_Az_CORB_Lower_Base_Address 0x1200040 +#define mmAudio_Az_CORB_Upper_Base_Address 0x1200044 +#define mmAudio_Az_CORB_Write_Pointer 0x1200048 +#define mmAudio_Az_CORB_Read_Pointer 0x120004A +#define mmAudio_Az_CORB_Control 0x120004C +#define mmAudio_Az_CORB_Status 0x120004D +#define mmAudio_Az_CORB_Size 0x120004E +#define mmAudio_Az_RIRB_Lower_Base_Address 0x1200050 +#define mmAudio_Az_RIRB_Upper_Base_Address 0x1200054 +#define mmAudio_Az_RIRB_Write_Pointer 0x1200058 +#define mmAudio_Az_RIRB_Response_Interrupt_Count 0x120005A +#define mmAudio_Az_RIRB_Control 0x120005C +#define mmAudio_Az_RIRB_Status 0x120005D +#define mmAudio_Az_RIRB_Size 0x120005E +#define mmAudio_Az_Immediate_Command_Output_Interface 0x1200060 +#define mmAudio_Az_Immediate_Response_Input_Interface 0x1200064 +#define mmAudio_Az_Immediate_Command_Status 0x1200068 +#define mmAudio_Az_DPLBASE 0x1200070 +#define mmAudio_Az_DPUBASE 0x1200074 +#define mmAudio_Az_Input_SD0CTL_and_STS 0x1200080 +#define mmAudio_Az_Input_SD0LPIB 0x1200084 +#define mmAudio_Az_Input_SD0CBL 0x1200088 +#define mmAudio_Az_Input_SD0LVI 0x120008C +#define mmAudio_Az_Input_SD0FIFOS 0x1200090 +#define mmAudio_Az_Input_SD0FMT 0x1200092 +#define mmAudio_Az_Input_SD0BDPL 0x1200098 +#define mmAudio_Az_Input_SD0BDPU 0x120009C +#define mmAudio_Az_Input_SD1CTL_and_STS 0x12000A0 +#define mmAudio_Az_Input_SD1LPIB 0x12000A4 +#define mmAudio_Az_Input_SD1CBL 0x12000A8 +#define mmAudio_Az_Input_SD1LVI 0x12000AC +#define mmAudio_Az_Input_SD1FIFOS 0x12000B0 +#define mmAudio_Az_Input_SD1FMT 0x12000B2 +#define mmAudio_Az_Input_SD1BDPL 0x12000B8 +#define mmAudio_Az_Input_SD1BDPU 0x12000BC +#define mmAudio_Az_Input_SD2CTL_and_STS 0x12000C0 +#define mmAudio_Az_Input_SD2LPIB 0x12000C4 +#define mmAudio_Az_Input_SD2CBL 0x12000C8 +#define mmAudio_Az_Input_SD2LVI 0x12000CC +#define mmAudio_Az_Input_SD2FIFOS 0x12000D0 +#define mmAudio_Az_Input_SD2FMT 0x12000D2 +#define mmAudio_Az_Input_SD2BDPL 0x12000D8 +#define mmAudio_Az_Input_SD2BDPU 0x12000DC +#define mmAudio_Az_Input_SD3CTL_and_STS 0x12000E0 +#define mmAudio_Az_Input_SD3LPIB 0x12000E4 +#define mmAudio_Az_Input_SD3CBL 0x12000E8 +#define mmAudio_Az_Input_SD3LVI 0x12000EC +#define mmAudio_Az_Input_SD3FIFOS 0x12000F0 +#define mmAudio_Az_Input_SD3FMT 0x12000F2 +#define mmAudio_Az_Input_SD3BDPL 0x12000F8 +#define mmAudio_Az_Input_SD3BDPU 0x12000FC +#define mmAudio_Az_Output_SD0CTL_and_STS 0x1200100 +#define mmAudio_Az_Output_SD0LPIB 0x1200104 +#define mmAudio_Az_Output_SD0CBL 0x1200108 +#define mmAudio_Az_Output_SD0LVI 0x120010C +#define mmAudio_Az_Output_SD0FIFOS 0x1200110 +#define mmAudio_Az_Output_SD0FMT 0x1200112 +#define mmAudio_Az_Output_SD0BDPL 0x1200118 +#define mmAudio_Az_Output_SD0BDPU 0x120011C +#define mmAudio_Az_Output_SD1CTL_and_STS 0x1200120 +#define mmAudio_Az_Output_SD1LPIB 0x1200124 +#define mmAudio_Az_Output_SD1CBL 0x1200128 +#define mmAudio_Az_Output_SD1LVI 0x120012C +#define mmAudio_Az_Output_SD1FIFOS 0x1200130 +#define mmAudio_Az_Output_SD1FMT 0x1200132 +#define mmAudio_Az_Output_SD1BDPL 0x1200138 +#define mmAudio_Az_Output_SD1BDPU 0x120013C +#define mmAudio_Az_Output_SD2CTL_and_STS 0x1200140 +#define mmAudio_Az_Output_SD2LPIB 0x1200144 +#define mmAudio_Az_Output_SD2CBL 0x1200148 +#define mmAudio_Az_Output_SD2LVI 0x120014C +#define mmAudio_Az_Output_SD2FIFOS 0x1200150 +#define mmAudio_Az_Output_SD2FMT 0x1200152 +#define mmAudio_Az_Output_SD2BDPL 0x1200158 +#define mmAudio_Az_Output_SD2BDPU 0x120015C +#define mmAudio_Az_Output_SD3CTL_and_STS 0x1200160 +#define mmAudio_Az_Output_SD3LPIB 0x1200164 +#define mmAudio_Az_Output_SD3CBL 0x1200168 +#define mmAudio_Az_Output_SD3LVI 0x120016C +#define mmAudio_Az_Output_SD3FIFOS 0x1200170 +#define mmAudio_Az_Output_SD3FMT 0x1200172 +#define mmAudio_Az_Output_SD3BDPL 0x1200178 +#define mmAudio_Az_Output_SD3BDPU 0x120017C +#define mmAudioAZ_Misc_Control_Register_1 0x1200180 +#define mmAudioAZ_Misc_Control_Register_2 0x1200182 +#define mmAudioAZ_Misc_Control_Register_3 0x1200183 +#define mmAudio_AZ_Multiple_Links_Capability_Header 0x1200200 +#define mmAudio_AZ_Multiple_Links_Capability_Declaration 0x1200204 +#define mmAudio_AZ_Link0_Capabilities 0x1200240 +#define mmAudio_AZ_Link0_Control 0x1200244 +#define mmAudio_AZ_Link0_Output_Stream_ID 0x1200248 +#define mmAudio_AZ_Link0_SDI_Identifier 0x120024C +#define mmAudio_AZ_Link0_Per_Stream_Overhead 0x1200250 +#define mmAudio_AZ_Link0_Wall_Frame_Counter 0x1200258 +#define mmAudio_AZ_Link0_Output_Payload_Capability_L 0x1200260 +#define mmAudio_AZ_Link0_Output_Payload_Capability_U 0x1200264 +#define mmAudio_AZ_Link0_Input_Payload_Capability_L 0x1200270 +#define mmAudio_AZ_Link0_Input_Payload_Capability_U 0x1200274 +#define mmAudio_Az_Input_SD0LICBA 0x1202084 +#define mmAudio_Az_Input_SD1LICBA 0x12020A4 +#define mmAudio_Az_Input_SD2LICBA 0x12020C4 +#define mmAudio_Az_Input_SD3LICBA 0x12020E4 +#define mmAudio_Az_Output_SD0LICBA 0x1202104 +#define mmAudio_Az_Output_SD1LICBA 0x1202124 +#define mmAudio_Az_Output_SD2LICBA 0x1202144 +#define mmAudio_Az_Output_SD3LICBA 0x1202164 +#define mmAUDIO_AZ_POWER_MANAGEMENT_CONTROL 0x1204000 +#define mmAUDIO_AZ_IOC_SOFTRST_CONTROL 0x1204004 +#define mmAUDIO_AZ_IOC_CLKGATE_CONTROL 0x1204008 + + +// Registers from ACP_AZALIA block + +#define mmACP_AZ_PAGE0_LBASE_ADDR 0x1243800 +#define mmACP_AZ_PAGE0_UBASE_ADDR 0x1243804 +#define mmACP_AZ_PAGE0_PGEN_SIZE 0x1243808 +#define mmACP_AZ_PAGE0_OFFSET 0x124380C +#define mmACP_AZ_PAGE1_LBASE_ADDR 0x1243810 +#define mmACP_AZ_PAGE1_UBASE_ADDR 0x1243814 +#define mmACP_AZ_PAGE1_PGEN_SIZE 0x1243818 +#define mmACP_AZ_PAGE1_OFFSET 0x124381C +#define mmACP_AZ_PAGE2_LBASE_ADDR 0x1243820 +#define mmACP_AZ_PAGE2_UBASE_ADDR 0x1243824 +#define mmACP_AZ_PAGE2_PGEN_SIZE 0x1243828 +#define mmACP_AZ_PAGE2_OFFSET 0x124382C +#define mmACP_AZ_PAGE3_LBASE_ADDR 0x1243830 +#define mmACP_AZ_PAGE3_UBASE_ADDR 0x1243834 +#define mmACP_AZ_PAGE3_PGEN_SIZE 0x1243838 +#define mmACP_AZ_PAGE3_OFFSET 0x124383C +#define mmACP_AZ_PAGE4_LBASE_ADDR 0x1243840 +#define mmACP_AZ_PAGE4_UBASE_ADDR 0x1243844 +#define mmACP_AZ_PAGE4_PGEN_SIZE 0x1243848 +#define mmACP_AZ_PAGE4_OFFSET 0x124384C +#define mmACP_AZ_PAGE5_LBASE_ADDR 0x1243850 +#define mmACP_AZ_PAGE5_UBASE_ADDR 0x1243854 +#define mmACP_AZ_PAGE5_PGEN_SIZE 0x1243858 +#define mmACP_AZ_PAGE5_OFFSET 0x124385C +#define mmACP_AZ_PAGE6_LBASE_ADDR 0x1243860 +#define mmACP_AZ_PAGE6_UBASE_ADDR 0x1243864 +#define mmACP_AZ_PAGE6_PGEN_SIZE 0x1243868 +#define mmACP_AZ_PAGE6_OFFSET 0x124386C +#define mmACP_AZ_PAGE7_LBASE_ADDR 0x1243870 +#define mmACP_AZ_PAGE7_UBASE_ADDR 0x1243874 +#define mmACP_AZ_PAGE7_PGEN_SIZE 0x1243878 +#define mmACP_AZ_PAGE7_OFFSET 0x124387C + + +#endif diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c new file mode 100644 index 000000000..a013a607b --- /dev/null +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ACP PCI Driver +// +//Copyright 2016 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include + +#include "acp3x.h" + +struct acp3x_dev_data { + void __iomem *acp3x_base; + bool acp3x_audio_mode; + struct resource *res; + struct platform_device *pdev[ACP3x_DEVS]; + u32 pme_en; +}; + +static int acp3x_power_on(struct acp3x_dev_data *adata) +{ + void __iomem *acp3x_base = adata->acp3x_base; + u32 val; + int timeout; + + val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if (!((val & ACP_PGFSM_STATUS_MASK) == + ACP_POWER_ON_IN_PROGRESS)) + rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp3x_base + mmACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); + if (!val) { + /* ACP power On clears PME_EN. + * Restore the value to its prior state + */ + rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN); + return 0; + } + udelay(1); + } + return -ETIMEDOUT; +} + +static int acp3x_reset(void __iomem *acp3x_base) +{ + u32 val; + int timeout; + + rv_writel(1, acp3x_base + mmACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rv_readl(acp3x_base + mmACP_SOFT_RESET); + if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) + break; + cpu_relax(); + } + rv_writel(0, acp3x_base + mmACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rv_readl(acp3x_base + mmACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void acp3x_enable_interrupts(void __iomem *acp_base) +{ + rv_writel(0x01, acp_base + mmACP_EXTERNAL_INTR_ENB); +} + +static void acp3x_disable_interrupts(void __iomem *acp_base) +{ + rv_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + + mmACP_EXTERNAL_INTR_STAT); + rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_CNTL); + rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_ENB); +} + +static int acp3x_init(struct acp3x_dev_data *adata) +{ + void __iomem *acp3x_base = adata->acp3x_base; + int ret; + + /* power on */ + ret = acp3x_power_on(adata); + if (ret) { + pr_err("ACP3x power on failed\n"); + return ret; + } + /* Reset */ + ret = acp3x_reset(acp3x_base); + if (ret) { + pr_err("ACP3x reset failed\n"); + return ret; + } + acp3x_enable_interrupts(acp3x_base); + return 0; +} + +static int acp3x_deinit(void __iomem *acp3x_base) +{ + int ret; + + acp3x_disable_interrupts(acp3x_base); + /* Reset */ + ret = acp3x_reset(acp3x_base); + if (ret) { + pr_err("ACP3x reset failed\n"); + return ret; + } + return 0; +} + +static int snd_acp3x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp3x_dev_data *adata; + struct platform_device_info pdevinfo[ACP3x_DEVS]; + unsigned int irqflags; + int ret, i; + u32 addr, val; + + /* Raven device detection */ + if (pci->revision != 0x00) + return -ENODEV; + + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP3x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + + irqflags = IRQF_SHARED; + + addr = pci_resource_start(pci, 0); + adata->acp3x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp3x_base) { + ret = -ENOMEM; + goto release_regions; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + /* Save ACP_PME_EN state */ + adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN); + ret = acp3x_init(adata); + if (ret) + goto release_regions; + + val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG); + switch (val) { + case I2S_MODE: + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * 4, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res[0].name = "acp3x_i2s_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + adata->res[0].start = addr; + adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START); + + adata->res[1].name = "acp3x_i2s_sp"; + adata->res[1].flags = IORESOURCE_MEM; + adata->res[1].start = addr + ACP3x_I2STDM_REG_START; + adata->res[1].end = addr + ACP3x_I2STDM_REG_END; + + adata->res[2].name = "acp3x_i2s_bt"; + adata->res[2].flags = IORESOURCE_MEM; + adata->res[2].start = addr + ACP3x_BT_TDM_REG_START; + adata->res[2].end = addr + ACP3x_BT_TDM_REG_END; + + adata->res[3].name = "acp3x_i2s_irq"; + adata->res[3].flags = IORESOURCE_IRQ; + adata->res[3].start = pci->irq; + adata->res[3].end = adata->res[3].start; + + adata->acp3x_audio_mode = ACP3x_I2S_MODE; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo[0].name = "acp3x_rv_i2s_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 4; + pdevinfo[0].res = &adata->res[0]; + pdevinfo[0].data = &irqflags; + pdevinfo[0].size_data = sizeof(irqflags); + + pdevinfo[1].name = "acp3x_i2s_playcap"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + pdevinfo[1].num_res = 1; + pdevinfo[1].res = &adata->res[1]; + + pdevinfo[2].name = "acp3x_i2s_playcap"; + pdevinfo[2].id = 1; + pdevinfo[2].parent = &pci->dev; + pdevinfo[2].num_res = 1; + pdevinfo[2].res = &adata->res[1]; + + pdevinfo[3].name = "acp3x_i2s_playcap"; + pdevinfo[3].id = 2; + pdevinfo[3].parent = &pci->dev; + pdevinfo[3].num_res = 1; + pdevinfo[3].res = &adata->res[2]; + for (i = 0; i < ACP3x_DEVS; i++) { + adata->pdev[i] = + platform_device_register_full(&pdevinfo[i]); + if (IS_ERR(adata->pdev[i])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[i].name); + ret = PTR_ERR(adata->pdev[i]); + goto unregister_devs; + } + } + break; + default: + dev_info(&pci->dev, "ACP audio mode : %d\n", val); + break; + } + pm_runtime_set_autosuspend_delay(&pci->dev, 2000); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +unregister_devs: + if (val == I2S_MODE) + for (i = 0; i < ACP3x_DEVS; i++) + platform_device_unregister(adata->pdev[i]); +de_init: + if (acp3x_deinit(adata->acp3x_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int snd_acp3x_suspend(struct device *dev) +{ + int ret; + struct acp3x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp3x_deinit(adata->acp3x_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + else + dev_dbg(dev, "ACP de-initialized\n"); + + return 0; +} + +static int snd_acp3x_resume(struct device *dev) +{ + int ret; + struct acp3x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp3x_init(adata); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static const struct dev_pm_ops acp3x_pm = { + .runtime_suspend = snd_acp3x_suspend, + .runtime_resume = snd_acp3x_resume, + .resume = snd_acp3x_resume, +}; + +static void snd_acp3x_remove(struct pci_dev *pci) +{ + struct acp3x_dev_data *adata; + int i, ret; + + adata = pci_get_drvdata(pci); + if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) { + for (i = 0; i < ACP3x_DEVS; i++) + platform_device_unregister(adata->pdev[i]); + } + ret = acp3x_deinit(adata->acp3x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp3x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp3x_ids); + +static struct pci_driver acp3x_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp3x_ids, + .probe = snd_acp3x_probe, + .remove = snd_acp3x_remove, + .driver = { + .pm = &acp3x_pm, + } +}; + +module_pci_driver(acp3x_driver); + +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); +MODULE_DESCRIPTION("AMD ACP3x PCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile new file mode 100644 index 000000000..76b4a9c3e --- /dev/null +++ b/sound/soc/amd/renoir/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Renoir platform Support +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 new file mode 100644 index 000000000..e60e38217 --- /dev/null +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -0,0 +1,506 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PDM Driver +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rn_acp3x.h" + +#define DRV_NAME "acp_rn_pdm_dma" + +static int pdm_gain = 3; +module_param(pdm_gain, int, 0644); +MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)"); + +static const struct snd_pcm_hardware acp_pdm_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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .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, +}; + +static irqreturn_t pdm_irq_handler(int irq, void *dev_id) +{ + struct pdm_dev_data *rn_pdm_data; + u16 cap_flag; + u32 val; + + rn_pdm_data = dev_id; + if (!rn_pdm_data) + return IRQ_NONE; + + cap_flag = 0; + val = rn_readl(rn_pdm_data->acp_base + ACP_EXTERNAL_INTR_STAT); + if ((val & BIT(PDM_DMA_STAT)) && rn_pdm_data->capture_stream) { + rn_writel(BIT(PDM_DMA_STAT), rn_pdm_data->acp_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(rn_pdm_data->capture_stream); + cap_flag = 1; + } + + if (cap_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static void init_pdm_ring_buffer(u32 physical_addr, + u32 buffer_size, + u32 watermark_size, + void __iomem *acp_base) +{ + rn_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR); + rn_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE); + rn_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + rn_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); +} + +static void enable_pdm_clock(void __iomem *acp_base) +{ + u32 pdm_clk_enable, pdm_ctrl; + + pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; + + rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); + pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL); + pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL; + pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3)); + rn_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL); +} + +static void enable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void disable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= ~PDM_DMA_INTR_MASK; + rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static bool check_pdm_dma_status(void __iomem *acp_base) +{ + bool pdm_dma_status; + u32 pdm_enable, pdm_dma_enable; + + pdm_dma_status = false; + pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & + ACP_PDM_DMA_EN_STATUS)) + pdm_dma_status = true; + return pdm_dma_status; +} + +static int start_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable; + u32 pdm_dma_enable; + int timeout; + + pdm_enable = 0x01; + pdm_dma_enable = 0x01; + + enable_pdm_clock(acp_base); + rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS) + return 0; + udelay(DELAY_US); + } + return -ETIMEDOUT; +} + +static int stop_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable, pdm_dma_enable; + int timeout; + + pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if (pdm_dma_enable & 0x01) { + pdm_dma_enable = 0x02; + rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = rn_readl(acp_base + + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == 0x00) + break; + udelay(DELAY_US); + } + if (timeout == ACP_COUNTER) + return -ETIMEDOUT; + } + if (pdm_enable == ACP_PDM_ENABLE) { + pdm_enable = ACP_PDM_DISABLE; + rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + } + rn_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH); + return 0; +} + +static void config_acp_dma(struct pdm_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val; + dma_addr_t addr; + + addr = rtd->dma_addr; + val = 0; + + /* Group Enable */ + rn_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp_base + + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + rn_writel(PAGE_SIZE_4K_ENABLE, rtd->acp_base + + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + rn_writel(low, rtd->acp_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + rn_writel(high, rtd->acp_base + ACP_SCRATCH_REG_0 + val + 4); + val += 8; + addr += PAGE_SIZE; + } +} + +static int acp_pdm_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct pdm_dev_data *adata; + struct pdm_stream_instance *pdm_data; + int ret; + + runtime = substream->runtime; + adata = dev_get_drvdata(component->dev); + pdm_data = kzalloc_obj(*pdm_data); + if (!pdm_data) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw = acp_pdm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(pdm_data); + return ret; + } + + enable_pdm_interrupts(adata->acp_base); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + adata->capture_stream = substream; + + pdm_data->acp_base = adata->acp_base; + runtime->private_data = pdm_data; + return ret; +} + +static int acp_pdm_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct pdm_stream_instance *rtd; + size_t size, period_bytes; + + rtd = substream->runtime->private_data; + if (!rtd) + return -EINVAL; + size = params_buffer_bytes(params); + period_bytes = params_period_bytes(params); + rtd->dma_addr = substream->runtime->dma_addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + config_acp_dma(rtd, substream->stream); + init_pdm_ring_buffer(MEM_WINDOW_START, size, period_bytes, + rtd->acp_base); + return 0; +} + +static u64 acp_pdm_get_byte_count(struct pdm_stream_instance *rtd, + int direction) +{ + union acp_pdm_dma_count byte_count; + + byte_count.bcount.high = + rn_readl(rtd->acp_base + + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + byte_count.bcount.low = + rn_readl(rtd->acp_base + + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + return byte_count.bytescount; +} + +static snd_pcm_uframes_t acp_pdm_dma_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *stream) +{ + struct pdm_stream_instance *rtd; + u32 pos, buffersize; + u64 bytescount; + + rtd = stream->runtime->private_data; + buffersize = frames_to_bytes(stream->runtime, + stream->runtime->buffer_size); + bytescount = acp_pdm_get_byte_count(rtd, stream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(stream->runtime, pos); +} + +static int acp_pdm_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp_pdm_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); + struct pdm_stream_instance *rtd = substream->runtime->private_data; + + disable_pdm_interrupts(adata->acp_base); + adata->capture_stream = NULL; + kfree(rtd); + return 0; +} + +static int acp_pdm_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct pdm_stream_instance *rtd; + int ret; + bool pdm_status; + unsigned int ch_mask; + + rtd = substream->runtime->private_data; + ret = 0; + switch (substream->runtime->channels) { + case TWO_CH: + ch_mask = 0x00; + break; + default: + return -EINVAL; + } + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rn_writel(ch_mask, rtd->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); + rn_writel(PDM_DECIMATION_FACTOR, rtd->acp_base + + ACP_WOV_PDM_DECIMATION_FACTOR); + rtd->bytescount = acp_pdm_get_byte_count(rtd, + substream->stream); + pdm_status = check_pdm_dma_status(rtd->acp_base); + if (!pdm_status) + ret = start_pdm_dma(rtd->acp_base); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pdm_status = check_pdm_dma_status(rtd->acp_base); + if (pdm_status) + ret = stop_pdm_dma(rtd->acp_base); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static const struct snd_soc_dai_ops acp_pdm_dai_ops = { + .trigger = acp_pdm_dai_trigger, +}; + +static struct snd_soc_dai_driver acp_pdm_dai_driver = { + .capture = { + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 48000, + .rate_max = 48000, + }, + .ops = &acp_pdm_dai_ops, +}; + +static const struct snd_soc_component_driver acp_pdm_component = { + .name = DRV_NAME, + .open = acp_pdm_dma_open, + .close = acp_pdm_dma_close, + .hw_params = acp_pdm_dma_hw_params, + .pointer = acp_pdm_dma_pointer, + .pcm_new = acp_pdm_dma_new, + .legacy_dai_naming = 1, +}; + +static int acp_pdm_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct pdm_dev_data *adata; + unsigned int irqflags; + int status; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "platform_data not retrieved\n"); + return -ENODEV; + } + irqflags = *((unsigned int *)(pdev->dev.platform_data)); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp_base) + return -ENOMEM; + + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->pdm_irq = status; + + adata->capture_stream = NULL; + + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp_pdm_component, + &acp_pdm_dai_driver, 1); + if (status) { + dev_err(&pdev->dev, "Fail to register acp pdm dai\n"); + + return -ENODEV; + } + status = devm_request_irq(&pdev->dev, adata->pdm_irq, pdm_irq_handler, + irqflags, "ACP_PDM_IRQ", adata); + if (status) { + dev_err(&pdev->dev, "ACP PDM IRQ request failed\n"); + return -ENODEV; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp_pdm_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp_pdm_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + struct snd_pcm_runtime *runtime; + struct pdm_stream_instance *rtd; + u32 period_bytes, buffer_len; + + adata = dev_get_drvdata(dev); + if (adata->capture_stream && adata->capture_stream->runtime) { + runtime = adata->capture_stream->runtime; + rtd = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + config_acp_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + init_pdm_ring_buffer(MEM_WINDOW_START, buffer_len, period_bytes, + adata->acp_base); + } + enable_pdm_interrupts(adata->acp_base); + return 0; +} + +static int acp_pdm_runtime_suspend(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + disable_pdm_interrupts(adata->acp_base); + + return 0; +} + +static int acp_pdm_runtime_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + enable_pdm_interrupts(adata->acp_base); + return 0; +} + +static const struct dev_pm_ops acp_pdm_pm_ops = { + .runtime_suspend = acp_pdm_runtime_suspend, + .runtime_resume = acp_pdm_runtime_resume, + .resume = acp_pdm_resume, +}; + +static struct platform_driver acp_pdm_dma_driver = { + .probe = acp_pdm_audio_probe, + .remove = acp_pdm_audio_remove, + .driver = { + .name = "acp_rn_pdm_dma", + .pm = &acp_pdm_pm_ops, + }, +}; + +module_platform_driver(acp_pdm_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP3x Renior PDM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c new file mode 100644 index 000000000..516c3d4f4 --- /dev/null +++ b/sound/soc/amd/renoir/acp3x-rn.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Machine driver for AMD Renoir platform using DMIC +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include + +#include "rn_acp3x.h" + +#define DRV_NAME "acp_pdm_mach" + +SND_SOC_DAILINK_DEF(acp_pdm, + DAILINK_COMP_ARRAY(COMP_CPU("acp_rn_pdm_dma.0"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0", + "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_rn_pdm_dma.0"))); + +static struct snd_soc_dai_link acp_dai_pdm[] = { + { + .name = "acp3x-dmic-capture", + .stream_name = "DMIC capture", + .capture_only = 1, + SND_SOC_DAILINK_REG(acp_pdm, dmic_codec, platform), + }, +}; + +static struct snd_soc_card acp_card = { + .name = "acp", + .owner = THIS_MODULE, + .dai_link = acp_dai_pdm, + .num_links = 1, +}; + +static int acp_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + + card = &acp_card; + acp_card.dev = &pdev->dev; + + platform_set_drvdata(pdev, card); + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "snd_soc_register_card(%s) failed\n", + card->name); + } + return 0; +} + +static struct platform_driver acp_mach_driver = { + .driver = { + .name = "acp_pdm_mach", + .pm = &snd_soc_pm_ops, + }, + .probe = acp_probe, +}; + +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/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c new file mode 100644 index 000000000..b3812b70f --- /dev/null +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD Renoir ACP PCI Driver +// +//Copyright 2020 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rn_acp3x.h" + +static int acp_power_gating; +module_param(acp_power_gating, int, 0644); +MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); + +/* + * dmic_acpi_check = -1 - Use ACPI/DMI method to detect the DMIC hardware presence at runtime + * = 0 - Skip the DMIC device creation and return probe failure + * = 1 - Force DMIC support + */ +static int dmic_acpi_check = ACP_DMIC_AUTO; +module_param(dmic_acpi_check, bint, 0644); +MODULE_PARM_DESC(dmic_acpi_check, "Digital microphone presence (-1=auto, 0=none, 1=force)"); + +struct acp_dev_data { + void __iomem *acp_base; + struct resource *res; + struct platform_device *pdev[ACP_DEVS]; +}; + +static int rn_acp_power_on(void __iomem *acp_base) +{ + u32 val; + int timeout; + + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if ((val & ACP_PGFSM_STATUS_MASK) != + ACP_POWER_ON_IN_PROGRESS) + rn_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + if (!val) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int rn_acp_power_off(void __iomem *acp_base) +{ + u32 val; + int timeout; + + rn_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK, + acp_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_PGFSM_STATUS); + if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int rn_acp_reset(void __iomem *acp_base) +{ + u32 val; + int timeout; + + rn_writel(1, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_SOFT_RESET); + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) + break; + cpu_relax(); + } + rn_writel(0, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = rn_readl(acp_base + ACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void rn_acp_enable_interrupts(void __iomem *acp_base) +{ + u32 ext_intr_ctrl; + + rn_writel(0x01, acp_base + ACP_EXTERNAL_INTR_ENB); + ext_intr_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_ctrl |= ACP_ERROR_MASK; + rn_writel(ext_intr_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void rn_acp_disable_interrupts(void __iomem *acp_base) +{ + rn_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + + ACP_EXTERNAL_INTR_STAT); + rn_writel(0x00, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int rn_acp_init(void __iomem *acp_base) +{ + int ret; + + /* power on */ + ret = rn_acp_power_on(acp_base); + if (ret) { + pr_err("ACP power on failed\n"); + return ret; + } + rn_writel(0x01, acp_base + ACP_CONTROL); + /* Reset */ + ret = rn_acp_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + rn_writel(0x03, acp_base + ACP_CLKMUX_SEL); + rn_acp_enable_interrupts(acp_base); + return 0; +} + +static int rn_acp_deinit(void __iomem *acp_base) +{ + int ret; + + rn_acp_disable_interrupts(acp_base); + /* Reset */ + ret = rn_acp_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + rn_writel(0x00, acp_base + ACP_CLKMUX_SEL); + rn_writel(0x00, acp_base + ACP_CONTROL); + /* power off */ + if (acp_power_gating) { + ret = rn_acp_power_off(acp_base); + if (ret) { + pr_err("ACP power off failed\n"); + return ret; + } + } + return 0; +} + +static const struct dmi_system_id rn_acp_quirk_table[] = { + { + /* Lenovo IdeaPad S340-14API */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81NB"), + } + }, + { + /* Lenovo IdeaPad Flex 5 14ARE05 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81X2"), + } + }, + { + /* Lenovo IdeaPad 5 15ARE05 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81YQ"), + } + }, + { + /* Lenovo ThinkPad E14 Gen 2 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "20T6CTO1WW"), + } + }, + { + /* Lenovo ThinkPad X395 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "20NLCTO1WW"), + } + }, + {} +}; + +static int snd_rn_acp_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp_dev_data *adata; + struct platform_device_info pdevinfo[ACP_DEVS]; +#if defined(CONFIG_ACPI) + acpi_handle handle; + acpi_integer dmic_status; +#endif + const struct dmi_system_id *dmi_id; + unsigned int irqflags, flag; + int ret, index; + u32 addr; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + + /* Renoir device check */ + if (pci->revision != 0x01) + return -ENODEV; + + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP3x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + + /* check for msi interrupt support */ + ret = pci_enable_msi(pci); + if (ret) + /* msi is not enabled */ + irqflags = IRQF_SHARED; + else + /* msi is enabled */ + irqflags = 0; + + addr = pci_resource_start(pci, 0); + adata->acp_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp_base) { + ret = -ENOMEM; + goto disable_msi; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = rn_acp_init(adata->acp_base); + if (ret) + goto disable_msi; + + if (!dmic_acpi_check) { + ret = -ENODEV; + goto de_init; + } else if (dmic_acpi_check == ACP_DMIC_AUTO) { +#if defined(CONFIG_ACPI) + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (ACPI_FAILURE(ret)) { + ret = -ENODEV; + goto de_init; + } + if (!dmic_status) { + ret = -ENODEV; + goto de_init; + } +#endif + dmi_id = dmi_first_match(rn_acp_quirk_table); + if (dmi_id && !dmi_id->driver_data) { + dev_info(&pci->dev, "ACPI settings override using DMI (ACP mic is not present)"); + ret = -ENODEV; + goto de_init; + } + } + + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * 2, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res[0].name = "acp_pdm_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + adata->res[0].start = addr; + adata->res[0].end = addr + (ACP_REG_END - ACP_REG_START); + adata->res[1].name = "acp_pdm_irq"; + adata->res[1].flags = IORESOURCE_IRQ; + adata->res[1].start = pci->irq; + adata->res[1].end = pci->irq; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo[0].name = "acp_rn_pdm_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 2; + pdevinfo[0].res = adata->res; + pdevinfo[0].data = &irqflags; + pdevinfo[0].size_data = sizeof(irqflags); + + pdevinfo[1].name = "dmic-codec"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + pdevinfo[2].name = "acp_pdm_mach"; + pdevinfo[2].id = 0; + pdevinfo[2].parent = &pci->dev; + for (index = 0; index < ACP_DEVS; index++) { + adata->pdev[index] = + platform_device_register_full(&pdevinfo[index]); + if (IS_ERR(adata->pdev[index])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[index].name); + ret = PTR_ERR(adata->pdev[index]); + goto unregister_devs; + } + } + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +unregister_devs: + for (index = 0; index < ACP_DEVS; index++) + platform_device_unregister(adata->pdev[index]); +de_init: + if (rn_acp_deinit(adata->acp_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +disable_msi: + pci_disable_msi(pci); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int snd_rn_acp_suspend(struct device *dev) +{ + int ret; + struct acp_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = rn_acp_deinit(adata->acp_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + else + dev_dbg(dev, "ACP de-initialized\n"); + + return ret; +} + +static int snd_rn_acp_resume(struct device *dev) +{ + int ret; + struct acp_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = rn_acp_init(adata->acp_base); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static const struct dev_pm_ops rn_acp_pm = { + .runtime_suspend = snd_rn_acp_suspend, + .runtime_resume = snd_rn_acp_resume, + .suspend = snd_rn_acp_suspend, + .resume = snd_rn_acp_resume, + .restore = snd_rn_acp_resume, + .poweroff = snd_rn_acp_suspend, +}; + +static void snd_rn_acp_remove(struct pci_dev *pci) +{ + struct acp_dev_data *adata; + int ret, index; + + adata = pci_get_drvdata(pci); + for (index = 0; index < ACP_DEVS; index++) + platform_device_unregister(adata->pdev[index]); + ret = rn_acp_deinit(adata->acp_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_disable_msi(pci); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_rn_acp_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_rn_acp_ids); + +static struct pci_driver rn_acp_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_rn_acp_ids, + .probe = snd_rn_acp_probe, + .remove = snd_rn_acp_remove, + .driver = { + .pm = &rn_acp_pm, + } +}; + +module_pci_driver(rn_acp_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP Renoir PCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h new file mode 100644 index 000000000..7d0f4e6a2 --- /dev/null +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PDM Driver + * + * Copyright 2020 Advanced Micro Devices, Inc. + */ + +#include "rn_chip_offset_byte.h" + +#define ACP_DEVS 3 +#define ACP_PHY_BASE_ADDRESS 0x1240000 +#define ACP_REG_START 0x1240000 +#define ACP_REG_END 0x1250200 + +#define ACP_DEVICE_ID 0x15E2 +#define ACP_POWER_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWER_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP_ERROR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF +#define PDM_DMA_STAT 0x10 +#define PDM_DMA_INTR_MASK 0x10000 +#define ACP_ERROR_STAT 29 +#define PDM_DECIMATION_FACTOR 0x2 +#define ACP_PDM_CLK_FREQ_MASK 0x07 +#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3) +#define ACP_PDM_ENABLE 0x01 +#define ACP_PDM_DISABLE 0x00 +#define ACP_PDM_DMA_EN_STATUS 0x02 +#define TWO_CH 0x02 +#define DELAY_US 5 +#define ACP_COUNTER 20000 +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 + +#define ACP_SRAM_PTE_OFFSET 0x02050000 +#define PAGE_SIZE_4K_ENABLE 0x2 +#define MEM_WINDOW_START 0x4000000 + +#define CAPTURE_MIN_NUM_PERIODS 4 +#define CAPTURE_MAX_NUM_PERIODS 4 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 4096 + +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER +#define ACP_DMIC_AUTO -1 + +struct pdm_dev_data { + u32 pdm_irq; + void __iomem *acp_base; + struct snd_pcm_substream *capture_stream; +}; + +struct pdm_stream_instance { + u16 num_pages; + u16 channels; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp_base; +}; + +union acp_pdm_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +static inline u32 rn_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP_PHY_BASE_ADDRESS); +} + +static inline void rn_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP_PHY_BASE_ADDRESS); +} + +/* Machine configuration */ +int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/renoir/rn_chip_offset_byte.h b/sound/soc/amd/renoir/rn_chip_offset_byte.h new file mode 100644 index 000000000..d20d967b5 --- /dev/null +++ b/sound/soc/amd/renoir/rn_chip_offset_byte.h @@ -0,0 +1,349 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 3.1 Register Documentation + * + * Copyright 2020 Advanced Micro Devices, Inc. + */ + +#ifndef _rn_OFFSET_HEADER +#define _rn_OFFSET_HEADER +// Registers from ACP_DMA block + +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_CNTL_1 0x1240004 +#define ACP_DMA_CNTL_2 0x1240008 +#define ACP_DMA_CNTL_3 0x124000C +#define ACP_DMA_CNTL_4 0x1240010 +#define ACP_DMA_CNTL_5 0x1240014 +#define ACP_DMA_CNTL_6 0x1240018 +#define ACP_DMA_CNTL_7 0x124001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_DSCR_CNT_1 0x1240044 +#define ACP_DMA_DSCR_CNT_2 0x1240048 +#define ACP_DMA_DSCR_CNT_3 0x124004C +#define ACP_DMA_DSCR_CNT_4 0x1240050 +#define ACP_DMA_DSCR_CNT_5 0x1240054 +#define ACP_DMA_DSCR_CNT_6 0x1240058 +#define ACP_DMA_DSCR_CNT_7 0x124005C +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_PRIO_1 0x1240064 +#define ACP_DMA_PRIO_2 0x1240068 +#define ACP_DMA_PRIO_3 0x124006C +#define ACP_DMA_PRIO_4 0x1240070 +#define ACP_DMA_PRIO_5 0x1240074 +#define ACP_DMA_PRIO_6 0x1240078 +#define ACP_DMA_PRIO_7 0x124007C +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_DSCR_1 0x1240084 +#define ACP_DMA_CUR_DSCR_2 0x1240088 +#define ACP_DMA_CUR_DSCR_3 0x124008C +#define ACP_DMA_CUR_DSCR_4 0x1240090 +#define ACP_DMA_CUR_DSCR_5 0x1240094 +#define ACP_DMA_CUR_DSCR_6 0x1240098 +#define ACP_DMA_CUR_DSCR_7 0x124009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define ACP_DMA_ERR_STS_0 0x12400C0 +#define ACP_DMA_ERR_STS_1 0x12400C4 +#define ACP_DMA_ERR_STS_2 0x12400C8 +#define ACP_DMA_ERR_STS_3 0x12400CC +#define ACP_DMA_ERR_STS_4 0x12400D0 +#define ACP_DMA_ERR_STS_5 0x12400D4 +#define ACP_DMA_ERR_STS_6 0x12400D8 +#define ACP_DMA_ERR_STS_7 0x12400DC +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +// Registers from ACP_AXI2AXIATU block + +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define ACPAXI2AXI_ATU_CTRL 0x1240C40 + +// Registers from ACP_CLKRST block + +#define ACP_SOFT_RESET 0x1241000 +#define ACP_CONTROL 0x1241004 +#define ACP_STATUS 0x1241008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 + +// Registers from ACP_MISC block + +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_CNTL 0x1241804 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_PGMEM_CTRL 0x12418C0 +#define ACP_ERROR_STATUS 0x12418C4 +#define ACP_SW_I2S_ERROR_REASON 0x12418C8 +#define ACP_MEM_PG_STS 0x12418CC + +// Registers from ACP_PGFSM block + +#define ACP_I2S_PIN_CONFIG 0x1241400 +#define ACP_PAD_PULLUP_PULLDOWN_CTRL 0x1241404 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x1241408 +#define ACP_SW_PAD_KEEPER_EN 0x124140C +#define ACP_PGFSM_CONTROL 0x124141C +#define ACP_PGFSM_STATUS 0x1241420 +#define ACP_CLKMUX_SEL 0x1241424 +#define ACP_DEVICE_STATE 0x1241428 +#define AZ_DEVICE_STATE 0x124142C +#define ACP_INTR_URGENCY_TIMER 0x1241430 +#define AZ_INTR_URGENCY_TIMER 0x1241434 + +// Registers from ACP_SCRATCH block + +#define ACP_SCRATCH_REG_0 0x1250000 +#define ACP_SCRATCH_REG_1 0x1250004 +#define ACP_SCRATCH_REG_2 0x1250008 +#define ACP_SCRATCH_REG_3 0x125000C +#define ACP_SCRATCH_REG_4 0x1250010 +#define ACP_SCRATCH_REG_5 0x1250014 +#define ACP_SCRATCH_REG_6 0x1250018 +#define ACP_SCRATCH_REG_7 0x125001C +#define ACP_SCRATCH_REG_8 0x1250020 +#define ACP_SCRATCH_REG_9 0x1250024 +#define ACP_SCRATCH_REG_10 0x1250028 +#define ACP_SCRATCH_REG_11 0x125002C +#define ACP_SCRATCH_REG_12 0x1250030 +#define ACP_SCRATCH_REG_13 0x1250034 +#define ACP_SCRATCH_REG_14 0x1250038 +#define ACP_SCRATCH_REG_15 0x125003C +#define ACP_SCRATCH_REG_16 0x1250040 +#define ACP_SCRATCH_REG_17 0x1250044 +#define ACP_SCRATCH_REG_18 0x1250048 +#define ACP_SCRATCH_REG_19 0x125004C +#define ACP_SCRATCH_REG_20 0x1250050 +#define ACP_SCRATCH_REG_21 0x1250054 +#define ACP_SCRATCH_REG_22 0x1250058 +#define ACP_SCRATCH_REG_23 0x125005C +#define ACP_SCRATCH_REG_24 0x1250060 +#define ACP_SCRATCH_REG_25 0x1250064 +#define ACP_SCRATCH_REG_26 0x1250068 +#define ACP_SCRATCH_REG_27 0x125006C +#define ACP_SCRATCH_REG_28 0x1250070 +#define ACP_SCRATCH_REG_29 0x1250074 +#define ACP_SCRATCH_REG_30 0x1250078 +#define ACP_SCRATCH_REG_31 0x125007C +#define ACP_SCRATCH_REG_32 0x1250080 +#define ACP_SCRATCH_REG_33 0x1250084 +#define ACP_SCRATCH_REG_34 0x1250088 +#define ACP_SCRATCH_REG_35 0x125008C +#define ACP_SCRATCH_REG_36 0x1250090 +#define ACP_SCRATCH_REG_37 0x1250094 +#define ACP_SCRATCH_REG_38 0x1250098 +#define ACP_SCRATCH_REG_39 0x125009C +#define ACP_SCRATCH_REG_40 0x12500A0 +#define ACP_SCRATCH_REG_41 0x12500A4 +#define ACP_SCRATCH_REG_42 0x12500A8 +#define ACP_SCRATCH_REG_43 0x12500AC +#define ACP_SCRATCH_REG_44 0x12500B0 +#define ACP_SCRATCH_REG_45 0x12500B4 +#define ACP_SCRATCH_REG_46 0x12500B8 +#define ACP_SCRATCH_REG_47 0x12500BC +#define ACP_SCRATCH_REG_48 0x12500C0 +#define ACP_SCRATCH_REG_49 0x12500C4 +#define ACP_SCRATCH_REG_50 0x12500C8 +#define ACP_SCRATCH_REG_51 0x12500CC +#define ACP_SCRATCH_REG_52 0x12500D0 +#define ACP_SCRATCH_REG_53 0x12500D4 +#define ACP_SCRATCH_REG_54 0x12500D8 +#define ACP_SCRATCH_REG_55 0x12500DC +#define ACP_SCRATCH_REG_56 0x12500E0 +#define ACP_SCRATCH_REG_57 0x12500E4 +#define ACP_SCRATCH_REG_58 0x12500E8 +#define ACP_SCRATCH_REG_59 0x12500EC +#define ACP_SCRATCH_REG_60 0x12500F0 +#define ACP_SCRATCH_REG_61 0x12500F4 +#define ACP_SCRATCH_REG_62 0x12500F8 +#define ACP_SCRATCH_REG_63 0x12500FC +#define ACP_SCRATCH_REG_64 0x1250100 +#define ACP_SCRATCH_REG_65 0x1250104 +#define ACP_SCRATCH_REG_66 0x1250108 +#define ACP_SCRATCH_REG_67 0x125010C +#define ACP_SCRATCH_REG_68 0x1250110 +#define ACP_SCRATCH_REG_69 0x1250114 +#define ACP_SCRATCH_REG_70 0x1250118 +#define ACP_SCRATCH_REG_71 0x125011C +#define ACP_SCRATCH_REG_72 0x1250120 +#define ACP_SCRATCH_REG_73 0x1250124 +#define ACP_SCRATCH_REG_74 0x1250128 +#define ACP_SCRATCH_REG_75 0x125012C +#define ACP_SCRATCH_REG_76 0x1250130 +#define ACP_SCRATCH_REG_77 0x1250134 +#define ACP_SCRATCH_REG_78 0x1250138 +#define ACP_SCRATCH_REG_79 0x125013C +#define ACP_SCRATCH_REG_80 0x1250140 +#define ACP_SCRATCH_REG_81 0x1250144 +#define ACP_SCRATCH_REG_82 0x1250148 +#define ACP_SCRATCH_REG_83 0x125014C +#define ACP_SCRATCH_REG_84 0x1250150 +#define ACP_SCRATCH_REG_85 0x1250154 +#define ACP_SCRATCH_REG_86 0x1250158 +#define ACP_SCRATCH_REG_87 0x125015C +#define ACP_SCRATCH_REG_88 0x1250160 +#define ACP_SCRATCH_REG_89 0x1250164 +#define ACP_SCRATCH_REG_90 0x1250168 +#define ACP_SCRATCH_REG_91 0x125016C +#define ACP_SCRATCH_REG_92 0x1250170 +#define ACP_SCRATCH_REG_93 0x1250174 +#define ACP_SCRATCH_REG_94 0x1250178 +#define ACP_SCRATCH_REG_95 0x125017C +#define ACP_SCRATCH_REG_96 0x1250180 +#define ACP_SCRATCH_REG_97 0x1250184 +#define ACP_SCRATCH_REG_98 0x1250188 +#define ACP_SCRATCH_REG_99 0x125018C +#define ACP_SCRATCH_REG_100 0x1250190 +#define ACP_SCRATCH_REG_101 0x1250194 +#define ACP_SCRATCH_REG_102 0x1250198 +#define ACP_SCRATCH_REG_103 0x125019C +#define ACP_SCRATCH_REG_104 0x12501A0 +#define ACP_SCRATCH_REG_105 0x12501A4 +#define ACP_SCRATCH_REG_106 0x12501A8 +#define ACP_SCRATCH_REG_107 0x12501AC +#define ACP_SCRATCH_REG_108 0x12501B0 +#define ACP_SCRATCH_REG_109 0x12501B4 +#define ACP_SCRATCH_REG_110 0x12501B8 +#define ACP_SCRATCH_REG_111 0x12501BC +#define ACP_SCRATCH_REG_112 0x12501C0 +#define ACP_SCRATCH_REG_113 0x12501C4 +#define ACP_SCRATCH_REG_114 0x12501C8 +#define ACP_SCRATCH_REG_115 0x12501CC +#define ACP_SCRATCH_REG_116 0x12501D0 +#define ACP_SCRATCH_REG_117 0x12501D4 +#define ACP_SCRATCH_REG_118 0x12501D8 +#define ACP_SCRATCH_REG_119 0x12501DC +#define ACP_SCRATCH_REG_120 0x12501E0 +#define ACP_SCRATCH_REG_121 0x12501E4 +#define ACP_SCRATCH_REG_122 0x12501E8 +#define ACP_SCRATCH_REG_123 0x12501EC +#define ACP_SCRATCH_REG_124 0x12501F0 +#define ACP_SCRATCH_REG_125 0x12501F4 +#define ACP_SCRATCH_REG_126 0x12501F8 +#define ACP_SCRATCH_REG_127 0x12501FC +#define ACP_SCRATCH_REG_128 0x1250200 + +// Registers from ACP_AUDIO_BUFFERS block + +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +// Registers from ACP_I2S_TDM block + +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 + +// Registers from ACP_BT_TDM block + +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 + +// Registers from ACP_WOV block + +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 +#define ACP_WOV_BUFFER_STATUS 0x1242C58 +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 +#endif diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile new file mode 100644 index 000000000..7eae82faa --- /dev/null +++ b/sound/soc/amd/vangogh/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Vangogh platform Support +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 +obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-pcm-dma.o +obj-$(CONFIG_SND_SOC_AMD_VANGOGH_MACH) += snd-soc-acp5x-mach.o diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c new file mode 100644 index 000000000..dbfb87e2f --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x-i2s.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp5x.h" + +#define DRV_NAME "acp5x_i2s_playcap" + +static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct i2s_dev_data *adata; + int mode; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + switch (mode) { + case SND_SOC_DAIFMT_I2S: + adata->tdm_mode = TDM_DISABLE; + break; + case SND_SOC_DAIFMT_DSP_A: + adata->tdm_mode = TDM_ENABLE; + break; + default: + return -EINVAL; + } + mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; + switch (mode) { + case SND_SOC_DAIFMT_BP_FP: + adata->master_mode = I2S_MASTER_MODE_ENABLE; + break; + case SND_SOC_DAIFMT_BC_FC: + adata->master_mode = I2S_MASTER_MODE_DISABLE; + break; + } + return 0; +} + +static int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, + u32 tx_mask, u32 rx_mask, + int slots, int slot_width) +{ + struct i2s_dev_data *adata; + u32 frm_len; + u16 slot_len; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + + /* These values are as per Hardware Spec */ + switch (slot_width) { + case SLOT_WIDTH_8: + slot_len = 8; + break; + case SLOT_WIDTH_16: + slot_len = 16; + break; + case SLOT_WIDTH_24: + slot_len = 24; + break; + case SLOT_WIDTH_32: + slot_len = 0; + break; + default: + return -EINVAL; + } + frm_len = FRM_LEN | (slots << 15) | (slot_len << 18); + adata->tdm_fmt = frm_len; + return 0; +} + +static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp5x_platform_info *pinfo; + struct i2s_dev_data *adata; + + u32 val; + u32 reg_val, frmt_reg; + u32 lrclk_div_val, bclk_div_val; + + lrclk_div_val = 0; + bclk_div_val = 0; + prtd = snd_soc_substream_to_rtd(substream); + rtd = substream->runtime->private_data; + card = prtd->card; + adata = snd_soc_dai_get_drvdata(dai); + pinfo = snd_soc_card_get_drvdata(card); + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rtd->i2s_instance = pinfo->play_i2s_instance; + else + rtd->i2s_instance = pinfo->cap_i2s_instance; + } + + /* These values are as per Hardware Spec */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + rtd->xfer_resolution = 0x0; + break; + case SNDRV_PCM_FORMAT_S16_LE: + rtd->xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + rtd->xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + rtd->xfer_resolution = 0x05; + break; + default: + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + frmt_reg = ACP_HSTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_ITER; + frmt_reg = ACP_I2STDM_TXFRMT; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + frmt_reg = ACP_HSTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_IRER; + frmt_reg = ACP_I2STDM_RXFRMT; + } + } + if (adata->tdm_mode) { + val = acp_readl(rtd->acp5x_base + reg_val); + acp_writel(val | 0x2, rtd->acp5x_base + reg_val); + acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg); + } + val = acp_readl(rtd->acp5x_base + reg_val); + val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK; + val = val | (rtd->xfer_resolution << 3); + acp_writel(val, rtd->acp5x_base + reg_val); + + if (adata->master_mode) { + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 768; + break; + case 16000: + bclk_div_val = 384; + break; + case 24000: + bclk_div_val = 256; + break; + case 32000: + bclk_div_val = 192; + break; + case 44100: + case 48000: + bclk_div_val = 128; + break; + case 88200: + case 96000: + bclk_div_val = 64; + break; + case 192000: + bclk_div_val = 32; + break; + default: + return -EINVAL; + } + lrclk_div_val = 32; + break; + case SNDRV_PCM_FORMAT_S32_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 384; + break; + case 16000: + bclk_div_val = 192; + break; + case 24000: + bclk_div_val = 128; + break; + case 32000: + bclk_div_val = 96; + break; + case 44100: + case 48000: + bclk_div_val = 64; + break; + case 88200: + case 96000: + bclk_div_val = 32; + break; + case 192000: + bclk_div_val = 16; + break; + default: + return -EINVAL; + } + lrclk_div_val = 64; + break; + default: + return -EINVAL; + } + rtd->lrclk_div = lrclk_div_val; + rtd->bclk_div = bclk_div_val; + } + return 0; +} + +static int acp5x_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + struct i2s_dev_data *adata; + u32 val, period_bytes, reg_val, ier_val, water_val; + u32 buf_size, buf_reg; + int ret; + + adata = snd_soc_dai_get_drvdata(dai); + rtd = substream->runtime->private_data; + period_bytes = frames_to_bytes(substream->runtime, + substream->runtime->period_size); + buf_size = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->bytescount = acp_get_byte_count(rtd, + substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + water_val = + ACP_HS_TX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_ITER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_TX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + ACP_I2S_TX_INTR_WATERMARK_SIZE; + reg_val = ACP_I2STDM_ITER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_TX_RINGBUFSIZE; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + water_val = + ACP_HS_RX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_IRER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_RX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + ACP_I2S_RX_INTR_WATERMARK_SIZE; + reg_val = ACP_I2STDM_IRER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_RX_RINGBUFSIZE; + } + } + acp_writel(period_bytes, rtd->acp5x_base + water_val); + acp_writel(buf_size, rtd->acp5x_base + buf_reg); + if (adata->master_mode) + acp5x_set_i2s_clk(adata, rtd); + val = acp_readl(rtd->acp5x_base + reg_val); + val = val | BIT(0); + acp_writel(val, rtd->acp5x_base + reg_val); + acp_writel(1, rtd->acp5x_base + ier_val); + ret = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_ITER; + } + + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_IRER; + } + } + val = acp_readl(rtd->acp5x_base + reg_val); + val = val & ~BIT(0); + acp_writel(val, rtd->acp5x_base + reg_val); + + if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) && + !(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0))) + acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER); + if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) && + !(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0))) + acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER); + ret = 0; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static const u64 acp5x_i2s_selectable_formats = + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_DSP_A; + +static const struct snd_soc_dai_ops acp5x_i2s_dai_ops = { + .hw_params = acp5x_i2s_hwparams, + .trigger = acp5x_i2s_trigger, + .set_fmt = acp5x_i2s_set_fmt, + .set_tdm_slot = acp5x_i2s_set_tdm_slot, + .auto_selectable_formats = &acp5x_i2s_selectable_formats, + .num_auto_selectable_formats = 1, +}; + +static const struct snd_soc_component_driver acp5x_dai_component = { + .name = "acp5x-i2s", + .legacy_dai_naming = 1, +}; + +static struct snd_soc_dai_driver acp5x_i2s_dai = { + .playback = { + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 96000, + }, + .ops = &acp5x_i2s_dai_ops, +}; + +static int acp5x_dai_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + int ret; + + adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data), + GFP_KERNEL); + if (!adata) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENOMEM; + } + adata->acp5x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp5x_base) + return -ENOMEM; + + adata->master_mode = I2S_MASTER_MODE_ENABLE; + dev_set_drvdata(&pdev->dev, adata); + ret = devm_snd_soc_register_component(&pdev->dev, + &acp5x_dai_component, + &acp5x_i2s_dai, 1); + if (ret) + dev_err(&pdev->dev, "Fail to register acp i2s dai\n"); + return ret; +} + +static struct platform_driver acp5x_dai_driver = { + .probe = acp5x_dai_probe, + .driver = { + .name = "acp5x_i2s_playcap", + }, +}; + +module_platform_driver(acp5x_dai_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver"); +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c new file mode 100644 index 000000000..5454de24f --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Machine driver for AMD Vangogh platform using either + * NAU8821 & CS35L41 or NAU8821 & MAX98388 codecs. + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../codecs/nau8821.h" +#include "acp5x.h" + +#define DRV_NAME "acp5x_mach" +#define DUAL_CHANNEL 2 +#define ACP5X_NAU8821_BCLK 3072000 +#define ACP5X_NAU8821_FREQ_OUT 12288000 +#define ACP5X_NAU8821_COMP_NAME "i2c-NVTN2020:00" +#define ACP5X_NAU8821_DAI_NAME "nau8821-hifi" +#define ACP5X_CS35L41_COMP_LNAME "spi-VLV1776:00" +#define ACP5X_CS35L41_COMP_RNAME "spi-VLV1776:01" +#define ACP5X_CS35L41_DAI_NAME "cs35l41-pcm" +#define ACP5X_MAX98388_COMP_LNAME "i2c-ADS8388:00" +#define ACP5X_MAX98388_COMP_RNAME "i2c-ADS8388:01" +#define ACP5X_MAX98388_DAI_NAME "max98388-aif1" + +static struct snd_soc_jack vg_headset; + +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_NAU8821_COMP_NAME, + ACP5X_NAU8821_DAI_NAME))); + +static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new acp5x_8821_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); + struct snd_soc_dai *dai; + int ret = 0; + + dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); + if (!dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "set sysclk err = %d\n", ret); + return -EIO; + } + } else { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(dai->dev, "can't set BLK clock %d\n", ret); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NAU8821_BCLK, ACP5X_NAU8821_FREQ_OUT); + if (ret < 0) + dev_err(dai->dev, "can't set FLL: %d\n", ret); + } + + return ret; +} + +static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + int ret; + + /* + * Headset buttons map to the google Reference headset. + * These can be configured by userspace. + */ + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &vg_headset, acp5x_nau8821_jack_pins, + ARRAY_SIZE(acp5x_nau8821_jack_pins)); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); + nau8821_enable_jack_detect(component, &vg_headset); + + return ret; +} + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const unsigned int channels[] = { + 2, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static const unsigned int acp5x_nau8821_format[] = {32}; + +static struct snd_pcm_hw_constraint_list constraints_sample_bits = { + .list = acp5x_nau8821_format, + .count = ARRAY_SIZE(acp5x_nau8821_format), +}; + +static int acp5x_8821_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + machine->cap_i2s_instance = I2S_SP_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + &constraints_sample_bits); + + return 0; +} + +static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); + int ret, bclk; + + if (!dai) + return -EINVAL; + + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(card->dev, "can't set FS clock %d\n", ret); + + bclk = snd_soc_params_to_bclk(params); + if (bclk < 0) { + dev_err(dai->dev, "Fail to get BCLK rate: %d\n", bclk); + return bclk; + } + + ret = snd_soc_dai_set_pll(dai, 0, 0, bclk, params_rate(params) * 256); + if (ret < 0) + dev_err(card->dev, "can't set FLL: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops acp5x_8821_ops = { + .startup = acp5x_8821_startup, + .hw_params = acp5x_nau8821_hw_params, +}; + +static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); + struct snd_pcm_runtime *runtime = substream->runtime; + + machine->play_i2s_instance = I2S_HS_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + return 0; +} + +static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + unsigned int bclk, rate = params_rate(params); + struct snd_soc_component *comp; + int ret, i; + + switch (rate) { + case 48000: + bclk = 1536000; + break; + default: + bclk = 0; + break; + } + + for_each_rtd_components(rtd, i, comp) { + if (!(strcmp(comp->name, ACP5X_CS35L41_COMP_LNAME)) || + !(strcmp(comp->name, ACP5X_CS35L41_COMP_RNAME))) { + if (!bclk) { + dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); + return -EINVAL; + } + + ret = snd_soc_component_set_sysclk(comp, 0, 0, bclk, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(comp->dev, "failed to set SYSCLK: %d\n", ret); + return ret; + } + } + } + + return 0; +} + +static const struct snd_soc_ops acp5x_cs35l41_play_ops = { + .startup = acp5x_cs35l41_startup, + .hw_params = acp5x_cs35l41_hw_params, +}; + +static struct snd_soc_codec_conf acp5x_cs35l41_conf[] = { + { + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_RNAME), + .name_prefix = "Right", + }, +}; + +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LNAME, + ACP5X_CS35L41_DAI_NAME), + COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, + ACP5X_CS35L41_DAI_NAME))); + +static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { + { + .name = "acp5x-8821-play", + .stream_name = "Playback/Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBC_CFC, + .ops = &acp5x_8821_ops, + .init = acp5x_8821_init, + SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform), + }, + { + .name = "acp5x-CS35L41-Stereo", + .stream_name = "CS35L41 Stereo Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBC_CFC, + .playback_only = 1, + .ops = &acp5x_cs35l41_play_ops, + SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), + }, +}; + +static const struct snd_soc_dapm_widget acp5x_8821_35l41_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route acp5x_8821_35l41_audio_route[] = { + /* HP jack connectors - unknown if we have jack detection */ + { "Headphone", NULL, "HPOL" }, + { "Headphone", NULL, "HPOR" }, + { "MICL", NULL, "Headset Mic" }, + { "MICR", NULL, "Headset Mic" }, + { "DMIC", NULL, "Int Mic" }, + + { "Headphone", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, + { "Int Mic", NULL, "Platform Clock" }, +}; + +static struct snd_soc_card acp5x_8821_35l41_card = { + .name = "acp5x", + .owner = THIS_MODULE, + .dai_link = acp5x_8821_35l41_dai, + .num_links = ARRAY_SIZE(acp5x_8821_35l41_dai), + .dapm_widgets = acp5x_8821_35l41_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_35l41_widgets), + .dapm_routes = acp5x_8821_35l41_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp5x_8821_35l41_audio_route), + .codec_conf = acp5x_cs35l41_conf, + .num_configs = ARRAY_SIZE(acp5x_cs35l41_conf), + .controls = acp5x_8821_controls, + .num_controls = ARRAY_SIZE(acp5x_8821_controls), +}; + +static int acp5x_max98388_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); + struct snd_pcm_runtime *runtime = substream->runtime; + + machine->play_i2s_instance = I2S_HS_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + return 0; +} + +static const struct snd_soc_ops acp5x_max98388_play_ops = { + .startup = acp5x_max98388_startup, +}; + +static struct snd_soc_codec_conf acp5x_max98388_conf[] = { + { + .dlc = COMP_CODEC_CONF(ACP5X_MAX98388_COMP_LNAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(ACP5X_MAX98388_COMP_RNAME), + .name_prefix = "Right", + }, +}; + +SND_SOC_DAILINK_DEF(max98388, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_MAX98388_COMP_LNAME, + ACP5X_MAX98388_DAI_NAME), + COMP_CODEC(ACP5X_MAX98388_COMP_RNAME, + ACP5X_MAX98388_DAI_NAME))); + +static struct snd_soc_dai_link acp5x_8821_98388_dai[] = { + { + .name = "acp5x-8821-play", + .stream_name = "Playback/Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBC_CFC, + .ops = &acp5x_8821_ops, + .init = acp5x_8821_init, + SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform), + }, + { + .name = "acp5x-max98388-play", + .stream_name = "MAX98388 Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBC_CFC, + .playback_only = 1, + .ops = &acp5x_max98388_play_ops, + SND_SOC_DAILINK_REG(acp5x_bt, max98388, platform), + }, +}; + +static const struct snd_soc_dapm_widget acp5x_8821_98388_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SPK("SPK", NULL), +}; + +static const struct snd_soc_dapm_route acp5x_8821_98388_route[] = { + { "Headphone", NULL, "HPOL" }, + { "Headphone", NULL, "HPOR" }, + { "MICL", NULL, "Headset Mic" }, + { "MICR", NULL, "Headset Mic" }, + { "DMIC", NULL, "Int Mic" }, + + { "Headphone", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, + { "Int Mic", NULL, "Platform Clock" }, + + { "SPK", NULL, "Left BE_OUT" }, + { "SPK", NULL, "Right BE_OUT" }, +}; + +static struct snd_soc_card acp5x_8821_98388_card = { + .name = "acp5x-max98388", + .owner = THIS_MODULE, + .dai_link = acp5x_8821_98388_dai, + .num_links = ARRAY_SIZE(acp5x_8821_98388_dai), + .dapm_widgets = acp5x_8821_98388_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_98388_widgets), + .dapm_routes = acp5x_8821_98388_route, + .num_dapm_routes = ARRAY_SIZE(acp5x_8821_98388_route), + .codec_conf = acp5x_max98388_conf, + .num_configs = ARRAY_SIZE(acp5x_max98388_conf), + .controls = acp5x_8821_controls, + .num_controls = ARRAY_SIZE(acp5x_8821_controls), +}; + +static const struct dmi_system_id acp5x_vg_quirk_table[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Valve"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), + }, + .driver_data = (void *)&acp5x_8821_35l41_card, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Valve"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"), + }, + .driver_data = (void *)&acp5x_8821_98388_card, + }, + {} +}; + +static int acp5x_probe(struct platform_device *pdev) +{ + const struct dmi_system_id *dmi_id; + struct acp5x_platform_info *machine; + struct device *dev = &pdev->dev; + struct snd_soc_card *card; + int ret; + + dmi_id = dmi_first_match(acp5x_vg_quirk_table); + if (!dmi_id || !dmi_id->driver_data) + return -ENODEV; + + machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL); + if (!machine) + return -ENOMEM; + + card = dmi_id->driver_data; + card->dev = dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + + ret = devm_snd_soc_register_card(dev, card); + if (ret) + return dev_err_probe(dev, ret, "Register card (%s) failed\n", card->name); + + return 0; +} + +static struct platform_driver acp5x_mach_driver = { + .driver = { + .name = DRV_NAME, + .pm = &snd_soc_pm_ops, + }, + .probe = acp5x_probe, +}; + +module_platform_driver(acp5x_mach_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("NAU8821/CS35L41 & NAU8821/MAX98388 audio support"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c new file mode 100644 index 000000000..831e30e9b --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -0,0 +1,513 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp5x.h" + +#define DRV_NAME "acp5x_i2s_dma" + +static const struct snd_pcm_hardware acp5x_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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .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 acp5x_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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .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, +}; + +static irqreturn_t i2s_irq_handler(int irq, void *dev_id) +{ + struct i2s_dev_data *vg_i2s_data; + u16 irq_flag; + u32 val; + + vg_i2s_data = dev_id; + if (!vg_i2s_data) + return IRQ_NONE; + + irq_flag = 0; + val = acp_readl(vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + if ((val & BIT(HS_TX_THRESHOLD)) && vg_i2s_data->play_stream) { + acp_writel(BIT(HS_TX_THRESHOLD), vg_i2s_data->acp5x_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->play_stream); + irq_flag = 1; + } + if ((val & BIT(I2S_TX_THRESHOLD)) && vg_i2s_data->i2ssp_play_stream) { + acp_writel(BIT(I2S_TX_THRESHOLD), + vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->i2ssp_play_stream); + irq_flag = 1; + } + + if ((val & BIT(HS_RX_THRESHOLD)) && vg_i2s_data->capture_stream) { + acp_writel(BIT(HS_RX_THRESHOLD), vg_i2s_data->acp5x_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->capture_stream); + irq_flag = 1; + } + if ((val & BIT(I2S_RX_THRESHOLD)) && vg_i2s_data->i2ssp_capture_stream) { + acp_writel(BIT(I2S_RX_THRESHOLD), + vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->i2ssp_capture_stream); + irq_flag = 1; + } + + if (irq_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static void config_acp5x_dma(struct i2s_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val, acp_fifo_addr, reg_fifo_addr; + u32 reg_dma_size, reg_fifo_size; + dma_addr_t addr; + + addr = rtd->dma_addr; + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + val = ACP_SRAM_HS_PB_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_PB_PTE_OFFSET; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + val = ACP_SRAM_HS_CP_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_CP_PTE_OFFSET; + } + } + /* Group Enable */ + acp_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp5x_base + + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + acp_writel(PAGE_SIZE_4K_ENABLE, rtd->acp5x_base + + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + acp_writel(low, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + acp_writel(high, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val + 4); + /* Move to next physically contiguous page */ + val += 8; + addr += PAGE_SIZE; + } + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_dma_size = ACP_HS_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + HS_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_TX_FIFOADDR; + reg_fifo_size = ACP_HS_TX_FIFOSIZE; + acp_writel(I2S_HS_TX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_HS_TX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = ACP_I2S_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR; + reg_fifo_size = ACP_I2S_TX_FIFOSIZE; + acp_writel(I2S_SP_TX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_I2S_TX_RINGBUFADDR); + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_dma_size = ACP_HS_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + HS_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_RX_FIFOADDR; + reg_fifo_size = ACP_HS_RX_FIFOSIZE; + acp_writel(I2S_HS_RX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_HS_RX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = ACP_I2S_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR; + reg_fifo_size = ACP_I2S_RX_FIFOSIZE; + acp_writel(I2S_SP_RX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_I2S_RX_RINGBUFADDR); + } + } + acp_writel(DMA_SIZE, rtd->acp5x_base + reg_dma_size); + acp_writel(acp_fifo_addr, rtd->acp5x_base + reg_fifo_addr); + acp_writel(FIFO_SIZE, rtd->acp5x_base + reg_fifo_size); + acp_writel(BIT(I2S_RX_THRESHOLD) | BIT(HS_RX_THRESHOLD) + | BIT(I2S_TX_THRESHOLD) | BIT(HS_TX_THRESHOLD), + rtd->acp5x_base + ACP_EXTERNAL_INTR_CNTL); +} + +static int acp5x_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *i2s_data; + int ret; + + runtime = substream->runtime; + prtd = snd_soc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + + i2s_data = kzalloc_obj(*i2s_data); + if (!i2s_data) + return -ENOMEM; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp5x_pcm_hardware_playback; + else + runtime->hw = acp5x_pcm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(i2s_data); + return ret; + } + i2s_data->acp5x_base = adata->acp5x_base; + runtime->private_data = i2s_data; + return ret; +} + +static int acp5x_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp5x_platform_info *pinfo; + struct i2s_dev_data *adata; + u64 size; + + prtd = snd_soc_substream_to_rtd(substream); + card = prtd->card; + pinfo = snd_soc_card_get_drvdata(card); + adata = dev_get_drvdata(component->dev); + rtd = substream->runtime->private_data; + + if (!rtd) + return -EINVAL; + + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + rtd->i2s_instance = pinfo->play_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + adata->play_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = substream; + } + } else { + rtd->i2s_instance = pinfo->cap_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + adata->capture_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = substream; + } + } + } else { + dev_err(component->dev, "pinfo failed\n"); + return -EINVAL; + } + size = params_buffer_bytes(params); + rtd->dma_addr = substream->runtime->dma_addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + config_acp5x_dma(rtd, substream->stream); + return 0; +} + +static snd_pcm_uframes_t acp5x_dma_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct i2s_stream_instance *rtd; + u32 pos; + u32 buffersize; + u64 bytescount; + + rtd = substream->runtime->private_data; + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + bytescount = acp_get_byte_count(rtd, substream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(substream->runtime, pos); +} + +static int acp5x_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp5x_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *ins; + + prtd = snd_soc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + ins = substream->runtime->private_data; + if (!ins) + return -EINVAL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (ins->i2s_instance) { + case I2S_HS_INSTANCE: + adata->play_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = NULL; + } + } else { + switch (ins->i2s_instance) { + case I2S_HS_INSTANCE: + adata->capture_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = NULL; + } + } + kfree(ins); + return 0; +} + +static const struct snd_soc_component_driver acp5x_i2s_component = { + .name = DRV_NAME, + .open = acp5x_dma_open, + .close = acp5x_dma_close, + .hw_params = acp5x_dma_hw_params, + .pointer = acp5x_dma_pointer, + .pcm_new = acp5x_dma_new, +}; + +static int acp5x_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + unsigned int irqflags; + int status; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "platform_data not retrieved\n"); + return -ENODEV; + } + irqflags = *((unsigned int *)(pdev->dev.platform_data)); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp5x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp5x_base) + return -ENOMEM; + + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->i2s_irq = status; + + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp5x_i2s_component, + NULL, 0); + if (status) { + dev_err(&pdev->dev, "Fail to register acp i2s component\n"); + return status; + } + status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler, + irqflags, "ACP5x_I2S_IRQ", adata); + if (status) { + dev_err(&pdev->dev, "ACP5x I2S IRQ request failed\n"); + return status; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp5x_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp5x_pcm_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + struct i2s_stream_instance *rtd; + u32 val; + + adata = dev_get_drvdata(dev); + + if (adata->play_stream && adata->play_stream->runtime) { + rtd = adata->play_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK); + acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_HSTDM_ITER); + if (adata->tdm_mode == TDM_ENABLE) { + acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_HSTDM_TXFRMT); + val = acp_readl(adata->acp5x_base + ACP_HSTDM_ITER); + acp_writel(val | 0x2, adata->acp5x_base + ACP_HSTDM_ITER); + } + } + if (adata->i2ssp_play_stream && adata->i2ssp_play_stream->runtime) { + rtd = adata->i2ssp_play_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK); + acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_I2STDM_ITER); + if (adata->tdm_mode == TDM_ENABLE) { + acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_I2STDM_TXFRMT); + val = acp_readl(adata->acp5x_base + ACP_I2STDM_ITER); + acp_writel(val | 0x2, adata->acp5x_base + ACP_I2STDM_ITER); + } + } + + if (adata->capture_stream && adata->capture_stream->runtime) { + rtd = adata->capture_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_HSTDM_IRER); + if (adata->tdm_mode == TDM_ENABLE) { + acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_HSTDM_RXFRMT); + val = acp_readl(adata->acp5x_base + ACP_HSTDM_IRER); + acp_writel(val | 0x2, adata->acp5x_base + ACP_HSTDM_IRER); + } + } + if (adata->i2ssp_capture_stream && adata->i2ssp_capture_stream->runtime) { + rtd = adata->i2ssp_capture_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_I2STDM_IRER); + if (adata->tdm_mode == TDM_ENABLE) { + acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_I2STDM_RXFRMT); + val = acp_readl(adata->acp5x_base + ACP_I2STDM_IRER); + acp_writel(val | 0x2, adata->acp5x_base + ACP_I2STDM_IRER); + } + } + acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int acp5x_pcm_suspend(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp_writel(0, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int acp5x_pcm_runtime_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static const struct dev_pm_ops acp5x_pm_ops = { + RUNTIME_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume) +}; + +static struct platform_driver acp5x_dma_driver = { + .probe = acp5x_audio_probe, + .remove = acp5x_audio_remove, + .driver = { + .name = "acp5x_i2s_dma", + .pm = &acp5x_pm_ops, + }, +}; + +module_platform_driver(acp5x_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP 5.x PCM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/vangogh/acp5x.h b/sound/soc/amd/vangogh/acp5x.h new file mode 100644 index 000000000..ac1936a8c --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PCM Driver + * + * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include "vg_chip_offset_byte.h" +#include + +#define ACP5x_PHY_BASE_ADDRESS 0x1240000 +#define ACP_DEVICE_ID 0x15E2 +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP_ERR_INTR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF + +#define ACP5x_DEVS 4 +#define ACP5x_REG_START 0x1240000 +#define ACP5x_REG_END 0x1250200 +#define ACP5x_I2STDM_REG_START 0x1242400 +#define ACP5x_I2STDM_REG_END 0x1242410 +#define ACP5x_HS_TDM_REG_START 0x1242814 +#define ACP5x_HS_TDM_REG_END 0x1242824 +#define I2S_MODE 0 +#define ACP5x_I2S_MODE 1 +#define ACP5x_RES 4 +#define I2S_RX_THRESHOLD 27 +#define I2S_TX_THRESHOLD 28 +#define HS_TX_THRESHOLD 24 +#define HS_RX_THRESHOLD 23 + +#define I2S_SP_INSTANCE 1 +#define I2S_HS_INSTANCE 2 + +#define ACP_SRAM_PTE_OFFSET 0x02050000 +#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 +#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 +#define ACP_SRAM_HS_PB_PTE_OFFSET 0x200 +#define ACP_SRAM_HS_CP_PTE_OFFSET 0x300 +#define PAGE_SIZE_4K_ENABLE 0x2 +#define I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define I2S_SP_RX_MEM_WINDOW_START 0x4020000 +#define I2S_HS_TX_MEM_WINDOW_START 0x4040000 +#define I2S_HS_RX_MEM_WINDOW_START 0x4060000 + +#define SP_PB_FIFO_ADDR_OFFSET 0x500 +#define SP_CAPT_FIFO_ADDR_OFFSET 0x700 +#define HS_PB_FIFO_ADDR_OFFSET 0x900 +#define HS_CAPT_FIFO_ADDR_OFFSET 0xB00 +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 8 +#define PLAYBACK_MAX_PERIOD_SIZE 8192 +#define PLAYBACK_MIN_PERIOD_SIZE 1024 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 8 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 1024 + +#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER +#define FIFO_SIZE 0x100 +#define DMA_SIZE 0x40 +#define FRM_LEN 0x100 + +#define I2S_MASTER_MODE_ENABLE 1 +#define I2S_MASTER_MODE_DISABLE 0 + +#define SLOT_WIDTH_8 8 +#define SLOT_WIDTH_16 16 +#define SLOT_WIDTH_24 24 +#define SLOT_WIDTH_32 32 +#define TDM_ENABLE 1 +#define TDM_DISABLE 0 +#define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38 + +struct i2s_dev_data { + bool tdm_mode; + bool master_mode; + int i2s_irq; + u16 i2s_instance; + u32 tdm_fmt; + void __iomem *acp5x_base; + struct snd_pcm_substream *play_stream; + struct snd_pcm_substream *capture_stream; + struct snd_pcm_substream *i2ssp_play_stream; + struct snd_pcm_substream *i2ssp_capture_stream; +}; + +struct i2s_stream_instance { + u16 num_pages; + u16 i2s_instance; + u16 direction; + u16 channels; + u32 xfer_resolution; + u32 val; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp5x_base; + u32 lrclk_div; + u32 bclk_div; +}; + +union acp_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +struct acp5x_platform_info { + u16 play_i2s_instance; + u16 cap_i2s_instance; +}; + +union acp_i2stdm_mstrclkgen { + struct { + u32 i2stdm_master_mode : 1; + u32 i2stdm_format_mode : 1; + u32 i2stdm_lrclk_div_val : 9; + u32 i2stdm_bclk_div_val : 11; + u32:10; + } bitfields, bits; + u32 u32_all; +}; + +/* common header file uses exact offset rather than relative + * offset which requires subtraction logic from base_addr + * for accessing ACP5x MMIO space registers + */ +static inline u32 acp_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP5x_PHY_BASE_ADDRESS); +} + +static inline void acp_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS); +} + +int snd_amd_acp_find_config(struct pci_dev *pci); + +static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, + int direction) +{ + union acp_dma_count byte_count; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_HS_TX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_HS_TX_LINEARPOSCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_I2S_TX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_I2S_TX_LINEARPOSCNTR_LOW); + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_HS_RX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_HS_RX_LINEARPOSCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_I2S_RX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_I2S_RX_LINEARPOSCNTR_LOW); + } + } + return byte_count.bytescount; +} + +static inline void acp5x_set_i2s_clk(struct i2s_dev_data *adata, + struct i2s_stream_instance *rtd) +{ + union acp_i2stdm_mstrclkgen mclkgen; + u32 master_reg; + + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + master_reg = ACP_I2STDM2_MSTRCLKGEN; + break; + case I2S_SP_INSTANCE: + default: + master_reg = ACP_I2STDM0_MSTRCLKGEN; + break; + } + + mclkgen.bits.i2stdm_master_mode = 0x1; + if (adata->tdm_mode) + mclkgen.bits.i2stdm_format_mode = 0x01; + else + mclkgen.bits.i2stdm_format_mode = 0x00; + + mclkgen.bits.i2stdm_bclk_div_val = rtd->bclk_div; + mclkgen.bits.i2stdm_lrclk_div_val = rtd->lrclk_div; + acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg); +} diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c new file mode 100644 index 000000000..af56ff09f --- /dev/null +++ b/sound/soc/amd/vangogh/pci-acp5x.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD Vangogh ACP PCI Driver +// +// Copyright (C) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include + +#include "acp5x.h" +#include "../mach-config.h" + +struct acp5x_dev_data { + void __iomem *acp5x_base; + bool acp5x_audio_mode; + struct resource *res; + struct platform_device *pdev[ACP5x_DEVS]; +}; + +static int acp5x_power_on(void __iomem *acp5x_base) +{ + u32 val; + int timeout; + + val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if ((val & ACP_PGFSM_STATUS_MASK) != + ACP_POWER_ON_IN_PROGRESS) + acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp5x_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); + if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int acp5x_reset(void __iomem *acp5x_base) +{ + u32 val; + int timeout; + + acp_writel(1, acp5x_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_SOFT_RESET); + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) + break; + cpu_relax(); + } + acp_writel(0, acp5x_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void acp5x_enable_interrupts(void __iomem *acp5x_base) +{ + acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB); +} + +static void acp5x_disable_interrupts(void __iomem *acp5x_base) +{ + acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base + + ACP_EXTERNAL_INTR_STAT); + acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL); + acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp5x_init(void __iomem *acp5x_base) +{ + int ret; + + /* power on */ + ret = acp5x_power_on(acp5x_base); + if (ret) { + pr_err("ACP5x power on failed\n"); + return ret; + } + acp_writel(0x01, acp5x_base + ACP_CONTROL); + /* Reset */ + ret = acp5x_reset(acp5x_base); + if (ret) { + pr_err("ACP5x reset failed\n"); + return ret; + } + acp_writel(0x03, acp5x_base + ACP_CLKMUX_SEL); + acp5x_enable_interrupts(acp5x_base); + return 0; +} + +static int acp5x_deinit(void __iomem *acp5x_base) +{ + int ret; + + acp5x_disable_interrupts(acp5x_base); + /* Reset */ + ret = acp5x_reset(acp5x_base); + if (ret) { + pr_err("ACP5x reset failed\n"); + return ret; + } + acp_writel(0x00, acp5x_base + ACP_CLKMUX_SEL); + acp_writel(0x00, acp5x_base + ACP_CONTROL); + return 0; +} + +static int snd_acp5x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp5x_dev_data *adata; + struct platform_device_info pdevinfo[ACP5x_DEVS]; + unsigned int irqflags, flag; + int ret, i; + u32 addr, val; + + /* + * Return if ACP config flag is defined, except when board + * supports SOF while it is not being enabled in kernel config. + */ + flag = snd_amd_acp_find_config(pci); + if (flag != FLAG_AMD_LEGACY && + (flag != FLAG_AMD_SOF || IS_ENABLED(CONFIG_SND_SOC_SOF_AMD_VANGOGH))) + return -ENODEV; + + irqflags = IRQF_SHARED; + if (pci->revision != 0x50) + return -ENODEV; + + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP5x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp5x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + addr = pci_resource_start(pci, 0); + adata->acp5x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp5x_base) { + ret = -ENOMEM; + goto release_regions; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = acp5x_init(adata->acp5x_base); + if (ret) + goto release_regions; + + val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG); + switch (val) { + case I2S_MODE: + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * ACP5x_RES, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res[0].name = "acp5x_i2s_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + adata->res[0].start = addr; + adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START); + + adata->res[1].name = "acp5x_i2s_sp"; + adata->res[1].flags = IORESOURCE_MEM; + adata->res[1].start = addr + ACP5x_I2STDM_REG_START; + adata->res[1].end = addr + ACP5x_I2STDM_REG_END; + + adata->res[2].name = "acp5x_i2s_hs"; + adata->res[2].flags = IORESOURCE_MEM; + adata->res[2].start = addr + ACP5x_HS_TDM_REG_START; + adata->res[2].end = addr + ACP5x_HS_TDM_REG_END; + + adata->res[3].name = "acp5x_i2s_irq"; + adata->res[3].flags = IORESOURCE_IRQ; + adata->res[3].start = pci->irq; + adata->res[3].end = adata->res[3].start; + + adata->acp5x_audio_mode = ACP5x_I2S_MODE; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo[0].name = "acp5x_i2s_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 4; + pdevinfo[0].res = &adata->res[0]; + pdevinfo[0].data = &irqflags; + pdevinfo[0].size_data = sizeof(irqflags); + + pdevinfo[1].name = "acp5x_i2s_playcap"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + pdevinfo[1].num_res = 1; + pdevinfo[1].res = &adata->res[1]; + + pdevinfo[2].name = "acp5x_i2s_playcap"; + pdevinfo[2].id = 1; + pdevinfo[2].parent = &pci->dev; + pdevinfo[2].num_res = 1; + pdevinfo[2].res = &adata->res[2]; + + pdevinfo[3].name = "acp5x_mach"; + pdevinfo[3].id = 0; + pdevinfo[3].parent = &pci->dev; + for (i = 0; i < ACP5x_DEVS; i++) { + adata->pdev[i] = + platform_device_register_full(&pdevinfo[i]); + if (IS_ERR(adata->pdev[i])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[i].name); + ret = PTR_ERR(adata->pdev[i]); + goto unregister_devs; + } + } + break; + default: + dev_info(&pci->dev, "ACP audio mode : %d\n", val); + } + pm_runtime_set_autosuspend_delay(&pci->dev, 2000); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +unregister_devs: + for (--i; i >= 0; i--) + platform_device_unregister(adata->pdev[i]); +de_init: + if (acp5x_deinit(adata->acp5x_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int snd_acp5x_suspend(struct device *dev) +{ + int ret; + struct acp5x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp5x_deinit(adata->acp5x_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + else + dev_dbg(dev, "ACP de-initialized\n"); + + return ret; +} + +static int snd_acp5x_resume(struct device *dev) +{ + int ret; + struct acp5x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp5x_init(adata->acp5x_base); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static const struct dev_pm_ops acp5x_pm = { + RUNTIME_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume) +}; + +static void snd_acp5x_remove(struct pci_dev *pci) +{ + struct acp5x_dev_data *adata; + int i, ret; + + adata = pci_get_drvdata(pci); + if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) { + for (i = 0; i < ACP5x_DEVS; i++) + platform_device_unregister(adata->pdev[i]); + } + ret = acp5x_deinit(adata->acp5x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp5x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp5x_ids); + +static struct pci_driver acp5x_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp5x_ids, + .probe = snd_acp5x_probe, + .remove = snd_acp5x_remove, + .driver = { + .pm = pm_ptr(&acp5x_pm), + } +}; + +module_pci_driver(acp5x_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD Vangogh ACP PCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/vangogh/vg_chip_offset_byte.h b/sound/soc/amd/vangogh/vg_chip_offset_byte.h new file mode 100644 index 000000000..b1165ae14 --- /dev/null +++ b/sound/soc/amd/vangogh/vg_chip_offset_byte.h @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 5.x Register Documentation + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#ifndef _acp_ip_OFFSET_HEADER +#define _acp_ip_OFFSET_HEADER + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_CNTL_1 0x1240004 +#define ACP_DMA_CNTL_2 0x1240008 +#define ACP_DMA_CNTL_3 0x124000C +#define ACP_DMA_CNTL_4 0x1240010 +#define ACP_DMA_CNTL_5 0x1240014 +#define ACP_DMA_CNTL_6 0x1240018 +#define ACP_DMA_CNTL_7 0x124001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_DSCR_CNT_1 0x1240044 +#define ACP_DMA_DSCR_CNT_2 0x1240048 +#define ACP_DMA_DSCR_CNT_3 0x124004C +#define ACP_DMA_DSCR_CNT_4 0x1240050 +#define ACP_DMA_DSCR_CNT_5 0x1240054 +#define ACP_DMA_DSCR_CNT_6 0x1240058 +#define ACP_DMA_DSCR_CNT_7 0x124005C +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_PRIO_1 0x1240064 +#define ACP_DMA_PRIO_2 0x1240068 +#define ACP_DMA_PRIO_3 0x124006C +#define ACP_DMA_PRIO_4 0x1240070 +#define ACP_DMA_PRIO_5 0x1240074 +#define ACP_DMA_PRIO_6 0x1240078 +#define ACP_DMA_PRIO_7 0x124007C +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_DSCR_1 0x1240084 +#define ACP_DMA_CUR_DSCR_2 0x1240088 +#define ACP_DMA_CUR_DSCR_3 0x124008C +#define ACP_DMA_CUR_DSCR_4 0x1240090 +#define ACP_DMA_CUR_DSCR_5 0x1240094 +#define ACP_DMA_CUR_DSCR_6 0x1240098 +#define ACP_DMA_CUR_DSCR_7 0x124009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define ACP_DMA_ERR_STS_0 0x12400C0 +#define ACP_DMA_ERR_STS_1 0x12400C4 +#define ACP_DMA_ERR_STS_2 0x12400C8 +#define ACP_DMA_ERR_STS_3 0x12400CC +#define ACP_DMA_ERR_STS_4 0x12400D0 +#define ACP_DMA_ERR_STS_5 0x12400D4 +#define ACP_DMA_ERR_STS_6 0x12400D8 +#define ACP_DMA_ERR_STS_7 0x12400DC +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +/* Registers from ACP_AXI2AXIATU block */ +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define ACPAXI2AXI_ATU_CTRL 0x1240C40 + +/* Registers from ACP_CLKRST block */ +#define ACP_SOFT_RESET 0x1241000 +#define ACP_CONTROL 0x1241004 +#define ACP_STATUS 0x1241008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 + +/* Registers from ACP_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_CNTL 0x1241804 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_ERROR_STATUS 0x12418C4 +#define ACP_SW_I2S_ERROR_REASON 0x12418C8 +#define ACP_MEM_PG_STS 0x12418CC +#define ACP_PGMEM_DEEP_SLEEP_CTRL 0x12418D0 +#define ACP_PGMEM_SHUT_DOWN_CTRL 0x12418D4 + +/* Registers from ACP_PGFSM block */ +#define ACP_PIN_CONFIG 0x1241400 +#define ACP_PAD_PULLUP_CTRL 0x1241404 +#define ACP_PAD_PULLDOWN_CTRL 0x1241408 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124140C +#define ACP_PAD_SCHMEN_CTRL 0x1241410 +#define ACP_SW_PAD_KEEPER_EN 0x1241414 +#define ACP_SW_WAKE_EN 0x1241418 +#define ACP_I2S_WAKE_EN 0x124141C +#define ACP_PME_EN 0x1241420 +#define ACP_PGFSM_CONTROL 0x1241424 +#define ACP_PGFSM_STATUS 0x1241428 +#define ACP_CLKMUX_SEL 0x124142C +#define ACP_DEVICE_STATE 0x1241430 +#define AZ_DEVICE_STATE 0x1241434 +#define ACP_INTR_URGENCY_TIMER 0x1241438 +#define AZ_INTR_URGENCY_TIMER 0x124143C +#define ACP_AON_SW_INTR_TRIG 0x1241440 + +/* Registers from ACP_SCRATCH block */ +#define ACP_SCRATCH_REG_0 0x1250000 +#define ACP_SCRATCH_REG_1 0x1250004 +#define ACP_SCRATCH_REG_2 0x1250008 +#define ACP_SCRATCH_REG_3 0x125000C +#define ACP_SCRATCH_REG_4 0x1250010 +#define ACP_SCRATCH_REG_5 0x1250014 +#define ACP_SCRATCH_REG_6 0x1250018 +#define ACP_SCRATCH_REG_7 0x125001C +#define ACP_SCRATCH_REG_8 0x1250020 +#define ACP_SCRATCH_REG_9 0x1250024 +#define ACP_SCRATCH_REG_10 0x1250028 +#define ACP_SCRATCH_REG_11 0x125002C +#define ACP_SCRATCH_REG_12 0x1250030 +#define ACP_SCRATCH_REG_13 0x1250034 +#define ACP_SCRATCH_REG_14 0x1250038 +#define ACP_SCRATCH_REG_15 0x125003C +#define ACP_SCRATCH_REG_16 0x1250040 +#define ACP_SCRATCH_REG_17 0x1250044 +#define ACP_SCRATCH_REG_18 0x1250048 +#define ACP_SCRATCH_REG_19 0x125004C +#define ACP_SCRATCH_REG_20 0x1250050 +#define ACP_SCRATCH_REG_21 0x1250054 +#define ACP_SCRATCH_REG_22 0x1250058 +#define ACP_SCRATCH_REG_23 0x125005C +#define ACP_SCRATCH_REG_24 0x1250060 +#define ACP_SCRATCH_REG_25 0x1250064 +#define ACP_SCRATCH_REG_26 0x1250068 +#define ACP_SCRATCH_REG_27 0x125006C +#define ACP_SCRATCH_REG_28 0x1250070 +#define ACP_SCRATCH_REG_29 0x1250074 +#define ACP_SCRATCH_REG_30 0x1250078 +#define ACP_SCRATCH_REG_31 0x125007C +#define ACP_SCRATCH_REG_32 0x1250080 +#define ACP_SCRATCH_REG_33 0x1250084 +#define ACP_SCRATCH_REG_34 0x1250088 +#define ACP_SCRATCH_REG_35 0x125008C +#define ACP_SCRATCH_REG_36 0x1250090 +#define ACP_SCRATCH_REG_37 0x1250094 +#define ACP_SCRATCH_REG_38 0x1250098 +#define ACP_SCRATCH_REG_39 0x125009C +#define ACP_SCRATCH_REG_40 0x12500A0 +#define ACP_SCRATCH_REG_41 0x12500A4 +#define ACP_SCRATCH_REG_42 0x12500A8 +#define ACP_SCRATCH_REG_43 0x12500AC +#define ACP_SCRATCH_REG_44 0x12500B0 +#define ACP_SCRATCH_REG_45 0x12500B4 +#define ACP_SCRATCH_REG_46 0x12500B8 +#define ACP_SCRATCH_REG_47 0x12500BC +#define ACP_SCRATCH_REG_48 0x12500C0 +#define ACP_SCRATCH_REG_49 0x12500C4 +#define ACP_SCRATCH_REG_50 0x12500C8 +#define ACP_SCRATCH_REG_51 0x12500CC +#define ACP_SCRATCH_REG_52 0x12500D0 +#define ACP_SCRATCH_REG_53 0x12500D4 +#define ACP_SCRATCH_REG_54 0x12500D8 +#define ACP_SCRATCH_REG_55 0x12500DC +#define ACP_SCRATCH_REG_56 0x12500E0 +#define ACP_SCRATCH_REG_57 0x12500E4 +#define ACP_SCRATCH_REG_58 0x12500E8 +#define ACP_SCRATCH_REG_59 0x12500EC +#define ACP_SCRATCH_REG_60 0x12500F0 +#define ACP_SCRATCH_REG_61 0x12500F4 +#define ACP_SCRATCH_REG_62 0x12500F8 +#define ACP_SCRATCH_REG_63 0x12500FC +#define ACP_SCRATCH_REG_64 0x1250100 +#define ACP_SCRATCH_REG_65 0x1250104 +#define ACP_SCRATCH_REG_66 0x1250108 +#define ACP_SCRATCH_REG_67 0x125010C +#define ACP_SCRATCH_REG_68 0x1250110 +#define ACP_SCRATCH_REG_69 0x1250114 +#define ACP_SCRATCH_REG_70 0x1250118 +#define ACP_SCRATCH_REG_71 0x125011C +#define ACP_SCRATCH_REG_72 0x1250120 +#define ACP_SCRATCH_REG_73 0x1250124 +#define ACP_SCRATCH_REG_74 0x1250128 +#define ACP_SCRATCH_REG_75 0x125012C +#define ACP_SCRATCH_REG_76 0x1250130 +#define ACP_SCRATCH_REG_77 0x1250134 +#define ACP_SCRATCH_REG_78 0x1250138 +#define ACP_SCRATCH_REG_79 0x125013C +#define ACP_SCRATCH_REG_80 0x1250140 +#define ACP_SCRATCH_REG_81 0x1250144 +#define ACP_SCRATCH_REG_82 0x1250148 +#define ACP_SCRATCH_REG_83 0x125014C +#define ACP_SCRATCH_REG_84 0x1250150 +#define ACP_SCRATCH_REG_85 0x1250154 +#define ACP_SCRATCH_REG_86 0x1250158 +#define ACP_SCRATCH_REG_87 0x125015C +#define ACP_SCRATCH_REG_88 0x1250160 +#define ACP_SCRATCH_REG_89 0x1250164 +#define ACP_SCRATCH_REG_90 0x1250168 +#define ACP_SCRATCH_REG_91 0x125016C +#define ACP_SCRATCH_REG_92 0x1250170 +#define ACP_SCRATCH_REG_93 0x1250174 +#define ACP_SCRATCH_REG_94 0x1250178 +#define ACP_SCRATCH_REG_95 0x125017C +#define ACP_SCRATCH_REG_96 0x1250180 +#define ACP_SCRATCH_REG_97 0x1250184 +#define ACP_SCRATCH_REG_98 0x1250188 +#define ACP_SCRATCH_REG_99 0x125018C +#define ACP_SCRATCH_REG_100 0x1250190 +#define ACP_SCRATCH_REG_101 0x1250194 +#define ACP_SCRATCH_REG_102 0x1250198 +#define ACP_SCRATCH_REG_103 0x125019C +#define ACP_SCRATCH_REG_104 0x12501A0 +#define ACP_SCRATCH_REG_105 0x12501A4 +#define ACP_SCRATCH_REG_106 0x12501A8 +#define ACP_SCRATCH_REG_107 0x12501AC +#define ACP_SCRATCH_REG_108 0x12501B0 +#define ACP_SCRATCH_REG_109 0x12501B4 +#define ACP_SCRATCH_REG_110 0x12501B8 +#define ACP_SCRATCH_REG_111 0x12501BC +#define ACP_SCRATCH_REG_112 0x12501C0 +#define ACP_SCRATCH_REG_113 0x12501C4 +#define ACP_SCRATCH_REG_114 0x12501C8 +#define ACP_SCRATCH_REG_115 0x12501CC +#define ACP_SCRATCH_REG_116 0x12501D0 +#define ACP_SCRATCH_REG_117 0x12501D4 +#define ACP_SCRATCH_REG_118 0x12501D8 +#define ACP_SCRATCH_REG_119 0x12501DC +#define ACP_SCRATCH_REG_120 0x12501E0 +#define ACP_SCRATCH_REG_121 0x12501E4 +#define ACP_SCRATCH_REG_122 0x12501E8 +#define ACP_SCRATCH_REG_123 0x12501EC +#define ACP_SCRATCH_REG_124 0x12501F0 +#define ACP_SCRATCH_REG_125 0x12501F4 +#define ACP_SCRATCH_REG_126 0x12501F8 +#define ACP_SCRATCH_REG_127 0x12501FC +#define ACP_SCRATCH_REG_128 0x1250200 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM1_MSTRCLKGEN 0x1242418 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C +#define ACP_I2STDM_REFCLKGEN 0x1242420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 +#endif diff --git a/sound/soc/amd/yc/Makefile b/sound/soc/amd/yc/Makefile new file mode 100644 index 000000000..7a0a3a410 --- /dev/null +++ b/sound/soc/amd/yc/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Yellow Carp platform Support +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 +obj-$(CONFIG_SND_SOC_AMD_YC_MACH) += snd-soc-acp6x-mach.o diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c new file mode 100644 index 000000000..21d7ec0e7 --- /dev/null +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -0,0 +1,969 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Machine driver for AMD Yellow Carp platform using DMIC + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp6x.h" + +#define DRV_NAME "acp_yc_mach" + +SND_SOC_DAILINK_DEF(acp6x_pdm, + DAILINK_COMP_ARRAY(COMP_CPU("acp_yc_pdm_dma.0"))); + +SND_SOC_DAILINK_DEF(dmic_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0", + "dmic-hifi"))); + +SND_SOC_DAILINK_DEF(pdm_platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_yc_pdm_dma.0"))); + +static struct snd_soc_dai_link acp6x_dai_pdm[] = { + { + .name = "acp6x-dmic-capture", + .stream_name = "DMIC capture", + .capture_only = 1, + SND_SOC_DAILINK_REG(acp6x_pdm, dmic_codec, pdm_platform), + }, +}; + +static struct snd_soc_card acp6x_card = { + .name = "acp6x", + .owner = THIS_MODULE, + .dai_link = acp6x_dai_pdm, + .num_links = 1, +}; + +static const struct dmi_system_id yc_acp_quirk_table[] = { + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire AG14-22P"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Lecoo"), + DMI_MATCH(DMI_PRODUCT_NAME, "Bellator N176"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15-fc0xxx"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Gaming Laptop 16-ap0xxx"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5525"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D0"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D0"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D1"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D2"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D3"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D4"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D5"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CF"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CQ"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CR"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CM"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CN"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CH"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CJ"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CK"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21CL"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21EF"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21EM"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21HY"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21J0"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21J5"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21J6"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + 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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82TL"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82UG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82UU"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82V2"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82YM"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83AS"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83BS"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), + } + }, + { + .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, "RB"), + DMI_MATCH(DMI_PRODUCT_NAME, "Nitro ANV15-41"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83J2"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83J3"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + 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 = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M6400RC"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M3402RA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M6500RE"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M6501RM"), + } + }, + { + .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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7VE"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7VF"), + } + }, + { + .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, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 17 D7VF"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vector A16 HX A8WHG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Crosshair A16 HX D7WFKG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Raider A18 HX A7VHG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vector A16 HX A8WIG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Raider A18 HX A9WJG"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R7 AMD"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R1 AMD"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"), + DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"), + DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 15 2022"), + } + }, + { + .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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "RB"), + DMI_MATCH(DMI_PRODUCT_NAME, "Swift SFA16-41"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "IRBIS"), + DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK PM1503CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "Victus by HP Gaming Laptop 15-fb1xxx"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "Victus by HP Gaming Laptop 15-fb2xxx"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A42"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A43"), + } + }, + { + .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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A3E"), + } + }, + { + .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, "8A81"), + } + }, + { + .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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8BD6"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8EE4"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8E35"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8F06"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "Victus by HP Laptop 16-e1xxx"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MECHREVO"), + DMI_MATCH(DMI_BOARD_NAME, "MRID6"), + } + }, + { + .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"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "System76"), + DMI_MATCH(DMI_PRODUCT_VERSION, "pang13"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7UCX"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HONOR"), + DMI_MATCH(DMI_PRODUCT_NAME, "GOH-X"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "RB"), + DMI_MATCH(DMI_BOARD_NAME, "XyloD5_RBU"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook_ASUSLaptop M6501RR_M6501RR"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK BM1503CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "PM1503CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "BM1403CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "BM1403CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Thin A15 B7VF"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Thin A15 B7VE"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Thin A15 B7UC"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M7601RM"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "MS-17LN"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "PM1403CDA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook_ASUSLaptop M6500RE_M6500RE"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "XIAOMI"), + DMI_MATCH(DMI_BOARD_NAME, "TM2423"), + } + }, + {} +}; + +static int acp6x_probe(struct platform_device *pdev) +{ + const struct dmi_system_id *dmi_id; + 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) { + const union acpi_object *obj; + + if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) && + obj->integer.value == 1) + 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) + platform_set_drvdata(pdev, dmi_id->driver_data); + + card = platform_get_drvdata(pdev); + if (!card) + return -ENODEV; + dev_info(&pdev->dev, "Enabling ACP DMIC support via %s", dmi_id ? "DMI" : "ACPI"); + acp6x_card.dev = &pdev->dev; + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "snd_soc_register_card(%s) failed\n", + card->name); + } + return 0; +} + +static struct platform_driver acp6x_mach_driver = { + .driver = { + .name = "acp_yc_mach", + .pm = &snd_soc_pm_ops, + }, + .probe = acp6x_probe, +}; + +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 new file mode 100644 index 000000000..710db721f --- /dev/null +++ b/sound/soc/amd/yc/acp6x-pdm-dma.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AMD ALSA SoC Yellow Carp PDM Driver + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp6x.h" + +#define DRV_NAME "acp_yc_pdm_dma" + +static int pdm_gain = 3; +module_param(pdm_gain, int, 0644); +MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)"); + +static const struct snd_pcm_hardware acp6x_pdm_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_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .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, +}; + +static void acp6x_init_pdm_ring_buffer(u32 physical_addr, u32 buffer_size, + u32 watermark_size, void __iomem *acp_base) +{ + acp6x_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR); + acp6x_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE); + acp6x_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + acp6x_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); +} + +static void acp6x_enable_pdm_clock(void __iomem *acp_base) +{ + u32 pdm_clk_enable, pdm_ctrl; + + pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; + pdm_ctrl = 0x00; + + acp6x_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); + pdm_ctrl = acp6x_readl(acp_base + ACP_WOV_MISC_CTRL); + pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL; + pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3)); + acp6x_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL); +} + +static void acp6x_enable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = acp6x_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl |= PDM_DMA_INTR_MASK; + acp6x_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void acp6x_disable_pdm_interrupts(void __iomem *acp_base) +{ + u32 ext_int_ctrl; + + ext_int_ctrl = acp6x_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_int_ctrl &= ~PDM_DMA_INTR_MASK; + acp6x_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static bool acp6x_check_pdm_dma_status(void __iomem *acp_base) +{ + bool pdm_dma_status; + u32 pdm_enable, pdm_dma_enable; + + pdm_dma_status = false; + pdm_enable = acp6x_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = acp6x_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & ACP_PDM_DMA_EN_STATUS)) + pdm_dma_status = true; + + return pdm_dma_status; +} + +static int acp6x_start_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable; + u32 pdm_dma_enable; + int timeout; + + pdm_enable = 0x01; + pdm_dma_enable = 0x01; + + acp6x_enable_pdm_clock(acp_base); + acp6x_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + acp6x_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = acp6x_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS) + return 0; + udelay(DELAY_US); + } + return -ETIMEDOUT; +} + +static int acp6x_stop_pdm_dma(void __iomem *acp_base) +{ + u32 pdm_enable, pdm_dma_enable; + int timeout; + + pdm_enable = 0x00; + pdm_dma_enable = 0x00; + + pdm_enable = acp6x_readl(acp_base + ACP_WOV_PDM_ENABLE); + pdm_dma_enable = acp6x_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if (pdm_dma_enable & 0x01) { + pdm_dma_enable = 0x02; + acp6x_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); + timeout = 0; + while (++timeout < ACP_COUNTER) { + pdm_dma_enable = acp6x_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); + if ((pdm_dma_enable & 0x02) == 0x00) + break; + udelay(DELAY_US); + } + if (timeout == ACP_COUNTER) + return -ETIMEDOUT; + } + if (pdm_enable == ACP_PDM_ENABLE) { + pdm_enable = ACP_PDM_DISABLE; + acp6x_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); + } + acp6x_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH); + return 0; +} + +static void acp6x_config_dma(struct pdm_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val; + dma_addr_t addr; + + addr = rtd->dma_addr; + val = PDM_PTE_OFFSET; + + /* Group Enable */ + acp6x_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp6x_base + + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + acp6x_writel(PAGE_SIZE_4K_ENABLE, rtd->acp6x_base + + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + acp6x_writel(low, rtd->acp6x_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + acp6x_writel(high, rtd->acp6x_base + ACP_SCRATCH_REG_0 + val + 4); + val += 8; + addr += PAGE_SIZE; + } +} + +static int acp6x_pdm_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct pdm_dev_data *adata; + struct pdm_stream_instance *pdm_data; + int ret; + + runtime = substream->runtime; + adata = dev_get_drvdata(component->dev); + pdm_data = kzalloc_obj(*pdm_data); + if (!pdm_data) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw = acp6x_pdm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(pdm_data); + return ret; + } + + acp6x_enable_pdm_interrupts(adata->acp6x_base); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + adata->capture_stream = substream; + + pdm_data->acp6x_base = adata->acp6x_base; + runtime->private_data = pdm_data; + return ret; +} + +static int acp6x_pdm_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct pdm_stream_instance *rtd; + size_t size, period_bytes; + + rtd = substream->runtime->private_data; + if (!rtd) + return -EINVAL; + size = params_buffer_bytes(params); + period_bytes = params_period_bytes(params); + rtd->dma_addr = substream->runtime->dma_addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + acp6x_config_dma(rtd, substream->stream); + acp6x_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, size, + period_bytes, rtd->acp6x_base); + return 0; +} + +static u64 acp6x_pdm_get_byte_count(struct pdm_stream_instance *rtd, + int direction) +{ + union acp_pdm_dma_count byte_count; + + byte_count.bcount.high = + acp6x_readl(rtd->acp6x_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + byte_count.bcount.low = + acp6x_readl(rtd->acp6x_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + return byte_count.bytescount; +} + +static snd_pcm_uframes_t acp6x_pdm_dma_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *stream) +{ + struct pdm_stream_instance *rtd; + u32 pos, buffersize; + u64 bytescount; + + rtd = stream->runtime->private_data; + buffersize = frames_to_bytes(stream->runtime, + stream->runtime->buffer_size); + bytescount = acp6x_pdm_get_byte_count(rtd, stream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(stream->runtime, pos); +} + +static int acp6x_pdm_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp6x_pdm_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); + + acp6x_disable_pdm_interrupts(adata->acp6x_base); + adata->capture_stream = NULL; + return 0; +} + +static int acp6x_pdm_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct pdm_stream_instance *rtd; + int ret; + bool pdm_status; + unsigned int ch_mask; + + rtd = substream->runtime->private_data; + ret = 0; + switch (substream->runtime->channels) { + case TWO_CH: + ch_mask = 0x00; + break; + default: + return -EINVAL; + } + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + acp6x_writel(ch_mask, rtd->acp6x_base + ACP_WOV_PDM_NO_OF_CHANNELS); + acp6x_writel(PDM_DECIMATION_FACTOR, rtd->acp6x_base + + ACP_WOV_PDM_DECIMATION_FACTOR); + rtd->bytescount = acp6x_pdm_get_byte_count(rtd, substream->stream); + pdm_status = acp6x_check_pdm_dma_status(rtd->acp6x_base); + if (!pdm_status) + ret = acp6x_start_pdm_dma(rtd->acp6x_base); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pdm_status = acp6x_check_pdm_dma_status(rtd->acp6x_base); + if (pdm_status) + ret = acp6x_stop_pdm_dma(rtd->acp6x_base); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static const struct snd_soc_dai_ops acp6x_pdm_dai_ops = { + .trigger = acp6x_pdm_dai_trigger, +}; + +static struct snd_soc_dai_driver acp6x_pdm_dai_driver = { + .capture = { + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 48000, + .rate_max = 48000, + }, + .ops = &acp6x_pdm_dai_ops, +}; + +static const struct snd_soc_component_driver acp6x_pdm_component = { + .name = DRV_NAME, + .open = acp6x_pdm_dma_open, + .close = acp6x_pdm_dma_close, + .hw_params = acp6x_pdm_dma_hw_params, + .pointer = acp6x_pdm_dma_pointer, + .pcm_new = acp6x_pdm_dma_new, + .legacy_dai_naming = 1, +}; + +static int acp6x_pdm_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct pdm_dev_data *adata; + int status; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp6x_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!adata->acp6x_base) + return -ENOMEM; + + adata->capture_stream = NULL; + + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp6x_pdm_component, + &acp6x_pdm_dai_driver, 1); + if (status) { + dev_err(&pdev->dev, "Fail to register acp pdm dai\n"); + + return -ENODEV; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; +} + +static void acp6x_pdm_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static int acp6x_pdm_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + struct snd_pcm_runtime *runtime; + struct pdm_stream_instance *rtd; + u32 period_bytes, buffer_len; + + adata = dev_get_drvdata(dev); + if (adata->capture_stream && adata->capture_stream->runtime) { + runtime = adata->capture_stream->runtime; + rtd = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + acp6x_config_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + acp6x_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, buffer_len, + period_bytes, adata->acp6x_base); + } + acp6x_enable_pdm_interrupts(adata->acp6x_base); + return 0; +} + +static int acp6x_pdm_suspend(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp6x_disable_pdm_interrupts(adata->acp6x_base); + return 0; +} + +static int acp6x_pdm_runtime_resume(struct device *dev) +{ + struct pdm_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp6x_enable_pdm_interrupts(adata->acp6x_base); + return 0; +} + +static const struct dev_pm_ops acp6x_pdm_pm_ops = { + RUNTIME_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_resume) +}; + +static struct platform_driver acp6x_pdm_dma_driver = { + .probe = acp6x_pdm_audio_probe, + .remove = acp6x_pdm_audio_remove, + .driver = { + .name = "acp_yc_pdm_dma", + .pm = pm_ptr(&acp6x_pdm_pm_ops), + }, +}; + +module_platform_driver(acp6x_pdm_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP6x YC PDM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/yc/acp6x.h b/sound/soc/amd/yc/acp6x.h new file mode 100644 index 000000000..2de7d1edf --- /dev/null +++ b/sound/soc/amd/yc/acp6x.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PDM Driver + * + * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include "acp6x_chip_offset_byte.h" + +#define ACP_DEVICE_ID 0x15E2 +#define ACP6x_PHY_BASE_ADDRESS 0x1240000 +#define ACP6x_REG_START 0x1240000 +#define ACP6x_REG_END 0x1250200 +#define ACP6x_DEVS 3 +#define ACP6x_PDM_MODE 1 + +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 +#define ACP_PGFSM_CNTL_POWER_ON_MASK 1 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP_PGFSM_STATUS_MASK 3 +#define ACP_POWERED_ON 0 +#define ACP_POWER_ON_IN_PROGRESS 1 +#define ACP_POWERED_OFF 2 +#define ACP_POWER_OFF_IN_PROGRESS 3 + +#define ACP_ERROR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF +#define PDM_DMA_STAT 0x10 + +#define PDM_DMA_INTR_MASK 0x10000 +#define ACP_ERROR_STAT 29 +#define PDM_DECIMATION_FACTOR 2 +#define ACP_PDM_CLK_FREQ_MASK 7 +#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3) +#define ACP_PDM_ENABLE 1 +#define ACP_PDM_DISABLE 0 +#define ACP_PDM_DMA_EN_STATUS 2 +#define TWO_CH 2 +#define DELAY_US 5 +#define ACP_COUNTER 20000 + +#define ACP_SRAM_PTE_OFFSET 0x03800000 +#define PAGE_SIZE_4K_ENABLE 2 +#define PDM_PTE_OFFSET 0 +#define PDM_MEM_WINDOW_START 0x4000000 + +#define CAPTURE_MIN_NUM_PERIODS 4 +#define CAPTURE_MAX_NUM_PERIODS 4 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 4096 + +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER + +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 + +enum acp_config { + ACP_CONFIG_0 = 0, + ACP_CONFIG_1, + ACP_CONFIG_2, + ACP_CONFIG_3, + ACP_CONFIG_4, + ACP_CONFIG_5, + ACP_CONFIG_6, + ACP_CONFIG_7, + ACP_CONFIG_8, + ACP_CONFIG_9, + ACP_CONFIG_10, + ACP_CONFIG_11, + ACP_CONFIG_12, + ACP_CONFIG_13, + ACP_CONFIG_14, + ACP_CONFIG_15, +}; + +struct pdm_dev_data { + u32 pdm_irq; + void __iomem *acp6x_base; + struct snd_pcm_substream *capture_stream; +}; + +struct pdm_stream_instance { + u16 num_pages; + u16 channels; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp6x_base; +}; + +union acp_pdm_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +static inline u32 acp6x_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP6x_PHY_BASE_ADDRESS); +} + +static inline void acp6x_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS); +} + +int snd_amd_acp_find_config(struct pci_dev *pci); + diff --git a/sound/soc/amd/yc/acp6x_chip_offset_byte.h b/sound/soc/amd/yc/acp6x_chip_offset_byte.h new file mode 100644 index 000000000..f05fb2dfb --- /dev/null +++ b/sound/soc/amd/yc/acp6x_chip_offset_byte.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 6.x Register Documentation + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#ifndef _acp6x_OFFSET_HEADER +#define _acp6x_OFFSET_HEADER + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_CNTL_1 0x1240004 +#define ACP_DMA_CNTL_2 0x1240008 +#define ACP_DMA_CNTL_3 0x124000C +#define ACP_DMA_CNTL_4 0x1240010 +#define ACP_DMA_CNTL_5 0x1240014 +#define ACP_DMA_CNTL_6 0x1240018 +#define ACP_DMA_CNTL_7 0x124001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_DSCR_CNT_1 0x1240044 +#define ACP_DMA_DSCR_CNT_2 0x1240048 +#define ACP_DMA_DSCR_CNT_3 0x124004C +#define ACP_DMA_DSCR_CNT_4 0x1240050 +#define ACP_DMA_DSCR_CNT_5 0x1240054 +#define ACP_DMA_DSCR_CNT_6 0x1240058 +#define ACP_DMA_DSCR_CNT_7 0x124005C +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_PRIO_1 0x1240064 +#define ACP_DMA_PRIO_2 0x1240068 +#define ACP_DMA_PRIO_3 0x124006C +#define ACP_DMA_PRIO_4 0x1240070 +#define ACP_DMA_PRIO_5 0x1240074 +#define ACP_DMA_PRIO_6 0x1240078 +#define ACP_DMA_PRIO_7 0x124007C +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_DSCR_1 0x1240084 +#define ACP_DMA_CUR_DSCR_2 0x1240088 +#define ACP_DMA_CUR_DSCR_3 0x124008C +#define ACP_DMA_CUR_DSCR_4 0x1240090 +#define ACP_DMA_CUR_DSCR_5 0x1240094 +#define ACP_DMA_CUR_DSCR_6 0x1240098 +#define ACP_DMA_CUR_DSCR_7 0x124009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define ACP_DMA_ERR_STS_0 0x12400C0 +#define ACP_DMA_ERR_STS_1 0x12400C4 +#define ACP_DMA_ERR_STS_2 0x12400C8 +#define ACP_DMA_ERR_STS_3 0x12400CC +#define ACP_DMA_ERR_STS_4 0x12400D0 +#define ACP_DMA_ERR_STS_5 0x12400D4 +#define ACP_DMA_ERR_STS_6 0x12400D8 +#define ACP_DMA_ERR_STS_7 0x12400DC +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +/* Registers from ACP_AXI2AXIATU block */ +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define ACPAXI2AXI_ATU_CTRL 0x1240C40 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_9 0x1240C44 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_9 0x1240C48 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_10 0x1240C4C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_10 0x1240C50 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_11 0x1240C54 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_11 0x1240C58 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_12 0x1240C5C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_12 0x1240C60 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_13 0x1240C64 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_13 0x1240C68 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_14 0x1240C6C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_14 0x1240C70 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_15 0x1240C74 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_15 0x1240C78 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_16 0x1240C7C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_16 0x1240C80 + +/* Registers from ACP_CLKRST block */ +#define ACP_SOFT_RESET 0x1241000 +#define ACP_CONTROL 0x1241004 +#define ACP_STATUS 0x1241008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 +#define ACP_ZSC_DSP_CTRL 0x1241014 +#define ACP_ZSC_STS 0x1241018 +#define ACP_PGFSM_CONTROL 0x1241024 +#define ACP_PGFSM_STATUS 0x1241028 +#define ACP_CLKMUX_SEL 0x124102C + +/* Registers from ACP_AON block */ +#define ACP_PME_EN 0x1241400 +#define ACP_DEVICE_STATE 0x1241404 +#define AZ_DEVICE_STATE 0x1241408 +#define ACP_PIN_CONFIG 0x1241440 +#define ACP_PAD_PULLUP_CTRL 0x1241444 +#define ACP_PAD_PULLDOWN_CTRL 0x1241448 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124144C +#define ACP_PAD_SCHMEN_CTRL 0x1241450 +#define ACP_SW_PAD_KEEPER_EN 0x1241454 +#define ACP_SW_WAKE_EN 0x1241458 +#define ACP_I2S_WAKE_EN 0x124145C +#define ACP_SW1_WAKE_EN 0x1241460 + +/* Registers from ACP_P1_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x1241A00 +#define ACP_EXTERNAL_INTR_CNTL 0x1241A04 +#define ACP_EXTERNAL_INTR_CNTL1 0x1241A08 +#define ACP_EXTERNAL_INTR_STAT 0x1241A0C +#define ACP_EXTERNAL_INTR_STAT1 0x1241A10 +#define ACP_ERROR_STATUS 0x1241A4C +#define ACP_P1_SW_I2S_ERROR_REASON 0x1241A50 +#define ACP_P1_SW_POS_TRACK_I2S_TX_CTRL 0x1241A6C +#define ACP_P1_SW_I2S_TX_DMA_POS 0x1241A70 +#define ACP_P1_SW_POS_TRACK_I2S_RX_CTRL 0x1241A74 +#define ACP_P1_SW_I2S_RX_DMA_POS 0x1241A78 +#define ACP_P1_DMIC_I2S_GPIO_INTR_CTRL 0x1241A7C +#define ACP_P1_DMIC_I2S_GPIO_INTR_STATUS 0x1241A80 +#define ACP_SCRATCH_REG_BASE_ADDR 0x1241A84 +#define ACP_P1_SW_POS_TRACK_BT_TX_CTRL 0x1241A88 +#define ACP_P1_SW_BT_TX_DMA_POS 0x1241A8C +#define ACP_P1_SW_POS_TRACK_HS_TX_CTRL 0x1241A90 +#define ACP_P1_SW_HS_TX_DMA_POS 0x1241A94 +#define ACP_P1_SW_POS_TRACK_BT_RX_CTRL 0x1241A98 +#define ACP_P1_SW_BT_RX_DMA_POS 0x1241A9C +#define ACP_P1_SW_POS_TRACK_HS_RX_CTRL 0x1241AA0 +#define ACP_P1_SW_HS_RX_DMA_POS 0x1241AA4 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM1_MSTRCLKGEN 0x1242418 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C +#define ACP_I2STDM_REFCLKGEN 0x1242420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 + +/* Registers from ACP_WOV block */ +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 +#define ACP_WOV_WAKE 0x1242C54 +#define ACP_WOV_BUFFER_STATUS 0x1242C58 +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 +#define ACP_PDM_CLKDIV 0x1242C6C + +/* Registers from ACP_P1_AUDIO_BUFFERS block */ +#define ACP_P1_I2S_RX_RINGBUFADDR 0x1243A00 +#define ACP_P1_I2S_RX_RINGBUFSIZE 0x1243A04 +#define ACP_P1_I2S_RX_LINKPOSITIONCNTR 0x1243A08 +#define ACP_P1_I2S_RX_FIFOADDR 0x1243A0C +#define ACP_P1_I2S_RX_FIFOSIZE 0x1243A10 +#define ACP_P1_I2S_RX_DMA_SIZE 0x1243A14 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1243A18 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x1243A1C +#define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x1243A20 +#define ACP_P1_I2S_TX_RINGBUFADDR 0x1243A24 +#define ACP_P1_I2S_TX_RINGBUFSIZE 0x1243A28 +#define ACP_P1_I2S_TX_LINKPOSITIONCNTR 0x1243A2C +#define ACP_P1_I2S_TX_FIFOADDR 0x1243A30 +#define ACP_P1_I2S_TX_FIFOSIZE 0x1243A34 +#define ACP_P1_I2S_TX_DMA_SIZE 0x1243A38 +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x1243A3C +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1243A40 +#define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x1243A44 +#define ACP_P1_BT_RX_RINGBUFADDR 0x1243A48 +#define ACP_P1_BT_RX_RINGBUFSIZE 0x1243A4C +#define ACP_P1_BT_RX_LINKPOSITIONCNTR 0x1243A50 +#define ACP_P1_BT_RX_FIFOADDR 0x1243A54 +#define ACP_P1_BT_RX_FIFOSIZE 0x1243A58 +#define ACP_P1_BT_RX_DMA_SIZE 0x1243A5C +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1243A60 +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x1243A64 +#define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x1243A68 +#define ACP_P1_BT_TX_RINGBUFADDR 0x1243A6C +#define ACP_P1_BT_TX_RINGBUFSIZE 0x1243A70 +#define ACP_P1_BT_TX_LINKPOSITIONCNTR 0x1243A74 +#define ACP_P1_BT_TX_FIFOADDR 0x1243A78 +#define ACP_P1_BT_TX_FIFOSIZE 0x1243A7C +#define ACP_P1_BT_TX_DMA_SIZE 0x1243A80 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1243A84 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x1243A88 +#define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x1243A8C +#define ACP_P1_HS_RX_RINGBUFADDR 0x1243A90 +#define ACP_P1_HS_RX_RINGBUFSIZE 0x1243A94 +#define ACP_P1_HS_RX_LINKPOSITIONCNTR 0x1243A98 +#define ACP_P1_HS_RX_FIFOADDR 0x1243A9C +#define ACP_P1_HS_RX_FIFOSIZE 0x1243AA0 +#define ACP_P1_HS_RX_DMA_SIZE 0x1243AA4 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x1243AA8 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x1243AAC +#define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x1243AB0 +#define ACP_P1_HS_TX_RINGBUFADDR 0x1243AB4 +#define ACP_P1_HS_TX_RINGBUFSIZE 0x1243AB8 +#define ACP_P1_HS_TX_LINKPOSITIONCNTR 0x1243ABC +#define ACP_P1_HS_TX_FIFOADDR 0x1243AC0 +#define ACP_P1_HS_TX_FIFOSIZE 0x1243AC4 +#define ACP_P1_HS_TX_DMA_SIZE 0x1243AC8 +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x1243ACC +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x1243AD0 +#define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x1243AD4 + +/* Registers from ACP_SCRATCH block */ +#define ACP_SCRATCH_REG_0 0x1250000 +#define ACP_SCRATCH_REG_1 0x1250004 +#define ACP_SCRATCH_REG_2 0x1250008 +#define ACP_SCRATCH_REG_3 0x125000C +#define ACP_SCRATCH_REG_4 0x1250010 +#define ACP_SCRATCH_REG_5 0x1250014 +#define ACP_SCRATCH_REG_6 0x1250018 +#define ACP_SCRATCH_REG_7 0x125001C +#define ACP_SCRATCH_REG_8 0x1250020 +#define ACP_SCRATCH_REG_9 0x1250024 +#define ACP_SCRATCH_REG_10 0x1250028 +#define ACP_SCRATCH_REG_11 0x125002C +#define ACP_SCRATCH_REG_12 0x1250030 +#define ACP_SCRATCH_REG_13 0x1250034 +#define ACP_SCRATCH_REG_14 0x1250038 +#define ACP_SCRATCH_REG_15 0x125003C +#define ACP_SCRATCH_REG_16 0x1250040 +#define ACP_SCRATCH_REG_17 0x1250044 +#define ACP_SCRATCH_REG_18 0x1250048 +#define ACP_SCRATCH_REG_19 0x125004C +#define ACP_SCRATCH_REG_20 0x1250050 +#define ACP_SCRATCH_REG_21 0x1250054 +#define ACP_SCRATCH_REG_22 0x1250058 +#define ACP_SCRATCH_REG_23 0x125005C +#define ACP_SCRATCH_REG_24 0x1250060 +#define ACP_SCRATCH_REG_25 0x1250064 +#define ACP_SCRATCH_REG_26 0x1250068 +#define ACP_SCRATCH_REG_27 0x125006C +#define ACP_SCRATCH_REG_28 0x1250070 +#define ACP_SCRATCH_REG_29 0x1250074 +#define ACP_SCRATCH_REG_30 0x1250078 +#define ACP_SCRATCH_REG_31 0x125007C +#define ACP_SCRATCH_REG_32 0x1250080 +#define ACP_SCRATCH_REG_33 0x1250084 +#define ACP_SCRATCH_REG_34 0x1250088 +#define ACP_SCRATCH_REG_35 0x125008C +#define ACP_SCRATCH_REG_36 0x1250090 +#define ACP_SCRATCH_REG_37 0x1250094 +#define ACP_SCRATCH_REG_38 0x1250098 +#define ACP_SCRATCH_REG_39 0x125009C +#define ACP_SCRATCH_REG_40 0x12500A0 +#define ACP_SCRATCH_REG_41 0x12500A4 +#define ACP_SCRATCH_REG_42 0x12500A8 +#define ACP_SCRATCH_REG_43 0x12500AC +#define ACP_SCRATCH_REG_44 0x12500B0 +#define ACP_SCRATCH_REG_45 0x12500B4 +#define ACP_SCRATCH_REG_46 0x12500B8 +#define ACP_SCRATCH_REG_47 0x12500BC +#define ACP_SCRATCH_REG_48 0x12500C0 +#define ACP_SCRATCH_REG_49 0x12500C4 +#define ACP_SCRATCH_REG_50 0x12500C8 +#define ACP_SCRATCH_REG_51 0x12500CC +#define ACP_SCRATCH_REG_52 0x12500D0 +#define ACP_SCRATCH_REG_53 0x12500D4 +#define ACP_SCRATCH_REG_54 0x12500D8 +#define ACP_SCRATCH_REG_55 0x12500DC +#define ACP_SCRATCH_REG_56 0x12500E0 +#define ACP_SCRATCH_REG_57 0x12500E4 +#define ACP_SCRATCH_REG_58 0x12500E8 +#define ACP_SCRATCH_REG_59 0x12500EC +#define ACP_SCRATCH_REG_60 0x12500F0 +#define ACP_SCRATCH_REG_61 0x12500F4 +#define ACP_SCRATCH_REG_62 0x12500F8 +#define ACP_SCRATCH_REG_63 0x12500FC +#define ACP_SCRATCH_REG_64 0x1250100 +#define ACP_SCRATCH_REG_65 0x1250104 +#define ACP_SCRATCH_REG_66 0x1250108 +#define ACP_SCRATCH_REG_67 0x125010C +#define ACP_SCRATCH_REG_68 0x1250110 +#define ACP_SCRATCH_REG_69 0x1250114 +#define ACP_SCRATCH_REG_70 0x1250118 +#define ACP_SCRATCH_REG_71 0x125011C +#define ACP_SCRATCH_REG_72 0x1250120 +#define ACP_SCRATCH_REG_73 0x1250124 +#define ACP_SCRATCH_REG_74 0x1250128 +#define ACP_SCRATCH_REG_75 0x125012C +#define ACP_SCRATCH_REG_76 0x1250130 +#define ACP_SCRATCH_REG_77 0x1250134 +#define ACP_SCRATCH_REG_78 0x1250138 +#define ACP_SCRATCH_REG_79 0x125013C +#define ACP_SCRATCH_REG_80 0x1250140 +#define ACP_SCRATCH_REG_81 0x1250144 +#define ACP_SCRATCH_REG_82 0x1250148 +#define ACP_SCRATCH_REG_83 0x125014C +#define ACP_SCRATCH_REG_84 0x1250150 +#define ACP_SCRATCH_REG_85 0x1250154 +#define ACP_SCRATCH_REG_86 0x1250158 +#define ACP_SCRATCH_REG_87 0x125015C +#define ACP_SCRATCH_REG_88 0x1250160 +#define ACP_SCRATCH_REG_89 0x1250164 +#define ACP_SCRATCH_REG_90 0x1250168 +#define ACP_SCRATCH_REG_91 0x125016C +#define ACP_SCRATCH_REG_92 0x1250170 +#define ACP_SCRATCH_REG_93 0x1250174 +#define ACP_SCRATCH_REG_94 0x1250178 +#define ACP_SCRATCH_REG_95 0x125017C +#define ACP_SCRATCH_REG_96 0x1250180 +#define ACP_SCRATCH_REG_97 0x1250184 +#define ACP_SCRATCH_REG_98 0x1250188 +#define ACP_SCRATCH_REG_99 0x125018C +#define ACP_SCRATCH_REG_100 0x1250190 +#define ACP_SCRATCH_REG_101 0x1250194 +#define ACP_SCRATCH_REG_102 0x1250198 +#define ACP_SCRATCH_REG_103 0x125019C +#define ACP_SCRATCH_REG_104 0x12501A0 +#define ACP_SCRATCH_REG_105 0x12501A4 +#define ACP_SCRATCH_REG_106 0x12501A8 +#define ACP_SCRATCH_REG_107 0x12501AC +#define ACP_SCRATCH_REG_108 0x12501B0 +#define ACP_SCRATCH_REG_109 0x12501B4 +#define ACP_SCRATCH_REG_110 0x12501B8 +#define ACP_SCRATCH_REG_111 0x12501BC +#define ACP_SCRATCH_REG_112 0x12501C0 +#define ACP_SCRATCH_REG_113 0x12501C4 +#define ACP_SCRATCH_REG_114 0x12501C8 +#define ACP_SCRATCH_REG_115 0x12501CC +#define ACP_SCRATCH_REG_116 0x12501D0 +#define ACP_SCRATCH_REG_117 0x12501D4 +#define ACP_SCRATCH_REG_118 0x12501D8 +#define ACP_SCRATCH_REG_119 0x12501DC +#define ACP_SCRATCH_REG_120 0x12501E0 +#define ACP_SCRATCH_REG_121 0x12501E4 +#define ACP_SCRATCH_REG_122 0x12501E8 +#define ACP_SCRATCH_REG_123 0x12501EC +#define ACP_SCRATCH_REG_124 0x12501F0 +#define ACP_SCRATCH_REG_125 0x12501F4 +#define ACP_SCRATCH_REG_126 0x12501F8 +#define ACP_SCRATCH_REG_127 0x12501FC +#define ACP_SCRATCH_REG_128 0x1250200 +#endif diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c new file mode 100644 index 000000000..671443204 --- /dev/null +++ b/sound/soc/amd/yc/pci-acp6x.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AMD Yellow Carp ACP PCI Driver + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acp6x.h" + +struct acp6x_dev_data { + void __iomem *acp6x_base; + struct resource *res; + bool acp6x_audio_mode; + struct platform_device *pdev[ACP6x_DEVS]; +}; + +static int acp6x_power_on(void __iomem *acp_base) +{ + u32 val; + int timeout; + + val = acp6x_readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return val; + + if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) + acp6x_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = acp6x_readl(acp_base + ACP_PGFSM_STATUS); + if (!val) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int acp6x_reset(void __iomem *acp_base) +{ + u32 val; + int timeout; + + acp6x_writel(1, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp6x_readl(acp_base + ACP_SOFT_RESET); + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) + break; + cpu_relax(); + } + acp6x_writel(0, acp_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp6x_readl(acp_base + ACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void acp6x_enable_interrupts(void __iomem *acp_base) +{ + acp6x_writel(0x01, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static void acp6x_disable_interrupts(void __iomem *acp_base) +{ + acp6x_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + + ACP_EXTERNAL_INTR_STAT); + acp6x_writel(0x00, acp_base + ACP_EXTERNAL_INTR_CNTL); + acp6x_writel(0x00, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp6x_init(void __iomem *acp_base) +{ + int ret; + + /* power on */ + ret = acp6x_power_on(acp_base); + if (ret) { + pr_err("ACP power on failed\n"); + return ret; + } + acp6x_writel(0x01, acp_base + ACP_CONTROL); + /* Reset */ + ret = acp6x_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + acp6x_writel(0x03, acp_base + ACP_CLKMUX_SEL); + acp6x_enable_interrupts(acp_base); + return 0; +} + +static int acp6x_deinit(void __iomem *acp_base) +{ + int ret; + + acp6x_disable_interrupts(acp_base); + /* Reset */ + ret = acp6x_reset(acp_base); + if (ret) { + pr_err("ACP reset failed\n"); + return ret; + } + acp6x_writel(0x00, acp_base + ACP_CLKMUX_SEL); + acp6x_writel(0x00, acp_base + ACP_CONTROL); + return 0; +} + +static irqreturn_t acp6x_irq_handler(int irq, void *dev_id) +{ + struct acp6x_dev_data *adata; + struct pdm_dev_data *yc_pdm_data; + u32 val; + + adata = dev_id; + if (!adata) + return IRQ_NONE; + + val = acp6x_readl(adata->acp6x_base + ACP_EXTERNAL_INTR_STAT); + if (val & BIT(PDM_DMA_STAT)) { + yc_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev); + acp6x_writel(BIT(PDM_DMA_STAT), adata->acp6x_base + ACP_EXTERNAL_INTR_STAT); + if (yc_pdm_data->capture_stream) + snd_pcm_period_elapsed(yc_pdm_data->capture_stream); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static int snd_acp6x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp6x_dev_data *adata; + struct platform_device_info pdevinfo[ACP6x_DEVS]; + int index = 0; + int val = 0x00; + u32 addr; + unsigned int irqflags, flag; + int ret; + + irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + + /* Yellow Carp device check */ + switch (pci->revision) { + case 0x60: + case 0x6f: + case 0x62: /* RPL */ + break; + default: + dev_dbg(&pci->dev, "acp6x pci device not found\n"); + return -ENODEV; + } + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP3x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp6x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + + addr = pci_resource_start(pci, 0); + adata->acp6x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp6x_base) { + ret = -ENOMEM; + goto release_regions; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = acp6x_init(adata->acp6x_base); + if (ret) + goto release_regions; + val = acp6x_readl(adata->acp6x_base + ACP_PIN_CONFIG); + switch (val) { + case ACP_CONFIG_0: + case ACP_CONFIG_1: + case ACP_CONFIG_2: + case ACP_CONFIG_3: + case ACP_CONFIG_9: + case ACP_CONFIG_15: + dev_info(&pci->dev, "Audio Mode %d\n", val); + break; + case ACP_CONFIG_10: + case ACP_CONFIG_11: + case ACP_CONFIG_12: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + /* PIN 10 to 14 is reserve for RPL */ + if (pci->revision == 0x62) { + dev_info(&pci->dev, "RPL Audio Mode %d\n", val); + break; + } + fallthrough; + default: + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource), + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res->name = "acp_iomem"; + adata->res->flags = IORESOURCE_MEM; + adata->res->start = addr; + adata->res->end = addr + (ACP6x_REG_END - ACP6x_REG_START); + + adata->acp6x_audio_mode = ACP6x_PDM_MODE; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo[0].name = "acp_yc_pdm_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 1; + pdevinfo[0].res = adata->res; + + pdevinfo[1].name = "dmic-codec"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + + pdevinfo[2].name = "acp_yc_mach"; + pdevinfo[2].id = 0; + pdevinfo[2].parent = &pci->dev; + + for (index = 0; index < ACP6x_DEVS; index++) { + adata->pdev[index] = + platform_device_register_full(&pdevinfo[index]); + if (IS_ERR(adata->pdev[index])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[index].name); + ret = PTR_ERR(adata->pdev[index]); + goto unregister_devs; + } + } + break; + } + ret = devm_request_irq(&pci->dev, pci->irq, acp6x_irq_handler, + irqflags, "ACP_PCI_IRQ", adata); + if (ret) { + dev_err(&pci->dev, "ACP PCI IRQ request failed\n"); + goto unregister_devs; + } + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + + return 0; +unregister_devs: + for (--index; index >= 0; index--) + platform_device_unregister(adata->pdev[index]); +de_init: + if (acp6x_deinit(adata->acp6x_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int snd_acp6x_suspend(struct device *dev) +{ + struct acp6x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp6x_deinit(adata->acp6x_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + return ret; +} + +static int snd_acp6x_resume(struct device *dev) +{ + struct acp6x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp6x_init(adata->acp6x_base); + if (ret) + dev_err(dev, "ACP init failed\n"); + return ret; +} + +static const struct dev_pm_ops acp6x_pm = { + RUNTIME_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume) +}; + +static void snd_acp6x_remove(struct pci_dev *pci) +{ + struct acp6x_dev_data *adata; + int ret, index; + + adata = pci_get_drvdata(pci); + if (adata->acp6x_audio_mode == ACP6x_PDM_MODE) { + for (index = 0; index < ACP6x_DEVS; index++) + platform_device_unregister(adata->pdev[index]); + } + ret = acp6x_deinit(adata->acp6x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp6x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp6x_ids); + +static struct pci_driver yc_acp6x_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp6x_ids, + .probe = snd_acp6x_probe, + .remove = snd_acp6x_remove, + .driver = { + .pm = pm_ptr(&acp6x_pm), + } +}; + +module_pci_driver(yc_acp6x_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP Yellow Carp PCI driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.3.1