summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2022-08-01 15:26:40 +0200
committerTakashi Iwai <tiwai@suse.de>2022-08-01 15:26:40 +0200
commita3b5d4715fd5a839857f8b7be78dff258a8d5a47 (patch)
treeb70d6f050f4831eaba82a60fb443659dc9dfca1c /sound/soc
parent9769e44d41a1359b9000ff8458f0f2f66080ebf4 (diff)
parent40d060b8158e26438398bf1132925f666e3b6480 (diff)
downloadlinux-stable-a3b5d4715fd5a839857f8b7be78dff258a8d5a47.tar.gz
linux-stable-a3b5d4715fd5a839857f8b7be78dff258a8d5a47.tar.bz2
linux-stable-a3b5d4715fd5a839857f8b7be78dff258a8d5a47.zip
Merge tag 'asoc-v5.20-2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: More updates for v5.20 More updates that came in since the last pull request I sent, a series of driver specific changes: - Support for AMD RPL, some Intel platforms and Mediatek MT8186.
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/amd/Kconfig10
-rw-r--r--sound/soc/amd/Makefile1
-rw-r--r--sound/soc/amd/acp/acp-pci.c33
-rw-r--r--sound/soc/amd/acp/acp-platform.c18
-rw-r--r--sound/soc/amd/rpl/Makefile5
-rw-r--r--sound/soc/amd/rpl/rpl-pci-acp6x.c227
-rw-r--r--sound/soc/amd/rpl/rpl_acp6x.h36
-rw-r--r--sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h30
-rw-r--r--sound/soc/amd/vangogh/acp5x-mach.c3
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c32
-rw-r--r--sound/soc/amd/yc/pci-acp6x.c2
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c9
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c19
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c22
-rw-r--r--sound/soc/codecs/cs35l41.c30
-rw-r--r--sound/soc/codecs/nau8821.c40
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c5
-rw-r--r--sound/soc/fsl/fsl_asrc.c6
-rw-r--r--sound/soc/fsl/fsl_easrc.c9
-rw-r--r--sound/soc/fsl/fsl_easrc.h2
-rw-r--r--sound/soc/fsl/fsl_sai.c2
-rw-r--r--sound/soc/fsl/imx-card.c8
-rw-r--r--sound/soc/generic/audio-graph-card.c4
-rw-r--r--sound/soc/generic/audio-graph-card2.c4
-rw-r--r--sound/soc/intel/avs/path.c54
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c1
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c1
-rw-r--r--sound/soc/intel/boards/bdw_rt286.c1
-rw-r--r--sound/soc/intel/boards/hsw_rt5640.c1
-rw-r--r--sound/soc/intel/boards/sof_es8336.c160
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c10
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c26
-rw-r--r--sound/soc/intel/boards/sof_sdw.c19
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711_sdca.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c54
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c17
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c1
-rw-r--r--sound/soc/mediatek/Kconfig45
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/common/Makefile2
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.c196
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.h36
-rw-r--r--sound/soc/mediatek/common/mtk-soc-card.h17
-rw-r--r--sound/soc/mediatek/mt8186/Makefile22
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-clk.c3
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-clk.h2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-common.h195
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-control.c255
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-pcm.c3000
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-adda.c8
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-i2s.c63
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-pcm.c5
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-tdm.c55
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-common.c57
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-common.h17
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c1002
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c978
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c233
-rw-r--r--sound/soc/qcom/qdsp6/q6adm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/sof/intel/atom.c16
-rw-r--r--sound/soc/sof/intel/hda-probes.c16
-rw-r--r--sound/soc/sof/intel/hda-stream.c15
-rw-r--r--sound/soc/sof/intel/hda.c86
-rw-r--r--sound/soc/sof/intel/mtl.c13
-rw-r--r--sound/soc/sof/ipc3-loader.c6
-rw-r--r--sound/soc/sof/ipc3-pcm.c3
-rw-r--r--sound/soc/sof/ipc4-pcm.c4
-rw-r--r--sound/soc/sof/ipc4-topology.c156
-rw-r--r--sound/soc/sof/ipc4-topology.h27
-rw-r--r--sound/soc/sof/mediatek/mt8195/mt8195-loader.c13
-rw-r--r--sound/soc/sof/sof-client-probes.c8
-rw-r--r--sound/soc/sof/sof-client-probes.h8
-rw-r--r--sound/soc/sof/sof-priv.h1
76 files changed, 6875 insertions, 605 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index d4528962ac34..453181ef6c94 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -9,12 +9,12 @@ endif
ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),)
# snd-soc-test-objs := soc-topology-test.o
-obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) := soc-topology-test.o
+obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) += soc-topology-test.o
endif
ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),)
# snd-soc-test-objs := soc-utils-test.o
-obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) := soc-utils-test.o
+obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o
endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 9c2fef2ce89f..08f5289dac54 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -117,3 +117,13 @@ config SND_AMD_ACP_CONFIG
driver modules to use
source "sound/soc/amd/acp/Kconfig"
+
+config SND_SOC_AMD_RPL_ACP6x
+ tristate "AMD Audio Coprocessor-v6.2 RPL support"
+ depends on X86 && PCI
+ help
+ This option enables Audio Coprocessor i.e ACP v6.2 support on
+ AMD RPL platform. By enabling this flag build will be
+ triggered for ACP PCI driver.
+ Say m if you have such a device.
+ If unsure select "N".
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index 8823f6f28611..0592e7c5c407 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/
obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o
+obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += rpl/
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index c03bcd31fc95..2c8e960cc9a6 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -29,7 +29,7 @@
static struct platform_device *dmic_dev;
static struct platform_device *pdev;
-static const struct resource acp3x_res[] = {
+static const struct resource acp_res[] = {
{
.start = 0,
.end = ACP3x_REG_END - ACP3x_REG_START,
@@ -70,42 +70,49 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
ret = pci_request_regions(pci, "AMD ACP3x audio");
if (ret < 0) {
dev_err(&pci->dev, "pci_request_regions failed\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto disable_pci;
}
pci_set_master(pci);
+ res_acp = acp_res;
+ num_res = ARRAY_SIZE(acp_res);
+
switch (pci->revision) {
case 0x01:
- res_acp = acp3x_res;
- num_res = ARRAY_SIZE(acp3x_res);
chip->name = "acp_asoc_renoir";
chip->acp_rev = ACP3X_DEV;
break;
case 0x6f:
- res_acp = acp3x_res;
- num_res = ARRAY_SIZE(acp3x_res);
chip->name = "acp_asoc_rembrandt";
chip->acp_rev = ACP6X_DEV;
break;
default:
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
- return -EINVAL;
+ ret = -EINVAL;
+ goto release_regions;
}
dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(dmic_dev)) {
dev_err(dev, "failed to create DMIC device\n");
- return PTR_ERR(dmic_dev);
+ ret = PTR_ERR(dmic_dev);
+ goto release_regions;
}
addr = pci_resource_start(pci, 0);
chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
+ if (!chip->base) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
if (!res) {
platform_device_unregister(dmic_dev);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto release_regions;
}
for (i = 0; i < num_res; i++, res_acp++) {
@@ -134,9 +141,17 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
platform_device_unregister(dmic_dev);
ret = PTR_ERR(pdev);
+ goto release_regions;
}
return ret;
+
+release_regions:
+ pci_release_regions(pci);
+disable_pci:
+ pci_disable_device(pci);
+
+ return ret;
};
static void acp_pci_remove(struct pci_dev *pci)
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index 327e17736dbd..f561d39b33e2 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -94,19 +94,19 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
struct acp_resource *rsrc = adata->rsrc;
struct acp_stream *stream;
u16 i2s_flag = 0;
- u32 val, val1, i;
+ u32 ext_intr_stat, ext_intr_stat1, i;
if (!adata)
return IRQ_NONE;
if (adata->rsrc->no_of_ctrls == 2)
- val1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
+ ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
- val = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
+ ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
for (i = 0; i < ACP_MAX_STREAM; i++) {
stream = adata->stream[i];
- if (stream && (val & stream->irq_bit)) {
+ if (stream && (ext_intr_stat & stream->irq_bit)) {
writel(stream->irq_bit,
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
snd_pcm_period_elapsed(stream->substream);
@@ -114,7 +114,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
break;
}
if (adata->rsrc->no_of_ctrls == 2) {
- if (stream && (val1 & stream->irq_bit)) {
+ if (stream && (ext_intr_stat1 & stream->irq_bit)) {
writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
(rsrc->irqp_used - 1)));
snd_pcm_period_elapsed(stream->substream);
@@ -258,13 +258,6 @@ static int acp_dma_new(struct snd_soc_component *component,
return 0;
}
-static int acp_dma_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return snd_pcm_lib_default_mmap(substream, vma);
-}
-
static int acp_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -288,7 +281,6 @@ static const struct snd_soc_component_driver acp_pcm_component = {
.close = acp_dma_close,
.hw_params = acp_dma_hw_params,
.pointer = acp_dma_pointer,
- .mmap = acp_dma_mmap,
.pcm_construct = acp_dma_new,
.legacy_dai_naming = 1,
};
diff --git a/sound/soc/amd/rpl/Makefile b/sound/soc/amd/rpl/Makefile
new file mode 100644
index 000000000000..11a33a05e94b
--- /dev/null
+++ b/sound/soc/amd/rpl/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+# RPL platform Support
+snd-rpl-pci-acp6x-objs := rpl-pci-acp6x.o
+
+obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += snd-rpl-pci-acp6x.o
diff --git a/sound/soc/amd/rpl/rpl-pci-acp6x.c b/sound/soc/amd/rpl/rpl-pci-acp6x.c
new file mode 100644
index 000000000000..a8e548ed991b
--- /dev/null
+++ b/sound/soc/amd/rpl/rpl-pci-acp6x.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AMD RPL ACP PCI Driver
+ *
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "rpl_acp6x.h"
+
+struct rpl_dev_data {
+ void __iomem *acp6x_base;
+};
+
+static int rpl_power_on(void __iomem *acp_base)
+{
+ u32 val;
+ int timeout;
+
+ val = rpl_acp_readl(acp_base + ACP_PGFSM_STATUS);
+
+ if (!val)
+ return val;
+
+ if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
+ rpl_acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = rpl_acp_readl(acp_base + ACP_PGFSM_STATUS);
+ if (!val)
+ return 0;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+}
+
+static int rpl_reset(void __iomem *acp_base)
+{
+ u32 val;
+ int timeout;
+
+ rpl_acp_writel(1, acp_base + ACP_SOFT_RESET);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = rpl_acp_readl(acp_base + ACP_SOFT_RESET);
+ if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
+ break;
+ cpu_relax();
+ }
+ rpl_acp_writel(0, acp_base + ACP_SOFT_RESET);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = rpl_acp_readl(acp_base + ACP_SOFT_RESET);
+ if (!val)
+ return 0;
+ cpu_relax();
+ }
+ return -ETIMEDOUT;
+}
+
+static int rpl_init(void __iomem *acp_base)
+{
+ int ret;
+
+ /* power on */
+ ret = rpl_power_on(acp_base);
+ if (ret) {
+ pr_err("ACP power on failed\n");
+ return ret;
+ }
+ rpl_acp_writel(0x01, acp_base + ACP_CONTROL);
+ /* Reset */
+ ret = rpl_reset(acp_base);
+ if (ret) {
+ pr_err("ACP reset failed\n");
+ return ret;
+ }
+ rpl_acp_writel(0x03, acp_base + ACP_CLKMUX_SEL);
+ return 0;
+}
+
+static int rpl_deinit(void __iomem *acp_base)
+{
+ int ret;
+
+ /* Reset */
+ ret = rpl_reset(acp_base);
+ if (ret) {
+ pr_err("ACP reset failed\n");
+ return ret;
+ }
+ rpl_acp_writel(0x00, acp_base + ACP_CLKMUX_SEL);
+ rpl_acp_writel(0x00, acp_base + ACP_CONTROL);
+ return 0;
+}
+
+static int snd_rpl_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ struct rpl_dev_data *adata;
+ u32 addr;
+ int ret;
+
+ /* RPL device check */
+ switch (pci->revision) {
+ case 0x62:
+ 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 ACP6x audio");
+ if (ret < 0) {
+ dev_err(&pci->dev, "pci_request_regions failed\n");
+ goto disable_pci;
+ }
+
+ adata = devm_kzalloc(&pci->dev, sizeof(struct rpl_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 = rpl_init(adata->acp6x_base);
+ 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_rpl_suspend(struct device *dev)
+{
+ struct rpl_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ ret = rpl_deinit(adata->acp6x_base);
+ if (ret)
+ dev_err(dev, "ACP de-init failed\n");
+ return ret;
+}
+
+static int __maybe_unused snd_rpl_resume(struct device *dev)
+{
+ struct rpl_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ ret = rpl_init(adata->acp6x_base);
+ if (ret)
+ dev_err(dev, "ACP init failed\n");
+ return ret;
+}
+
+static const struct dev_pm_ops rpl_pm = {
+ SET_RUNTIME_PM_OPS(snd_rpl_suspend, snd_rpl_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(snd_rpl_suspend, snd_rpl_resume)
+};
+
+static void snd_rpl_remove(struct pci_dev *pci)
+{
+ struct rpl_dev_data *adata;
+ int ret;
+
+ adata = pci_get_drvdata(pci);
+ ret = rpl_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_rpl_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_rpl_ids);
+
+static struct pci_driver rpl_acp6x_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_rpl_ids,
+ .probe = snd_rpl_probe,
+ .remove = snd_rpl_remove,
+ .driver = {
+ .pm = &rpl_pm,
+ }
+};
+
+module_pci_driver(rpl_acp6x_driver);
+
+MODULE_DESCRIPTION("AMD ACP RPL PCI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/rpl/rpl_acp6x.h b/sound/soc/amd/rpl/rpl_acp6x.h
new file mode 100644
index 000000000000..f5816a33632e
--- /dev/null
+++ b/sound/soc/amd/rpl/rpl_acp6x.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ACP Driver
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include "rpl_acp6x_chip_offset_byte.h"
+
+#define ACP_DEVICE_ID 0x15E2
+#define ACP6x_PHY_BASE_ADDRESS 0x1240000
+
+#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 DELAY_US 5
+#define ACP_COUNTER 20000
+
+/* time in ms for runtime suspend delay */
+#define ACP_SUSPEND_DELAY_MS 2000
+
+static inline u32 rpl_acp_readl(void __iomem *base_addr)
+{
+ return readl(base_addr - ACP6x_PHY_BASE_ADDRESS);
+}
+
+static inline void rpl_acp_writel(u32 val, void __iomem *base_addr)
+{
+ writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS);
+}
diff --git a/sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h b/sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h
new file mode 100644
index 000000000000..456498f5396d
--- /dev/null
+++ b/sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ACP 6.2 Register Documentation
+ *
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _rpl_acp6x_OFFSET_HEADER
+#define _rpl_acp6x_OFFSET_HEADER
+
+/* 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_PGFSM_CONTROL 0x124101C
+#define ACP_PGFSM_STATUS 0x1241020
+#define ACP_CLKMUX_SEL 0x1241024
+
+/* 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
+
+#endif
diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c
index 727de46860b1..af3737ef9707 100644
--- a/sound/soc/amd/vangogh/acp5x-mach.c
+++ b/sound/soc/amd/vangogh/acp5x-mach.c
@@ -178,8 +178,7 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream,
ret = 0;
for (i = 0; i < num_codecs; i++) {
codec_dai = asoc_rtd_to_codec(rtd, i);
- if ((strcmp(codec_dai->name, "spi-VLV1776:00") == 0) ||
- (strcmp(codec_dai->name, "spi-VLV1776:01") == 0)) {
+ if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) {
switch (params_rate(params)) {
case 48000:
bclk_val = 1536000;
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index f06e6c1a7799..ecfe7a790790 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -105,28 +105,14 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21AW"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21CM"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21AX"),
- }
- },
- {
- .driver_data = &acp6x_card,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21BN"),
- }
- },
- {
- .driver_data = &acp6x_card,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21BQ"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21CN"),
}
},
{
@@ -157,20 +143,6 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
}
},
- {
- .driver_data = &acp6x_card,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21D8"),
- }
- },
- {
- .driver_data = &acp6x_card,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21D9"),
- }
- },
{}
};
diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c
index 20f7a99783f2..77c5fa1f7af1 100644
--- a/sound/soc/amd/yc/pci-acp6x.c
+++ b/sound/soc/amd/yc/pci-acp6x.c
@@ -159,7 +159,7 @@ static int snd_acp6x_probe(struct pci_dev *pci,
case 0x6f:
break;
default:
- dev_err(&pci->dev, "acp6x pci device not found\n");
+ dev_dbg(&pci->dev, "acp6x pci device not found\n");
return -ENODEV;
}
if (pci_enable_device(pci)) {
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 8aae0beadcfe..e868b7e028d6 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -762,7 +762,6 @@ static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
return 0;
}
-#ifdef CONFIG_PM
static int atmel_ssc_suspend(struct snd_soc_component *component)
{
struct atmel_ssc_info *ssc_p;
@@ -821,10 +820,6 @@ static int atmel_ssc_resume(struct snd_soc_component *component)
return 0;
}
-#else /* CONFIG_PM */
-# define atmel_ssc_suspend NULL
-# define atmel_ssc_resume NULL
-#endif /* CONFIG_PM */
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -859,8 +854,8 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
static const struct snd_soc_component_driver atmel_ssc_component = {
.name = "atmel-ssc",
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
+ .suspend = pm_ptr(atmel_ssc_suspend),
+ .resume = pm_ptr(atmel_ssc_resume),
.legacy_dai_naming = 1,
};
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index 0d37b78b94a0..ec0705cc40fa 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -221,11 +221,11 @@ struct mchp_spdifrx_user_data {
};
struct mchp_spdifrx_mixer_control {
- struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
- struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
- bool ulock;
- bool badf;
- bool signal;
+ struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
+ struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
+ bool ulock;
+ bool badf;
+ bool signal;
};
struct mchp_spdifrx_dev {
@@ -288,15 +288,17 @@ static void mchp_spdifrx_isr_blockend_en(struct mchp_spdifrx_dev *dev)
spin_unlock_irqrestore(&dev->blockend_lock, flags);
}
-/* called from atomic context only */
+/* called from atomic/non-atomic context */
static void mchp_spdifrx_isr_blockend_dis(struct mchp_spdifrx_dev *dev)
{
- spin_lock(&dev->blockend_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->blockend_lock, flags);
dev->blockend_refcount--;
/* don't enable BLOCKEND interrupt if it's already enabled */
if (dev->blockend_refcount == 0)
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
- spin_unlock(&dev->blockend_lock);
+ spin_unlock_irqrestore(&dev->blockend_lock, flags);
}
static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
@@ -575,6 +577,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
if (ret <= 0) {
dev_dbg(dev->dev, "user data for channel %d timeout\n",
channel);
+ mchp_spdifrx_isr_blockend_dis(dev);
return ret;
}
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 78d5bcf0819a..4850a177803d 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -196,7 +196,6 @@ struct mchp_spdiftx_dev {
struct clk *pclk;
struct clk *gclk;
unsigned int fmt;
- const struct mchp_i2s_caps *caps;
int gclk_enabled:1;
};
@@ -341,12 +340,10 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd,
ret = regmap_write(dev->regmap, SPDIFTX_MR, mr);
spin_unlock(&ctrl->lock);
- if (ret) {
+ if (ret)
dev_err(dev->dev, "unable to disable TX: %d\n", ret);
- return ret;
- }
- return 0;
+ return ret;
}
static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream,
@@ -763,12 +760,10 @@ static const struct of_device_id mchp_spdiftx_dt_ids[] = {
},
{ /* sentinel */ }
};
-
MODULE_DEVICE_TABLE(of, mchp_spdiftx_dt_ids);
+
static int mchp_spdiftx_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
struct mchp_spdiftx_dev *dev;
struct resource *mem;
struct regmap *regmap;
@@ -782,11 +777,6 @@ static int mchp_spdiftx_probe(struct platform_device *pdev)
if (!dev)
return -ENOMEM;
- /* Get hardware capabilities. */
- match = of_match_node(mchp_spdiftx_dt_ids, np);
- if (match)
- dev->caps = match->data;
-
/* Map I/O registers. */
base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
if (IS_ERR(base))
@@ -848,12 +838,10 @@ static int mchp_spdiftx_probe(struct platform_device *pdev)
err = devm_snd_soc_register_component(&pdev->dev,
&mchp_spdiftx_component,
&mchp_spdiftx_dai, 1);
- if (err) {
+ if (err)
dev_err(&pdev->dev, "failed to register component: %d\n", err);
- return err;
- }
- return 0;
+ return err;
}
static struct platform_driver mchp_spdiftx_driver = {
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 8766e19d85f1..c223d83e02cf 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -6,6 +6,7 @@
//
// Author: David Rhodes <david.rhodes@cirrus.com>
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -1142,6 +1143,30 @@ err_dsp:
return ret;
}
+static int cs35l41_acpi_get_name(struct cs35l41_private *cs35l41)
+{
+ acpi_handle handle = ACPI_HANDLE(cs35l41->dev);
+ const char *sub;
+
+ /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */
+ if (!handle)
+ return 0;
+
+ sub = acpi_get_subsystem_id(handle);
+ if (IS_ERR(sub)) {
+ /* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */
+ if (PTR_ERR(sub) == -ENODATA)
+ return 0;
+ else
+ return PTR_ERR(sub);
+ }
+
+ cs35l41->dsp.system_name = sub;
+ dev_dbg(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name);
+
+ return 0;
+}
+
int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg)
{
u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
@@ -1270,6 +1295,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *
goto err;
}
+ ret = cs35l41_acpi_get_name(cs35l41);
+ if (ret < 0)
+ goto err;
+
ret = cs35l41_dsp_init(cs35l41);
if (ret < 0)
goto err;
@@ -1316,6 +1345,7 @@ void cs35l41_remove(struct cs35l41_private *cs35l41)
pm_runtime_disable(cs35l41->dev);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
+ kfree(cs35l41->dsp.system_name);
wm_adsp2_remove(&cs35l41->dsp);
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c
index 2600be250a3c..2d21339932e6 100644
--- a/sound/soc/codecs/nau8821.c
+++ b/sound/soc/codecs/nau8821.c
@@ -36,6 +36,7 @@
static int nau8821_configure_sysclk(struct nau8821 *nau8821,
int clk_id, unsigned int freq);
+static bool nau8821_is_jack_inserted(struct regmap *regmap);
struct nau8821_fll {
int mclk_src;
@@ -495,7 +496,33 @@ static int nau8821_output_dac_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int system_clock_control(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ dev_dbg(nau8821->dev, "system clock control : POWER OFF\n");
+ /* Set clock source to disable or internal clock before the
+ * playback or capture end. Codec needs clock for Jack
+ * detection and button press if jack inserted; otherwise,
+ * the clock should be closed.
+ */
+ if (nau8821_is_jack_inserted(nau8821->regmap)) {
+ nau8821_configure_sysclk(nau8821,
+ NAU8821_CLK_INTERNAL, 0);
+ } else {
+ nau8821_configure_sysclk(nau8821, NAU8821_CLK_DIS, 0);
+ }
+ }
+ return 0;
+}
+
static const struct snd_soc_dapm_widget nau8821_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("System Clock", SND_SOC_NOPM, 0, 0,
+ system_clock_control, SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("MICBIAS", NAU8821_R74_MIC_BIAS,
NAU8821_MICBIAS_POWERUP_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DMIC Clock", SND_SOC_NOPM, 0, 0,
@@ -607,6 +634,9 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
{"AIFTX", NULL, "ADCL Digital path"},
{"AIFTX", NULL, "ADCR Digital path"},
+ {"AIFTX", NULL, "System Clock"},
+ {"AIFRX", NULL, "System Clock"},
+
{"DDACL", NULL, "AIFRX"},
{"DDACR", NULL, "AIFRX"},
@@ -1699,15 +1729,6 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
return ret;
}
-static int nau8821_i2c_remove(struct i2c_client *i2c_client)
-{
- struct nau8821 *nau8821 = i2c_get_clientdata(i2c_client);
-
- devm_free_irq(nau8821->dev, nau8821->irq, nau8821);
-
- return 0;
-}
-
static const struct i2c_device_id nau8821_i2c_ids[] = {
{ "nau8821", 0 },
{ }
@@ -1737,7 +1758,6 @@ static struct i2c_driver nau8821_driver = {
.acpi_match_table = ACPI_PTR(nau8821_acpi_match),
},
.probe_new = nau8821_i2c_probe,
- .remove = nau8821_i2c_remove,
.id_table = nau8821_i2c_ids,
};
module_i2c_driver(nau8821_driver);
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index d9a0d4768c4d..c836848ef0a6 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -537,6 +537,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
struct device *codec_dev = NULL;
const char *codec_dai_name;
const char *codec_dev_name;
+ u32 asrc_fmt = 0;
u32 width;
int ret;
@@ -829,8 +830,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
goto asrc_fail;
}
- ret = of_property_read_u32(asrc_np, "fsl,asrc-format",
- &priv->asrc_format);
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-format", &asrc_fmt);
+ priv->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
if (ret) {
/* Fallback to old binding; translate to asrc_format */
ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 20a9f8e924b3..aa5edf32d988 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1066,6 +1066,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *regs;
int irq, ret, i;
+ u32 asrc_fmt = 0;
u32 map_idx;
char tmp[16];
u32 width;
@@ -1174,7 +1175,8 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return ret;
}
- ret = of_property_read_u32(np, "fsl,asrc-format", &asrc->asrc_format);
+ ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt);
+ asrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
if (ret) {
ret = of_property_read_u32(np, "fsl,asrc-width", &width);
if (ret) {
@@ -1197,7 +1199,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
}
}
- if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) {
+ if (!(FSL_ASRC_FORMATS & pcm_format_to_bits(asrc->asrc_format))) {
dev_warn(&pdev->dev, "unsupported width, use default S24_LE\n");
asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
}
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index ea96b0fb6b20..3153d19136b2 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -476,7 +476,8 @@ static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc,
struct fsl_asrc_pair *ctx;
struct device *dev;
u32 inrate, outrate, offset = 0;
- u32 in_s_rate, out_s_rate, in_s_fmt, out_s_fmt;
+ u32 in_s_rate, out_s_rate;
+ snd_pcm_format_t in_s_fmt, out_s_fmt;
int ret, i;
if (!easrc)
@@ -1874,6 +1875,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
struct resource *res;
struct device_node *np;
void __iomem *regs;
+ u32 asrc_fmt = 0;
int ret, irq;
easrc = devm_kzalloc(dev, sizeof(*easrc), GFP_KERNEL);
@@ -1934,13 +1936,14 @@ static int fsl_easrc_probe(struct platform_device *pdev)
return ret;
}
- ret = of_property_read_u32(np, "fsl,asrc-format", &easrc->asrc_format);
+ ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt);
+ easrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
if (ret) {
dev_err(dev, "failed to asrc format\n");
return ret;
}
- if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) {
+ if (!(FSL_EASRC_FORMATS & (pcm_format_to_bits(easrc->asrc_format)))) {
dev_warn(dev, "unsupported format, switching to S24_LE\n");
easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
}
diff --git a/sound/soc/fsl/fsl_easrc.h b/sound/soc/fsl/fsl_easrc.h
index 86d5c360d4f5..7c70dac52713 100644
--- a/sound/soc/fsl/fsl_easrc.h
+++ b/sound/soc/fsl/fsl_easrc.h
@@ -569,7 +569,7 @@ struct fsl_easrc_io_params {
unsigned int access_len;
unsigned int fifo_wtmk;
unsigned int sample_rate;
- unsigned int sample_format;
+ snd_pcm_format_t sample_format;
unsigned int norm_rate;
};
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 974ba0780b19..7523bb944b21 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -61,7 +61,7 @@ static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir)
static struct pinctrl_state *fsl_sai_get_pins_state(struct fsl_sai *sai, u32 bclk)
{
- struct pinctrl_state *state = 0;
+ struct pinctrl_state *state = NULL;
if (sai->is_pdm_mode) {
/* DSD512@44.1kHz, DSD512@48kHz */
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
index ccc4194dc5e7..14be29530fb5 100644
--- a/sound/soc/fsl/imx-card.c
+++ b/sound/soc/fsl/imx-card.c
@@ -118,7 +118,7 @@ struct imx_card_data {
struct snd_soc_card card;
int num_dapm_routes;
u32 asrc_rate;
- u32 asrc_format;
+ snd_pcm_format_t asrc_format;
};
static struct imx_akcodec_fs_mul ak4458_fs_mul[] = {
@@ -474,7 +474,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_none(mask);
- snd_mask_set(mask, data->asrc_format);
+ snd_mask_set(mask, (__force unsigned int)data->asrc_format);
return 0;
}
@@ -493,6 +493,7 @@ static int imx_card_parse_of(struct imx_card_data *data)
struct dai_link_data *link_data;
struct of_phandle_args args;
int ret, num_links;
+ u32 asrc_fmt = 0;
u32 width;
ret = snd_soc_of_parse_card_name(card, "model");
@@ -639,7 +640,8 @@ static int imx_card_parse_of(struct imx_card_data *data)
goto err;
}
- ret = of_property_read_u32(args.np, "fsl,asrc-format", &data->asrc_format);
+ ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt);
+ data->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
if (ret) {
/* Fallback to old binding; translate to asrc_format */
ret = of_property_read_u32(args.np, "fsl,asrc-width", &width);
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 2b598af8feef..b327372f2e4a 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -158,8 +158,10 @@ static int asoc_simple_parse_dai(struct device_node *ep,
* if he unbinded CPU or Codec.
*/
ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(node);
return ret;
+ }
dlc->of_node = node;
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 18d053a0d05c..8ac6df645ee6 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -445,8 +445,10 @@ static int asoc_simple_parse_dai(struct device_node *ep,
* if he unbinded CPU or Codec.
*/
ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(node);
return ret;
+ }
dlc->of_node = node;
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index 3d46dd5e5bc4..ce157a8d6552 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -449,35 +449,39 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod)
return ret;
}
+static int avs_probe_create(struct avs_dev *adev, struct avs_path_module *mod)
+{
+ dev_err(adev->dev, "Probe module can't be instantiated by topology");
+ return -EINVAL;
+}
+
+struct avs_module_create {
+ guid_t *guid;
+ int (*create)(struct avs_dev *adev, struct avs_path_module *mod);
+};
+
+static struct avs_module_create avs_module_create[] = {
+ { &AVS_MIXIN_MOD_UUID, avs_modbase_create },
+ { &AVS_MIXOUT_MOD_UUID, avs_modbase_create },
+ { &AVS_KPBUFF_MOD_UUID, avs_modbase_create },
+ { &AVS_COPIER_MOD_UUID, avs_copier_create },
+ { &AVS_MICSEL_MOD_UUID, avs_micsel_create },
+ { &AVS_MUX_MOD_UUID, avs_mux_create },
+ { &AVS_UPDWMIX_MOD_UUID, avs_updown_mix_create },
+ { &AVS_SRCINTC_MOD_UUID, avs_src_create },
+ { &AVS_AEC_MOD_UUID, avs_aec_create },
+ { &AVS_ASRC_MOD_UUID, avs_asrc_create },
+ { &AVS_INTELWOV_MOD_UUID, avs_wov_create },
+ { &AVS_PROBE_MOD_UUID, avs_probe_create },
+};
+
static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_module *mod)
{
const guid_t *type = &mod->template->cfg_ext->type;
- if (guid_equal(type, &AVS_MIXIN_MOD_UUID) ||
- guid_equal(type, &AVS_MIXOUT_MOD_UUID) ||
- guid_equal(type, &AVS_KPBUFF_MOD_UUID))
- return avs_modbase_create(adev, mod);
- if (guid_equal(type, &AVS_COPIER_MOD_UUID))
- return avs_copier_create(adev, mod);
- if (guid_equal(type, &AVS_MICSEL_MOD_UUID))
- return avs_micsel_create(adev, mod);
- if (guid_equal(type, &AVS_MUX_MOD_UUID))
- return avs_mux_create(adev, mod);
- if (guid_equal(type, &AVS_UPDWMIX_MOD_UUID))
- return avs_updown_mix_create(adev, mod);
- if (guid_equal(type, &AVS_SRCINTC_MOD_UUID))
- return avs_src_create(adev, mod);
- if (guid_equal(type, &AVS_AEC_MOD_UUID))
- return avs_aec_create(adev, mod);
- if (guid_equal(type, &AVS_ASRC_MOD_UUID))
- return avs_asrc_create(adev, mod);
- if (guid_equal(type, &AVS_INTELWOV_MOD_UUID))
- return avs_wov_create(adev, mod);
-
- if (guid_equal(type, &AVS_PROBE_MOD_UUID)) {
- dev_err(adev->dev, "Probe module can't be instantiated by topology");
- return -EINVAL;
- }
+ for (int i = 0; i < ARRAY_SIZE(avs_module_create); i++)
+ if (guid_equal(type, avs_module_create[i].guid))
+ return avs_module_create[i].create(adev, mod);
return avs_modext_create(adev, mod);
}
diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c
index aae857fdcdb8..67c3f49b924c 100644
--- a/sound/soc/intel/boards/bdw-rt5650.c
+++ b/sound/soc/intel/boards/bdw-rt5650.c
@@ -249,6 +249,7 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = {
/* SSP0 - Codec */
.name = "Codec",
.id = 0,
+ .nonatomic = 1,
.no_pcm = 1,
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c
index d0ecbba2febe..31488702768e 100644
--- a/sound/soc/intel/boards/bdw-rt5677.c
+++ b/sound/soc/intel/boards/bdw-rt5677.c
@@ -349,6 +349,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
/* SSP0 - Codec */
.name = "Codec",
.id = 0,
+ .nonatomic = 1,
.no_pcm = 1,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
diff --git a/sound/soc/intel/boards/bdw_rt286.c b/sound/soc/intel/boards/bdw_rt286.c
index 47eaddb00936..6b76df0e7c9b 100644
--- a/sound/soc/intel/boards/bdw_rt286.c
+++ b/sound/soc/intel/boards/bdw_rt286.c
@@ -162,6 +162,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
/* SSP0 - Codec */
.name = "Codec",
.id = 0,
+ .nonatomic = 1,
.no_pcm = 1,
.init = codec_link_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC,
diff --git a/sound/soc/intel/boards/hsw_rt5640.c b/sound/soc/intel/boards/hsw_rt5640.c
index ad747363d112..050c53ebd6ba 100644
--- a/sound/soc/intel/boards/hsw_rt5640.c
+++ b/sound/soc/intel/boards/hsw_rt5640.c
@@ -121,6 +121,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
/* SSP0 - Codec */
.name = "Codec",
.id = 0,
+ .nonatomic = 1,
.no_pcm = 1,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC,
.ignore_pmdown_time = 1,
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 23d03e0f7759..c7f33c89588e 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -28,6 +28,24 @@
#define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0))
#define SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK BIT(4)
+
+/* HDMI capture*/
+#define SOF_SSP_HDMI_CAPTURE_PRESENT BIT(14)
+#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 15
+#define SOF_NO_OF_HDMI_CAPTURE_SSP_MASK (GENMASK(16, 15))
+#define SOF_NO_OF_HDMI_CAPTURE_SSP(quirk) \
+ (((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK)
+
+#define SOF_HDMI_CAPTURE_1_SSP_SHIFT 7
+#define SOF_HDMI_CAPTURE_1_SSP_MASK (GENMASK(9, 7))
+#define SOF_HDMI_CAPTURE_1_SSP(quirk) \
+ (((quirk) << SOF_HDMI_CAPTURE_1_SSP_SHIFT) & SOF_HDMI_CAPTURE_1_SSP_MASK)
+
+#define SOF_HDMI_CAPTURE_2_SSP_SHIFT 10
+#define SOF_HDMI_CAPTURE_2_SSP_MASK (GENMASK(12, 10))
+#define SOF_HDMI_CAPTURE_2_SSP(quirk) \
+ (((quirk) << SOF_HDMI_CAPTURE_2_SSP_SHIFT) & SOF_HDMI_CAPTURE_2_SSP_MASK)
+
#define SOF_ES8336_ENABLE_DMIC BIT(5)
#define SOF_ES8336_JD_INVERTED BIT(6)
#define SOF_ES8336_HEADPHONE_GPIO BIT(7)
@@ -57,28 +75,26 @@ static const struct acpi_gpio_params enable_gpio0 = { 0, 0, true };
static const struct acpi_gpio_params enable_gpio1 = { 1, 0, true };
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio0[] = {
- { "speakers-enable-gpios", &enable_gpio0, 1 },
+ { "speakers-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
{ }
};
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio1[] = {
- { "speakers-enable-gpios", &enable_gpio1, 1 },
+ { "speakers-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
};
static const struct acpi_gpio_mapping acpi_enable_both_gpios[] = {
- { "speakers-enable-gpios", &enable_gpio0, 1 },
- { "headphone-enable-gpios", &enable_gpio1, 1 },
+ { "speakers-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
+ { "headphone-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
{ }
};
static const struct acpi_gpio_mapping acpi_enable_both_gpios_rev_order[] = {
- { "speakers-enable-gpios", &enable_gpio1, 1 },
- { "headphone-enable-gpios", &enable_gpio0, 1 },
+ { "speakers-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
+ { "headphone-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
{ }
};
-static const struct acpi_gpio_mapping *gpio_mapping = acpi_speakers_enable_gpio0;
-
static void log_quirks(struct device *dev)
{
dev_info(dev, "quirk mask %#lx\n", quirk);
@@ -272,15 +288,6 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
{
quirk = (unsigned long)id->driver_data;
- if (quirk & SOF_ES8336_HEADPHONE_GPIO) {
- if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
- gpio_mapping = acpi_enable_both_gpios;
- else
- gpio_mapping = acpi_enable_both_gpios_rev_order;
- } else if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK) {
- gpio_mapping = acpi_speakers_enable_gpio1;
- }
-
return 1;
}
@@ -356,6 +363,13 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
+static struct snd_soc_dai_link_component dummy_component[] = {
+ {
+ .name = "snd-soc-dummy",
+ .dai_name = "snd-soc-dummy-dai",
+ }
+};
+
static int sof_es8336_late_probe(struct snd_soc_card *card)
{
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
@@ -507,6 +521,37 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
id++;
}
+ /* HDMI-In SSP */
+ if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) {
+ int num_of_hdmi_ssp = (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
+ SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
+
+ for (i = 1; i <= num_of_hdmi_ssp; i++) {
+ int port = (i == 1 ? (quirk & SOF_HDMI_CAPTURE_1_SSP_MASK) >>
+ SOF_HDMI_CAPTURE_1_SSP_SHIFT :
+ (quirk & SOF_HDMI_CAPTURE_2_SSP_MASK) >>
+ SOF_HDMI_CAPTURE_2_SSP_SHIFT);
+
+ links[id].cpus = &cpus[id];
+ links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SSP%d Pin", port);
+ if (!links[id].cpus->dai_name)
+ return NULL;
+ links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port);
+ if (!links[id].name)
+ return NULL;
+ links[id].id = id + hdmi_id_offset;
+ links[id].codecs = dummy_component;
+ links[id].num_codecs = ARRAY_SIZE(dummy_component);
+ links[id].platforms = platform_component;
+ links[id].num_platforms = ARRAY_SIZE(platform_component);
+ links[id].dpcm_capture = 1;
+ links[id].no_pcm = 1;
+ links[id].num_cpus = 1;
+ id++;
+ }
+ }
+
return links;
devm_err:
@@ -529,6 +574,7 @@ static int sof_es8336_probe(struct platform_device *pdev)
struct acpi_device *adev;
struct snd_soc_dai_link *dai_links;
struct device *codec_dev;
+ const struct acpi_gpio_mapping *gpio_mapping;
unsigned int cnt = 0;
int dmic_be_num = 0;
int hdmi_num = 3;
@@ -541,29 +587,34 @@ static int sof_es8336_probe(struct platform_device *pdev)
card = &sof_es8336_card;
card->dev = dev;
+ if (pdev->id_entry && pdev->id_entry->driver_data)
+ quirk = (unsigned long)pdev->id_entry->driver_data;
+
/* check GPIO DMI quirks */
dmi_check_system(sof_es8336_quirk_table);
- if (!mach->mach_params.i2s_link_mask) {
- dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n");
- } else {
- /*
- * Set configuration based on platform NHLT.
- * In this machine driver, we can only support one SSP for the
- * ES8336 link, the else-if below are intentional.
- * In some cases multiple SSPs can be reported by NHLT, starting MSB-first
- * seems to pick the right connection.
- */
- unsigned long ssp = 0;
-
- if (mach->mach_params.i2s_link_mask & BIT(2))
- ssp = SOF_ES8336_SSP_CODEC(2);
- else if (mach->mach_params.i2s_link_mask & BIT(1))
- ssp = SOF_ES8336_SSP_CODEC(1);
- else if (mach->mach_params.i2s_link_mask & BIT(0))
- ssp = SOF_ES8336_SSP_CODEC(0);
-
- quirk |= ssp;
+ /* Use NHLT configuration only for Non-HDMI capture use case.
+ * Because more than one SSP will be enabled for HDMI capture hence wrong codec
+ * SSP will be set.
+ */
+ if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER) {
+ if (!mach->mach_params.i2s_link_mask) {
+ dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n");
+ } else {
+ /*
+ * Set configuration based on platform NHLT.
+ * In this machine driver, we can only support one SSP for the
+ * ES8336 link.
+ * In some cases multiple SSPs can be reported by NHLT, starting MSB-first
+ * seems to pick the right connection.
+ */
+ unsigned long ssp;
+
+ /* fls returns 1-based results, SSPs indices are 0-based */
+ ssp = fls(mach->mach_params.i2s_link_mask) - 1;
+
+ quirk |= ssp;
+ }
}
if (mach->mach_params.dmic_num)
@@ -579,7 +630,13 @@ static int sof_es8336_probe(struct platform_device *pdev)
if (quirk & SOF_ES8336_ENABLE_DMIC)
dmic_be_num = 2;
- sof_es8336_card.num_links += dmic_be_num + hdmi_num;
+ /* compute number of dai links */
+ sof_es8336_card.num_links = 1 + dmic_be_num + hdmi_num;
+
+ if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT)
+ sof_es8336_card.num_links += (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
+ SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
+
dai_links = sof_card_dai_links_create(dev,
SOF_ES8336_SSP_CODEC(quirk),
dmic_be_num, hdmi_num);
@@ -635,6 +692,17 @@ static int sof_es8336_probe(struct platform_device *pdev)
}
/* get speaker enable GPIO */
+ if (quirk & SOF_ES8336_HEADPHONE_GPIO) {
+ if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
+ gpio_mapping = acpi_enable_both_gpios;
+ else
+ gpio_mapping = acpi_enable_both_gpios_rev_order;
+ } else if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK) {
+ gpio_mapping = acpi_speakers_enable_gpio1;
+ } else {
+ gpio_mapping = acpi_speakers_enable_gpio0;
+ }
+
ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
if (ret)
dev_warn(codec_dev, "unable to add GPIO mapping table\n");
@@ -690,6 +758,21 @@ static int sof_es8336_remove(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id board_ids[] = {
+ {
+ .name = "adl_es83x6_c1_h02",
+ .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) |
+ SOF_NO_OF_HDMI_CAPTURE_SSP(2) |
+ SOF_HDMI_CAPTURE_1_SSP(0) |
+ SOF_HDMI_CAPTURE_2_SSP(2) |
+ SOF_SSP_HDMI_CAPTURE_PRESENT |
+ SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK |
+ SOF_ES8336_JD_INVERTED),
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, board_ids);
+
static struct platform_driver sof_es8336_driver = {
.driver = {
.name = "sof-essx8336",
@@ -697,6 +780,7 @@ static struct platform_driver sof_es8336_driver = {
},
.probe = sof_es8336_probe,
.remove = sof_es8336_remove,
+ .id_table = board_ids,
};
module_platform_driver(sof_es8336_driver);
diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
index f49700eb721b..8d7e5ba9e516 100644
--- a/sound/soc/intel/boards/sof_nau8825.c
+++ b/sound/soc/intel/boards/sof_nau8825.c
@@ -190,11 +190,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
struct sof_hdmi_pcm *pcm;
int err;
- if (list_empty(&ctx->hdmi_pcm_list))
- return -EINVAL;
-
- pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
-
if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
/* Disable Left and Right Spk pin after boot */
snd_soc_dapm_disable_pin(dapm, "Left Spk");
@@ -204,6 +199,11 @@ static int sof_card_late_probe(struct snd_soc_card *card)
return err;
}
+ if (list_empty(&ctx->hdmi_pcm_list))
+ return -EINVAL;
+
+ pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
+
return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
}
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 1384716c6360..045965312245 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -447,6 +447,15 @@ static int sof_card_late_probe(struct snd_soc_card *card)
struct sof_hdmi_pcm *pcm;
int err;
+ if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
+ /* Disable Left and Right Spk pin after boot */
+ snd_soc_dapm_disable_pin(dapm, "Left Spk");
+ snd_soc_dapm_disable_pin(dapm, "Right Spk");
+ err = snd_soc_dapm_sync(dapm);
+ if (err < 0)
+ return err;
+ }
+
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
if (is_legacy_cpu || !ctx->idisp_codec)
return 0;
@@ -477,15 +486,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
return err;
}
- if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
- /* Disable Left and Right Spk pin after boot */
- snd_soc_dapm_disable_pin(dapm, "Left Spk");
- snd_soc_dapm_disable_pin(dapm, "Right Spk");
- err = snd_soc_dapm_sync(dapm);
- if (err < 0)
- return err;
- }
-
return hdac_hdmi_jack_port_init(component, &card->dapm);
}
@@ -1092,6 +1092,14 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
+ {
+ .name = "mtl_mx98357_rt5682",
+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_SSP_CODEC(0) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_RT5682_SSP_AMP(1) |
+ SOF_RT5682_NUM_HDMIDEV(4)),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 0c47d76a79e2..a49bfaab6b21 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -250,6 +250,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ RT711_JD2 |
+ SOF_SDW_FOUR_SPK),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
},
/* No Jack */
@@ -315,6 +325,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
RT711_JD2 |
SOF_SDW_FOUR_SPK),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ RT711_JD2),
+ },
/* MeteorLake devices */
{
.callback = sof_sdw_quirk_cb,
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index 49ff0871e9e7..8291967f23f3 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -139,6 +139,9 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ if (!ctx->headset_codec_dev)
+ return 0;
+
device_remove_software_node(ctx->headset_codec_dev);
put_device(ctx->headset_codec_dev);
diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
index b3fc32bacfa8..7f16304d025b 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
@@ -140,6 +140,9 @@ int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ if (!ctx->headset_codec_dev)
+ return 0;
+
device_remove_software_node(ctx->headset_codec_dev);
put_device(ctx->headset_codec_dev);
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index fea087d3fa15..9990d5502d26 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -8,6 +8,11 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+static const struct snd_soc_acpi_codecs essx_83x6 = {
+ .num_codecs = 3,
+ .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
+};
+
static const struct snd_soc_acpi_endpoint single_endpoint = {
.num = 0,
.aggregated = 0,
@@ -137,6 +142,15 @@ static const struct snd_soc_acpi_adr_device rt1316_2_single_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
+ {
+ .adr = 0x000330025D131601ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1316-1"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
{
.adr = 0x000030025D071401ull,
@@ -326,6 +340,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link2_rt714_link0[] = {
{}
};
+static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link3[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
+ .adr_d = rt711_sdca_0_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt1316_3_single_adr),
+ .adr_d = rt1316_3_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_adr_device mx8373_2_adr[] = {
{
.adr = 0x000223019F837300ull,
@@ -412,6 +440,11 @@ static const struct snd_soc_acpi_codecs adl_max98390_amp = {
.codecs = {"MX98390"}
};
+static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = {
+ .num_codecs = 1,
+ .codecs = {"INTC10B0"}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
{
.comp_ids = &adl_rt5682_rt5682s_hp,
@@ -492,6 +525,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
.drv_name = "adl_cs35l41",
.sof_tplg_filename = "sof-adl-cs35l41.tplg",
},
+ {
+ .comp_ids = &essx_83x6,
+ .drv_name = "adl_es83x6_c1_h02",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &adl_lt6911_hdmi,
+ .sof_tplg_filename = "sof-adl-es83x6-ssp1-hdmi-ssp02.tplg",
+ },
+ {
+ .comp_ids = &essx_83x6,
+ .drv_name = "sof-essx8336",
+ .sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
+ SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
+ SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_machines);
@@ -547,6 +595,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
.sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l0.tplg",
},
{
+ .link_mask = 0x9, /* 2 active links required */
+ .links = adl_sdw_rt711_link0_rt1316_link3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l3.tplg",
+ },
+ {
.link_mask = 0x1, /* link0 required */
.links = adl_rvp,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index 74d3b82f8d35..36c361fb28a4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -10,7 +10,24 @@
#include <sound/soc-acpi-intel-match.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
+static const struct snd_soc_acpi_codecs mtl_max98357a_amp = {
+ .num_codecs = 1,
+ .codecs = {"MX98357A"}
+};
+
+static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
+ .num_codecs = 2,
+ .codecs = {"10EC5682", "RTL5682"},
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
+ {
+ .comp_ids = &mtl_rt5682_rt5682s_hp,
+ .drv_name = "mtl_mx98357_rt5682",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &mtl_max98357a_amp,
+ .sof_tplg_filename = "sof-mtl-max98357a-rt5682.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines);
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index ecd8df70d39c..c4c1e89b47c1 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -93,7 +93,6 @@ struct i2s_soc_info {
};
struct jz4740_i2s {
- struct resource *mem;
void __iomem *base;
struct clk *clk_aic;
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 9e5ce1a82639..363fa4d47680 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -152,6 +152,51 @@ config SND_SOC_MT8183_DA7219_MAX98357A
Select Y if you have such device.
If unsure select "N".
+config SND_SOC_MT8186
+ tristate "ASoC support for Mediatek MT8186 chip"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on COMMON_CLK
+ select SND_SOC_MEDIATEK
+ select SND_SOC_MT6358
+ select MFD_SYSCON if SND_SOC_MT6358
+ help
+ This adds ASoC driver for Mediatek MT8186 boards
+ that can be used with other codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
+config SND_SOC_MT8186_MT6366_DA7219_MAX98357
+ tristate "ASoC Audio driver for MT8186 with DA7219 MAX98357A codec"
+ depends on I2C && GPIOLIB
+ depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
+ select SND_SOC_MT6358
+ select SND_SOC_MAX98357A
+ select SND_SOC_DA7219
+ select SND_SOC_BT_SCO
+ select SND_SOC_DMIC
+ select SND_SOC_HDMI_CODEC
+ help
+ This adds ASoC driver for Mediatek MT8186 boards
+ with the MT6366(MT6358) DA7219 MAX98357A codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
+config SND_SOC_MT8186_MT6366_RT1019_RT5682S
+ tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S codec"
+ depends on I2C && GPIOLIB
+ depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
+ select SND_SOC_MT6358
+ select SND_SOC_RT1015P
+ select SND_SOC_RT5682S
+ select SND_SOC_BT_SCO
+ select SND_SOC_DMIC
+ select SND_SOC_HDMI_CODEC
+ help
+ This adds ASoC driver for Mediatek MT8186 boards
+ with the MT6366(MT6358) RT1019 RT5682S codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
config SND_SOC_MTK_BTCVSD
tristate "ALSA BT SCO CVSD/MSBC Driver"
help
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index 34778ca12106..5571c640a288 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -4,5 +4,6 @@ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
+obj-$(CONFIG_SND_SOC_MT8186) += mt8186/
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
diff --git a/sound/soc/mediatek/common/Makefile b/sound/soc/mediatek/common/Makefile
index acbe01e9e928..576deb7f8cce 100644
--- a/sound/soc/mediatek/common/Makefile
+++ b/sound/soc/mediatek/common/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# platform driver
-snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o
+snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o mtk-dsp-sof-common.o
obj-$(CONFIG_SND_SOC_MEDIATEK) += snd-soc-mtk-common.o
obj-$(CONFIG_SND_SOC_MTK_BTCVSD) += mtk-btcvsd.o
diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.c b/sound/soc/mediatek/common/mtk-dsp-sof-common.c
new file mode 100644
index 000000000000..8b1b623207be
--- /dev/null
+++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mtk-dsp-sof-common.c -- MediaTek dsp sof common ctrl
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Chunxu Li <chunxu.li@mediatek.com>
+ */
+
+#include "mtk-dsp-sof-common.h"
+#include "mtk-soc-card.h"
+
+/* fixup the BE DAI link to match any values from topology */
+int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
+ struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
+ int i, j, ret = 0;
+
+ for (i = 0; i < sof_priv->num_streams; i++) {
+ struct snd_soc_dai *cpu_dai;
+ struct snd_soc_pcm_runtime *runtime;
+ struct snd_soc_dai_link *sof_dai_link = NULL;
+ const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
+
+ if (strcmp(rtd->dai_link->name, conn->normal_link))
+ continue;
+
+ for_each_card_rtds(card, runtime) {
+ if (strcmp(runtime->dai_link->name, conn->sof_link))
+ continue;
+
+ for_each_rtd_cpu_dais(runtime, j, cpu_dai) {
+ if (cpu_dai->stream_active[conn->stream_dir] > 0) {
+ sof_dai_link = runtime->dai_link;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (sof_dai_link && sof_dai_link->be_hw_params_fixup)
+ ret = sof_dai_link->be_hw_params_fixup(runtime, params);
+
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mtk_sof_dai_link_fixup);
+
+int mtk_sof_card_probe(struct snd_soc_card *card)
+{
+ int i;
+ struct snd_soc_dai_link *dai_link;
+
+ /* Set stream_name to help sof bind widgets */
+ for_each_card_prelinks(card, i, dai_link) {
+ if (dai_link->no_pcm && !dai_link->stream_name && dai_link->name)
+ dai_link->stream_name = dai_link->name;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_sof_card_probe);
+
+int mtk_sof_card_late_probe(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_component *sof_comp = NULL;
+ struct mtk_soc_card_data *soc_card_data =
+ snd_soc_card_get_drvdata(card);
+ struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
+ int i;
+
+ /* 1. find sof component */
+ for_each_card_rtds(card, rtd) {
+ sof_comp = snd_soc_rtdcom_lookup(rtd, "sof-audio-component");
+ if (sof_comp)
+ break;
+ }
+
+ if (!sof_comp) {
+ dev_info(card->dev, "probe without sof-audio-component\n");
+ return 0;
+ }
+
+ /* 2. add route path and fixup callback */
+ for (i = 0; i < sof_priv->num_streams; i++) {
+ const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
+ struct snd_soc_pcm_runtime *sof_rtd = NULL;
+ struct snd_soc_pcm_runtime *normal_rtd = NULL;
+
+ for_each_card_rtds(card, rtd) {
+ if (!strcmp(rtd->dai_link->name, conn->sof_link)) {
+ sof_rtd = rtd;
+ continue;
+ }
+ if (!strcmp(rtd->dai_link->name, conn->normal_link)) {
+ normal_rtd = rtd;
+ continue;
+ }
+ if (normal_rtd && sof_rtd)
+ break;
+ }
+ if (normal_rtd && sof_rtd) {
+ int j;
+ struct snd_soc_dai *cpu_dai;
+
+ for_each_rtd_cpu_dais(sof_rtd, j, cpu_dai) {
+ struct snd_soc_dapm_route route;
+ struct snd_soc_dapm_path *p = NULL;
+ struct snd_soc_dapm_widget *play_widget =
+ cpu_dai->playback_widget;
+ struct snd_soc_dapm_widget *cap_widget =
+ cpu_dai->capture_widget;
+ memset(&route, 0, sizeof(route));
+ if (conn->stream_dir == SNDRV_PCM_STREAM_CAPTURE &&
+ cap_widget) {
+ snd_soc_dapm_widget_for_each_sink_path(cap_widget, p) {
+ route.source = conn->sof_dma;
+ route.sink = p->sink->name;
+ snd_soc_dapm_add_routes(&card->dapm, &route, 1);
+ }
+ } else if (conn->stream_dir == SNDRV_PCM_STREAM_PLAYBACK &&
+ play_widget) {
+ snd_soc_dapm_widget_for_each_source_path(play_widget, p) {
+ route.source = p->source->name;
+ route.sink = conn->sof_dma;
+ snd_soc_dapm_add_routes(&card->dapm, &route, 1);
+ }
+ } else {
+ dev_err(cpu_dai->dev, "stream dir and widget not pair\n");
+ }
+ }
+
+ sof_rtd->dai_link->be_hw_params_fixup =
+ sof_comp->driver->be_hw_params_fixup;
+ if (sof_priv->sof_dai_link_fixup)
+ normal_rtd->dai_link->be_hw_params_fixup =
+ sof_priv->sof_dai_link_fixup;
+ else
+ normal_rtd->dai_link->be_hw_params_fixup = mtk_sof_dai_link_fixup;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_sof_card_late_probe);
+
+int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
+ const char *propname, struct snd_soc_dai_link *pre_dai_links,
+ int pre_num_links)
+{
+ struct device *dev = card->dev;
+ struct snd_soc_dai_link *parsed_dai_link;
+ const char *dai_name = NULL;
+ int i, j, ret, num_links, parsed_num_links = 0;
+
+ num_links = of_property_count_strings(np, "mediatek,dai-link");
+ if (num_links < 0 || num_links > card->num_links) {
+ dev_dbg(dev, "number of dai-link is invalid\n");
+ return -EINVAL;
+ }
+
+ parsed_dai_link = devm_kcalloc(dev, num_links, sizeof(*parsed_dai_link), GFP_KERNEL);
+ if (!parsed_dai_link)
+ return -ENOMEM;
+
+ for (i = 0; i < num_links; i++) {
+ ret = of_property_read_string_index(np, propname, i, &dai_name);
+ if (ret) {
+ dev_dbg(dev, "ASoC: Property '%s' index %d could not be read: %d\n",
+ propname, i, ret);
+ return ret;
+ }
+ dev_dbg(dev, "ASoC: Property get dai_name:%s\n", dai_name);
+ for (j = 0; j < pre_num_links; j++) {
+ if (!strcmp(dai_name, pre_dai_links[j].name)) {
+ memcpy(&parsed_dai_link[parsed_num_links++], &pre_dai_links[j],
+ sizeof(struct snd_soc_dai_link));
+ break;
+ }
+ }
+ }
+
+ if (parsed_num_links != num_links)
+ return -EINVAL;
+
+ card->dai_link = parsed_dai_link;
+ card->num_links = parsed_num_links;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_sof_dailink_parse_of);
diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.h b/sound/soc/mediatek/common/mtk-dsp-sof-common.h
new file mode 100644
index 000000000000..dd38c4a93574
--- /dev/null
+++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mtk-dsp-sof-common.h -- MediaTek dsp sof common definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Chunxu Li <chunxu.li@mediatek.com>
+ */
+
+#ifndef _MTK_DSP_SOF_COMMON_H_
+#define _MTK_DSP_SOF_COMMON_H_
+
+#include <sound/soc.h>
+
+struct sof_conn_stream {
+ const char *normal_link;
+ const char *sof_link;
+ const char *sof_dma;
+ int stream_dir;
+};
+
+struct mtk_sof_priv {
+ const struct sof_conn_stream *conn_streams;
+ int num_streams;
+ int (*sof_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+};
+
+int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+int mtk_sof_card_probe(struct snd_soc_card *card);
+int mtk_sof_card_late_probe(struct snd_soc_card *card);
+int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
+ const char *propname, struct snd_soc_dai_link *pre_dai_links,
+ int pre_num_links);
+
+#endif
diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h
new file mode 100644
index 000000000000..eeda79370049
--- /dev/null
+++ b/sound/soc/mediatek/common/mtk-soc-card.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mtk-soc-card.h -- MediaTek soc card data definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Chunxu Li <chunxu.li@mediatek.com>
+ */
+
+#ifndef _MTK_SOC_CARD_H_
+#define _MTK_SOC_CARD_H_
+
+struct mtk_soc_card_data {
+ void *mach_priv;
+ void *sof_priv;
+};
+
+#endif
diff --git a/sound/soc/mediatek/mt8186/Makefile b/sound/soc/mediatek/mt8186/Makefile
new file mode 100644
index 000000000000..49b0026628a0
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# platform driver
+snd-soc-mt8186-afe-objs := \
+ mt8186-afe-pcm.o \
+ mt8186-audsys-clk.o \
+ mt8186-afe-clk.o \
+ mt8186-afe-gpio.o \
+ mt8186-dai-adda.o \
+ mt8186-afe-control.o \
+ mt8186-dai-i2s.o \
+ mt8186-dai-hw-gain.o \
+ mt8186-dai-pcm.o \
+ mt8186-dai-src.o \
+ mt8186-dai-hostless.o \
+ mt8186-dai-tdm.o \
+ mt8186-misc-control.o \
+ mt8186-mt6366-common.o
+
+obj-$(CONFIG_SND_SOC_MT8186) += snd-soc-mt8186-afe.o
+obj-$(CONFIG_SND_SOC_MT8186_MT6366_DA7219_MAX98357) += mt8186-mt6366-da7219-max98357.o
+obj-$(CONFIG_SND_SOC_MT8186_MT6366_RT1019_RT5682S) += mt8186-mt6366-rt1019-rt5682s.o
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
index 0275f66ddc18..a6b4f29049bb 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
@@ -645,7 +645,8 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
return 0;
}
-void mt8186_deinit_clock(struct mtk_base_afe *afe)
+void mt8186_deinit_clock(void *priv)
{
+ struct mtk_base_afe *afe = priv;
mt8186_audsys_clk_unregister(afe);
}
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
index c539557d7c78..d5988717d8f2 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
@@ -81,7 +81,7 @@ enum {
struct mtk_base_afe;
int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
int mt8186_init_clock(struct mtk_base_afe *afe);
-void mt8186_deinit_clock(struct mtk_base_afe *afe);
+void mt8186_deinit_clock(void *priv);
int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
int mt8186_afe_enable_clock(struct mtk_base_afe *afe);
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-common.h b/sound/soc/mediatek/mt8186/mt8186-afe-common.h
new file mode 100644
index 000000000000..b8f03e1b7e49
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-common.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * mt8186-afe-common.h -- Mediatek 8186 audio driver definitions
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+ */
+
+#ifndef _MT_8186_AFE_COMMON_H_
+#define _MT_8186_AFE_COMMON_H_
+#include <sound/soc.h>
+#include <linux/list.h>
+#include <linux/regmap.h>
+#include "mt8186-reg.h"
+#include "../common/mtk-base-afe.h"
+
+enum {
+ MT8186_MEMIF_DL1,
+ MT8186_MEMIF_DL12,
+ MT8186_MEMIF_DL2,
+ MT8186_MEMIF_DL3,
+ MT8186_MEMIF_DL4,
+ MT8186_MEMIF_DL5,
+ MT8186_MEMIF_DL6,
+ MT8186_MEMIF_DL7,
+ MT8186_MEMIF_DL8,
+ MT8186_MEMIF_VUL12,
+ MT8186_MEMIF_VUL2,
+ MT8186_MEMIF_VUL3,
+ MT8186_MEMIF_VUL4,
+ MT8186_MEMIF_VUL5,
+ MT8186_MEMIF_VUL6,
+ MT8186_MEMIF_AWB,
+ MT8186_MEMIF_AWB2,
+ MT8186_MEMIF_NUM,
+ MT8186_DAI_ADDA = MT8186_MEMIF_NUM,
+ MT8186_DAI_AP_DMIC,
+ MT8186_DAI_CONNSYS_I2S,
+ MT8186_DAI_I2S_0,
+ MT8186_DAI_I2S_1,
+ MT8186_DAI_I2S_2,
+ MT8186_DAI_I2S_3,
+ MT8186_DAI_HW_GAIN_1,
+ MT8186_DAI_HW_GAIN_2,
+ MT8186_DAI_SRC_1,
+ MT8186_DAI_SRC_2,
+ MT8186_DAI_PCM,
+ MT8186_DAI_TDM_IN,
+ MT8186_DAI_HOSTLESS_LPBK,
+ MT8186_DAI_HOSTLESS_FM,
+ MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO,
+ MT8186_DAI_HOSTLESS_SRC_AAUDIO,
+ MT8186_DAI_HOSTLESS_SRC_1,
+ MT8186_DAI_HOSTLESS_SRC_BARGEIN,
+ MT8186_DAI_HOSTLESS_UL1,
+ MT8186_DAI_HOSTLESS_UL2,
+ MT8186_DAI_HOSTLESS_UL3,
+ MT8186_DAI_HOSTLESS_UL5,
+ MT8186_DAI_HOSTLESS_UL6,
+ MT8186_DAI_NUM,
+};
+
+#define MT8186_RECORD_MEMIF MT8186_MEMIF_VUL12
+#define MT8186_ECHO_REF_MEMIF MT8186_MEMIF_AWB
+#define MT8186_PRIMARY_MEMIF MT8186_MEMIF_DL1
+#define MT8186_FAST_MEMIF MT8186_MEMIF_DL2
+#define MT8186_DEEP_MEMIF MT8186_MEMIF_DL3
+#define MT8186_VOIP_MEMIF MT8186_MEMIF_DL12
+#define MT8186_MMAP_DL_MEMIF MT8186_MEMIF_DL5
+#define MT8186_MMAP_UL_MEMIF MT8186_MEMIF_VUL5
+#define MT8186_BARGEIN_MEMIF MT8186_MEMIF_AWB
+
+enum {
+ MT8186_IRQ_0,
+ MT8186_IRQ_1,
+ MT8186_IRQ_2,
+ MT8186_IRQ_3,
+ MT8186_IRQ_4,
+ MT8186_IRQ_5,
+ MT8186_IRQ_6,
+ MT8186_IRQ_7,
+ MT8186_IRQ_8,
+ MT8186_IRQ_9,
+ MT8186_IRQ_10,
+ MT8186_IRQ_11,
+ MT8186_IRQ_12,
+ MT8186_IRQ_13,
+ MT8186_IRQ_14,
+ MT8186_IRQ_15,
+ MT8186_IRQ_16,
+ MT8186_IRQ_17,
+ MT8186_IRQ_18,
+ MT8186_IRQ_19,
+ MT8186_IRQ_20,
+ MT8186_IRQ_21,
+ MT8186_IRQ_22,
+ MT8186_IRQ_23,
+ MT8186_IRQ_24,
+ MT8186_IRQ_25,
+ MT8186_IRQ_26,
+ MT8186_IRQ_NUM,
+};
+
+enum {
+ MT8186_AFE_IRQ_DIR_MCU = 0,
+ MT8186_AFE_IRQ_DIR_DSP,
+ MT8186_AFE_IRQ_DIR_BOTH,
+};
+
+enum {
+ MTKAIF_PROTOCOL_1 = 0,
+ MTKAIF_PROTOCOL_2,
+ MTKAIF_PROTOCOL_2_CLK_P2,
+};
+
+enum {
+ MTK_AFE_ADDA_DL_GAIN_MUTE = 0,
+ MTK_AFE_ADDA_DL_GAIN_NORMAL = 0xf74f,
+ /* SA suggest apply -0.3db to audio/speech path */
+};
+
+#define MTK_SPK_I2S_0_STR "MTK_SPK_I2S_0"
+#define MTK_SPK_I2S_1_STR "MTK_SPK_I2S_1"
+#define MTK_SPK_I2S_2_STR "MTK_SPK_I2S_2"
+#define MTK_SPK_I2S_3_STR "MTK_SPK_I2S_3"
+
+/* MCLK */
+enum {
+ MT8186_I2S0_MCK = 0,
+ MT8186_I2S1_MCK,
+ MT8186_I2S2_MCK,
+ MT8186_I2S4_MCK,
+ MT8186_TDM_MCK,
+ MT8186_MCK_NUM,
+};
+
+struct snd_pcm_substream;
+struct mtk_base_irq_data;
+struct clk;
+
+struct mt8186_afe_private {
+ struct clk **clk;
+ struct clk_lookup **lookup;
+ struct regmap *topckgen;
+ struct regmap *apmixedsys;
+ struct regmap *infracfg;
+ int irq_cnt[MT8186_MEMIF_NUM];
+ int stf_positive_gain_db;
+ int pm_runtime_bypass_reg_ctl;
+ int sgen_mode;
+ int sgen_rate;
+ int sgen_amplitude;
+
+ /* xrun assert */
+ int xrun_assert[MT8186_MEMIF_NUM];
+
+ /* dai */
+ bool dai_on[MT8186_DAI_NUM];
+ void *dai_priv[MT8186_DAI_NUM];
+
+ /* adda */
+ bool mtkaif_calibration_ok;
+ int mtkaif_protocol;
+ int mtkaif_chosen_phase[4];
+ int mtkaif_phase_cycle[4];
+ int mtkaif_calibration_num_phase;
+ int mtkaif_dmic;
+ int mtkaif_looback0;
+ int mtkaif_looback1;
+
+ /* mck */
+ int mck_rate[MT8186_MCK_NUM];
+};
+
+int mt8186_dai_adda_register(struct mtk_base_afe *afe);
+int mt8186_dai_i2s_register(struct mtk_base_afe *afe);
+int mt8186_dai_tdm_register(struct mtk_base_afe *afe);
+int mt8186_dai_hw_gain_register(struct mtk_base_afe *afe);
+int mt8186_dai_src_register(struct mtk_base_afe *afe);
+int mt8186_dai_pcm_register(struct mtk_base_afe *afe);
+int mt8186_dai_hostless_register(struct mtk_base_afe *afe);
+
+int mt8186_add_misc_control(struct snd_soc_component *component);
+
+unsigned int mt8186_general_rate_transform(struct device *dev,
+ unsigned int rate);
+unsigned int mt8186_rate_transform(struct device *dev,
+ unsigned int rate, int aud_blk);
+unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev,
+ unsigned int rate);
+
+int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id,
+ int priv_size, const void *priv_data);
+
+#endif
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-control.c b/sound/soc/mediatek/mt8186/mt8186-afe-control.c
new file mode 100644
index 000000000000..d714e9641571
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-control.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include "mt8186-afe-common.h"
+#include <linux/pm_runtime.h>
+
+enum {
+ MTK_AFE_RATE_8K = 0,
+ MTK_AFE_RATE_11K,
+ MTK_AFE_RATE_12K,
+ MTK_AFE_RATE_384K,
+ MTK_AFE_RATE_16K,
+ MTK_AFE_RATE_22K,
+ MTK_AFE_RATE_24K,
+ MTK_AFE_RATE_352K,
+ MTK_AFE_RATE_32K,
+ MTK_AFE_RATE_44K,
+ MTK_AFE_RATE_48K,
+ MTK_AFE_RATE_88K,
+ MTK_AFE_RATE_96K,
+ MTK_AFE_RATE_176K,
+ MTK_AFE_RATE_192K,
+ MTK_AFE_RATE_260K,
+};
+
+enum {
+ MTK_AFE_PCM_RATE_8K = 0,
+ MTK_AFE_PCM_RATE_16K,
+ MTK_AFE_PCM_RATE_32K,
+ MTK_AFE_PCM_RATE_48K,
+};
+
+enum {
+ MTK_AFE_TDM_RATE_8K = 0,
+ MTK_AFE_TDM_RATE_12K,
+ MTK_AFE_TDM_RATE_16K,
+ MTK_AFE_TDM_RATE_24K,
+ MTK_AFE_TDM_RATE_32K,
+ MTK_AFE_TDM_RATE_48K,
+ MTK_AFE_TDM_RATE_64K,
+ MTK_AFE_TDM_RATE_96K,
+ MTK_AFE_TDM_RATE_128K,
+ MTK_AFE_TDM_RATE_192K,
+ MTK_AFE_TDM_RATE_256K,
+ MTK_AFE_TDM_RATE_384K,
+ MTK_AFE_TDM_RATE_11K,
+ MTK_AFE_TDM_RATE_22K,
+ MTK_AFE_TDM_RATE_44K,
+ MTK_AFE_TDM_RATE_88K,
+ MTK_AFE_TDM_RATE_176K,
+ MTK_AFE_TDM_RATE_352K,
+};
+
+enum {
+ MTK_AFE_TDM_RELATCH_RATE_8K = 0,
+ MTK_AFE_TDM_RELATCH_RATE_11K,
+ MTK_AFE_TDM_RELATCH_RATE_12K,
+ MTK_AFE_TDM_RELATCH_RATE_16K,
+ MTK_AFE_TDM_RELATCH_RATE_22K,
+ MTK_AFE_TDM_RELATCH_RATE_24K,
+ MTK_AFE_TDM_RELATCH_RATE_32K,
+ MTK_AFE_TDM_RELATCH_RATE_44K,
+ MTK_AFE_TDM_RELATCH_RATE_48K,
+ MTK_AFE_TDM_RELATCH_RATE_88K,
+ MTK_AFE_TDM_RELATCH_RATE_96K,
+ MTK_AFE_TDM_RELATCH_RATE_176K,
+ MTK_AFE_TDM_RELATCH_RATE_192K,
+ MTK_AFE_TDM_RELATCH_RATE_352K,
+ MTK_AFE_TDM_RELATCH_RATE_384K,
+};
+
+unsigned int mt8186_general_rate_transform(struct device *dev, unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_RATE_8K;
+ case 11025:
+ return MTK_AFE_RATE_11K;
+ case 12000:
+ return MTK_AFE_RATE_12K;
+ case 16000:
+ return MTK_AFE_RATE_16K;
+ case 22050:
+ return MTK_AFE_RATE_22K;
+ case 24000:
+ return MTK_AFE_RATE_24K;
+ case 32000:
+ return MTK_AFE_RATE_32K;
+ case 44100:
+ return MTK_AFE_RATE_44K;
+ case 48000:
+ return MTK_AFE_RATE_48K;
+ case 88200:
+ return MTK_AFE_RATE_88K;
+ case 96000:
+ return MTK_AFE_RATE_96K;
+ case 176400:
+ return MTK_AFE_RATE_176K;
+ case 192000:
+ return MTK_AFE_RATE_192K;
+ case 260000:
+ return MTK_AFE_RATE_260K;
+ case 352800:
+ return MTK_AFE_RATE_352K;
+ case 384000:
+ return MTK_AFE_RATE_384K;
+ default:
+ dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
+ __func__, rate, MTK_AFE_RATE_48K);
+ }
+
+ return MTK_AFE_RATE_48K;
+}
+
+static unsigned int tdm_rate_transform(struct device *dev, unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_TDM_RATE_8K;
+ case 11025:
+ return MTK_AFE_TDM_RATE_11K;
+ case 12000:
+ return MTK_AFE_TDM_RATE_12K;
+ case 16000:
+ return MTK_AFE_TDM_RATE_16K;
+ case 22050:
+ return MTK_AFE_TDM_RATE_22K;
+ case 24000:
+ return MTK_AFE_TDM_RATE_24K;
+ case 32000:
+ return MTK_AFE_TDM_RATE_32K;
+ case 44100:
+ return MTK_AFE_TDM_RATE_44K;
+ case 48000:
+ return MTK_AFE_TDM_RATE_48K;
+ case 64000:
+ return MTK_AFE_TDM_RATE_64K;
+ case 88200:
+ return MTK_AFE_TDM_RATE_88K;
+ case 96000:
+ return MTK_AFE_TDM_RATE_96K;
+ case 128000:
+ return MTK_AFE_TDM_RATE_128K;
+ case 176400:
+ return MTK_AFE_TDM_RATE_176K;
+ case 192000:
+ return MTK_AFE_TDM_RATE_192K;
+ case 256000:
+ return MTK_AFE_TDM_RATE_256K;
+ case 352800:
+ return MTK_AFE_TDM_RATE_352K;
+ case 384000:
+ return MTK_AFE_TDM_RATE_384K;
+ default:
+ dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
+ __func__, rate, MTK_AFE_TDM_RATE_48K);
+ }
+
+ return MTK_AFE_TDM_RATE_48K;
+}
+
+static unsigned int pcm_rate_transform(struct device *dev, unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_PCM_RATE_8K;
+ case 16000:
+ return MTK_AFE_PCM_RATE_16K;
+ case 32000:
+ return MTK_AFE_PCM_RATE_32K;
+ case 48000:
+ return MTK_AFE_PCM_RATE_48K;
+ default:
+ dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
+ __func__, rate, MTK_AFE_PCM_RATE_48K);
+ }
+
+ return MTK_AFE_PCM_RATE_48K;
+}
+
+unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev, unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_TDM_RELATCH_RATE_8K;
+ case 11025:
+ return MTK_AFE_TDM_RELATCH_RATE_11K;
+ case 12000:
+ return MTK_AFE_TDM_RELATCH_RATE_12K;
+ case 16000:
+ return MTK_AFE_TDM_RELATCH_RATE_16K;
+ case 22050:
+ return MTK_AFE_TDM_RELATCH_RATE_22K;
+ case 24000:
+ return MTK_AFE_TDM_RELATCH_RATE_24K;
+ case 32000:
+ return MTK_AFE_TDM_RELATCH_RATE_32K;
+ case 44100:
+ return MTK_AFE_TDM_RELATCH_RATE_44K;
+ case 48000:
+ return MTK_AFE_TDM_RELATCH_RATE_48K;
+ case 88200:
+ return MTK_AFE_TDM_RELATCH_RATE_88K;
+ case 96000:
+ return MTK_AFE_TDM_RELATCH_RATE_96K;
+ case 176400:
+ return MTK_AFE_TDM_RELATCH_RATE_176K;
+ case 192000:
+ return MTK_AFE_TDM_RELATCH_RATE_192K;
+ case 352800:
+ return MTK_AFE_TDM_RELATCH_RATE_352K;
+ case 384000:
+ return MTK_AFE_TDM_RELATCH_RATE_384K;
+ default:
+ dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
+ __func__, rate, MTK_AFE_TDM_RELATCH_RATE_48K);
+ }
+
+ return MTK_AFE_TDM_RELATCH_RATE_48K;
+}
+
+unsigned int mt8186_rate_transform(struct device *dev, unsigned int rate, int aud_blk)
+{
+ switch (aud_blk) {
+ case MT8186_DAI_PCM:
+ return pcm_rate_transform(dev, rate);
+ case MT8186_DAI_TDM_IN:
+ return tdm_rate_transform(dev, rate);
+ default:
+ return mt8186_general_rate_transform(dev, rate);
+ }
+}
+
+int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id, int priv_size, const void *priv_data)
+{
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ void *temp_data;
+
+ temp_data = devm_kzalloc(afe->dev,
+ priv_size,
+ GFP_KERNEL);
+ if (!temp_data)
+ return -ENOMEM;
+
+ if (priv_data)
+ memcpy(temp_data, priv_data, priv_size);
+
+ afe_priv->dai_priv[id] = temp_data;
+
+ return 0;
+}
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
new file mode 100644
index 000000000000..eb729ab00f5a
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
@@ -0,0 +1,3000 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Mediatek ALSA SoC AFE platform driver for 8186
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <sound/soc.h>
+
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-afe-fe-dai.h"
+
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-interconnection.h"
+
+static const struct snd_pcm_hardware mt8186_afe_hardware = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+ .period_bytes_min = 96,
+ .period_bytes_max = 4 * 48 * 1024,
+ .periods_min = 2,
+ .periods_max = 256,
+ .buffer_bytes_max = 4 * 48 * 1024,
+ .fifo_size = 0,
+};
+
+static int mt8186_fe_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware;
+ int ret;
+
+ memif->substream = substream;
+
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
+
+ snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
+ return ret;
+ }
+
+ /* dynamic allocate irq to memif */
+ if (memif->irq_usage < 0) {
+ int irq_id = mtk_dynamic_irq_acquire(afe);
+
+ if (irq_id != afe->irqs_size) {
+ /* link */
+ memif->irq_usage = irq_id;
+ } else {
+ dev_err(afe->dev, "%s() error: no more asys irq\n",
+ __func__);
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+static void mt8186_fe_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ int irq_id = memif->irq_usage;
+
+ memif->substream = NULL;
+ afe_priv->irq_cnt[id] = 0;
+ afe_priv->xrun_assert[id] = 0;
+
+ if (!memif->const_irq) {
+ mtk_dynamic_irq_release(afe, irq_id);
+ memif->irq_usage = -1;
+ memif->substream = NULL;
+ }
+}
+
+static int mt8186_fe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ int ret;
+
+ ret = mtk_afe_fe_hw_params(substream, params, dai);
+ if (ret)
+ return ret;
+
+ /* channel merge configuration, enable control is in UL5_IN_MUX */
+ if (id == MT8186_MEMIF_VUL3) {
+ int update_cnt = 8;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int fs_mode = mt8186_rate_transform(afe->dev, rate, id);
+
+ /* set rate, channel, update cnt, disable sgen */
+ val = fs_mode << CM1_FS_SELECT_SFT |
+ (channels - 1) << CHANNEL_MERGE0_CHNUM_SFT |
+ update_cnt << CHANNEL_MERGE0_UPDATE_CNT_SFT;
+ mask = CM1_FS_SELECT_MASK_SFT |
+ CHANNEL_MERGE0_CHNUM_MASK_SFT |
+ CHANNEL_MERGE0_UPDATE_CNT_MASK_SFT;
+ regmap_update_bits(afe->regmap, AFE_CM1_CON, mask, val);
+ }
+
+ return 0;
+}
+
+static int mt8186_fe_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ ret = mtk_afe_fe_hw_free(substream, dai);
+ if (ret) {
+ dev_err(afe->dev, "%s failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8186_fe_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime * const runtime = substream->runtime;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ int irq_id = memif->irq_usage;
+ struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id];
+ const struct mtk_base_irq_data *irq_data = irqs->irq_data;
+ unsigned int rate = runtime->rate;
+ unsigned int counter;
+ int fs;
+ int ret;
+
+ dev_dbg(afe->dev, "%s(), %s cmd %d, irq_id %d\n",
+ __func__, memif->data->name, cmd, irq_id);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ ret = mtk_memif_set_enable(afe, id);
+ if (ret) {
+ dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n",
+ __func__, id, ret);
+ return ret;
+ }
+
+ /*
+ * for small latency record
+ * ul memif need read some data before irq enable
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+ ((runtime->period_size * 1000) / rate <= 10))
+ udelay(300);
+
+ /* set irq counter */
+ if (afe_priv->irq_cnt[id] > 0)
+ counter = afe_priv->irq_cnt[id];
+ else
+ counter = runtime->period_size;
+
+ regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
+ irq_data->irq_cnt_maskbit
+ << irq_data->irq_cnt_shift,
+ counter << irq_data->irq_cnt_shift);
+
+ /* set irq fs */
+ fs = afe->irq_fs(substream, runtime->rate);
+ if (fs < 0)
+ return -EINVAL;
+
+ regmap_update_bits(afe->regmap, irq_data->irq_fs_reg,
+ irq_data->irq_fs_maskbit
+ << irq_data->irq_fs_shift,
+ fs << irq_data->irq_fs_shift);
+
+ /* enable interrupt */
+ if (runtime->stop_threshold != ~(0U))
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_en_reg,
+ 1 << irq_data->irq_en_shift,
+ 1 << irq_data->irq_en_shift);
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (afe_priv->xrun_assert[id] > 0) {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ int avail = snd_pcm_capture_avail(runtime);
+ /* alsa can trigger stop/start when occur xrun */
+ if (avail >= runtime->buffer_size)
+ dev_dbg(afe->dev, "%s(), id %d, xrun assert\n",
+ __func__, id);
+ }
+ }
+
+ ret = mtk_memif_set_disable(afe, id);
+ if (ret)
+ dev_err(afe->dev, "%s(), error, id %d, memif enable, ret %d\n",
+ __func__, id, ret);
+
+ /* disable interrupt */
+ if (runtime->stop_threshold != ~(0U))
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_en_reg,
+ 1 << irq_data->irq_en_shift,
+ 0 << irq_data->irq_en_shift);
+
+ /* clear pending IRQ */
+ regmap_write(afe->regmap, irq_data->irq_clr_reg,
+ 1 << irq_data->irq_clr_shift);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt8186_memif_fs(struct snd_pcm_substream *substream,
+ unsigned int rate)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+
+ return mt8186_rate_transform(afe->dev, rate, id);
+}
+
+static int mt8186_get_dai_fs(struct mtk_base_afe *afe,
+ int dai_id, unsigned int rate)
+{
+ return mt8186_rate_transform(afe->dev, rate, dai_id);
+}
+
+static int mt8186_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+
+ return mt8186_general_rate_transform(afe->dev, rate);
+}
+
+static int mt8186_get_memif_pbuf_size(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if ((runtime->period_size * 1000) / runtime->rate > 10)
+ return MT8186_MEMIF_PBUF_SIZE_256_BYTES;
+
+ return MT8186_MEMIF_PBUF_SIZE_32_BYTES;
+}
+
+static int mt8186_fe_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime * const runtime = substream->runtime;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ int irq_id = memif->irq_usage;
+ struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id];
+ const struct mtk_base_irq_data *irq_data = irqs->irq_data;
+ unsigned int counter = runtime->period_size;
+ int fs;
+ int ret;
+
+ ret = mtk_afe_fe_prepare(substream, dai);
+ if (ret)
+ return ret;
+
+ /* set irq counter */
+ regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
+ irq_data->irq_cnt_maskbit
+ << irq_data->irq_cnt_shift,
+ counter << irq_data->irq_cnt_shift);
+
+ /* set irq fs */
+ fs = afe->irq_fs(substream, runtime->rate);
+
+ if (fs < 0)
+ return -EINVAL;
+
+ regmap_update_bits(afe->regmap, irq_data->irq_fs_reg,
+ irq_data->irq_fs_maskbit
+ << irq_data->irq_fs_shift,
+ fs << irq_data->irq_fs_shift);
+
+ return 0;
+}
+
+/* FE DAIs */
+static const struct snd_soc_dai_ops mt8186_memif_dai_ops = {
+ .startup = mt8186_fe_startup,
+ .shutdown = mt8186_fe_shutdown,
+ .hw_params = mt8186_fe_hw_params,
+ .hw_free = mt8186_fe_hw_free,
+ .prepare = mt8186_fe_prepare,
+ .trigger = mt8186_fe_trigger,
+};
+
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_176400 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_PCM_DAI_RATES (SNDRV_PCM_RATE_8000 |\
+ SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 |\
+ SNDRV_PCM_RATE_48000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mt8186_memif_dai_driver[] = {
+ /* FE DAIs: memory intefaces to CPU */
+ {
+ .name = "DL1",
+ .id = MT8186_MEMIF_DL1,
+ .playback = {
+ .stream_name = "DL1",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL12",
+ .id = MT8186_MEMIF_DL12,
+ .playback = {
+ .stream_name = "DL12",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL2",
+ .id = MT8186_MEMIF_DL2,
+ .playback = {
+ .stream_name = "DL2",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL3",
+ .id = MT8186_MEMIF_DL3,
+ .playback = {
+ .stream_name = "DL3",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL4",
+ .id = MT8186_MEMIF_DL4,
+ .playback = {
+ .stream_name = "DL4",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL5",
+ .id = MT8186_MEMIF_DL5,
+ .playback = {
+ .stream_name = "DL5",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL6",
+ .id = MT8186_MEMIF_DL6,
+ .playback = {
+ .stream_name = "DL6",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL7",
+ .id = MT8186_MEMIF_DL7,
+ .playback = {
+ .stream_name = "DL7",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "DL8",
+ .id = MT8186_MEMIF_DL8,
+ .playback = {
+ .stream_name = "DL8",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL1",
+ .id = MT8186_MEMIF_VUL12,
+ .capture = {
+ .stream_name = "UL1",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL2",
+ .id = MT8186_MEMIF_AWB,
+ .capture = {
+ .stream_name = "UL2",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL3",
+ .id = MT8186_MEMIF_VUL2,
+ .capture = {
+ .stream_name = "UL3",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL4",
+ .id = MT8186_MEMIF_AWB2,
+ .capture = {
+ .stream_name = "UL4",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL5",
+ .id = MT8186_MEMIF_VUL3,
+ .capture = {
+ .stream_name = "UL5",
+ .channels_min = 1,
+ .channels_max = 12,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL6",
+ .id = MT8186_MEMIF_VUL4,
+ .capture = {
+ .stream_name = "UL6",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL7",
+ .id = MT8186_MEMIF_VUL5,
+ .capture = {
+ .stream_name = "UL7",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ },
+ {
+ .name = "UL8",
+ .id = MT8186_MEMIF_VUL6,
+ .capture = {
+ .stream_name = "UL8",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8186_memif_dai_ops,
+ }
+};
+
+/* kcontrol */
+static int mt8186_irq_cnt1_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+ ucontrol->value.integer.value[0] =
+ afe_priv->irq_cnt[MT8186_PRIMARY_MEMIF];
+
+ return 0;
+}
+
+static int mt8186_irq_cnt1_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int memif_num = MT8186_PRIMARY_MEMIF;
+ struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+ int irq_id = memif->irq_usage;
+ int irq_cnt = afe_priv->irq_cnt[memif_num];
+
+ dev_dbg(afe->dev, "%s(), irq_id %d, irq_cnt = %d, value = %ld\n",
+ __func__, irq_id, irq_cnt, ucontrol->value.integer.value[0]);
+
+ if (irq_cnt == ucontrol->value.integer.value[0])
+ return 0;
+
+ irq_cnt = ucontrol->value.integer.value[0];
+ afe_priv->irq_cnt[memif_num] = irq_cnt;
+
+ if (!pm_runtime_status_suspended(afe->dev) && irq_id >= 0) {
+ struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id];
+ const struct mtk_base_irq_data *irq_data = irqs->irq_data;
+
+ regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
+ irq_data->irq_cnt_maskbit
+ << irq_data->irq_cnt_shift,
+ irq_cnt << irq_data->irq_cnt_shift);
+ } else {
+ dev_dbg(afe->dev, "%s(), suspended || irq_id %d, not set\n",
+ __func__, irq_id);
+ }
+
+ return 1;
+}
+
+static int mt8186_irq_cnt2_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+ ucontrol->value.integer.value[0] =
+ afe_priv->irq_cnt[MT8186_RECORD_MEMIF];
+
+ return 0;
+}
+
+static int mt8186_irq_cnt2_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int memif_num = MT8186_RECORD_MEMIF;
+ struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+ int irq_id = memif->irq_usage;
+ int irq_cnt = afe_priv->irq_cnt[memif_num];
+
+ dev_dbg(afe->dev, "%s(), irq_id %d, irq_cnt = %d, value = %ld\n",
+ __func__, irq_id, irq_cnt, ucontrol->value.integer.value[0]);
+
+ if (irq_cnt == ucontrol->value.integer.value[0])
+ return 0;
+
+ irq_cnt = ucontrol->value.integer.value[0];
+ afe_priv->irq_cnt[memif_num] = irq_cnt;
+
+ if (!pm_runtime_status_suspended(afe->dev) && irq_id >= 0) {
+ struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id];
+ const struct mtk_base_irq_data *irq_data = irqs->irq_data;
+
+ regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
+ irq_data->irq_cnt_maskbit
+ << irq_data->irq_cnt_shift,
+ irq_cnt << irq_data->irq_cnt_shift);
+ } else {
+ dev_dbg(afe->dev, "%s(), suspended || irq_id %d, not set\n",
+ __func__, irq_id);
+ }
+
+ return 1;
+}
+
+static int mt8186_record_xrun_assert_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int xrun_assert = afe_priv->xrun_assert[MT8186_RECORD_MEMIF];
+
+ ucontrol->value.integer.value[0] = xrun_assert;
+
+ return 0;
+}
+
+static int mt8186_record_xrun_assert_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int xrun_assert = ucontrol->value.integer.value[0];
+
+ dev_dbg(afe->dev, "%s(), xrun_assert %d\n", __func__, xrun_assert);
+
+ if (xrun_assert == afe_priv->xrun_assert[MT8186_RECORD_MEMIF])
+ return 0;
+
+ afe_priv->xrun_assert[MT8186_RECORD_MEMIF] = xrun_assert;
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new mt8186_pcm_kcontrols[] = {
+ SOC_SINGLE_EXT("Audio IRQ1 CNT", SND_SOC_NOPM, 0, 0x3ffff, 0,
+ mt8186_irq_cnt1_get, mt8186_irq_cnt1_set),
+ SOC_SINGLE_EXT("Audio IRQ2 CNT", SND_SOC_NOPM, 0, 0x3ffff, 0,
+ mt8186_irq_cnt2_get, mt8186_irq_cnt2_set),
+ SOC_SINGLE_EXT("record_xrun_assert", SND_SOC_NOPM, 0, 0x1, 0,
+ mt8186_record_xrun_assert_get,
+ mt8186_record_xrun_assert_set),
+};
+
+/* dma widget & routes*/
+static const struct snd_kcontrol_new memif_ul1_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN21,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN21,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN21,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH1 Switch", AFE_CONN21_1,
+ I_TDM_IN_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul1_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN22,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN22,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN22,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4 Switch", AFE_CONN22,
+ I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH2 Switch", AFE_CONN22_1,
+ I_TDM_IN_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul1_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN9,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN9,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN9,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH3 Switch", AFE_CONN9_1,
+ I_TDM_IN_CH3, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul1_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN10,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN10,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN10,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4 Switch", AFE_CONN10,
+ I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH4 Switch", AFE_CONN10_1,
+ I_TDM_IN_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul2_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN5,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN5,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN5,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN5,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN5,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN5_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN5_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN5_1,
+ I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN5,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN5,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN5_1,
+ I_CONNSYS_I2S_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN5_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul2_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN6,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN6,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN6,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN6,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN6,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN6_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN6_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN6_1,
+ I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN6,
+ I_PCM_1_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN6,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN6_1,
+ I_CONNSYS_I2S_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN6_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul3_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN32_1,
+ I_CONNSYS_I2S_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN32,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN32,
+ I_DL2_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul3_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN33_1,
+ I_CONNSYS_I2S_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul4_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN38,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN38,
+ I_I2S0_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul4_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN39,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN39,
+ I_I2S0_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul5_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN44,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul5_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN45,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul6_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN46,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN46,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN46,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN46_1,
+ I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN46,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN46,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN46_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN46,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN46,
+ I_GAIN1_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul6_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN47,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN47,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN47,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN47_1,
+ I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN47,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN47,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN47_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN47,
+ I_PCM_1_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN47,
+ I_GAIN1_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul7_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN48,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN48,
+ I_GAIN2_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1 Switch", AFE_CONN48_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul7_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN49,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN49,
+ I_GAIN2_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2 Switch", AFE_CONN49_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul8_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN50,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul8_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN51,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH1 Switch", AFE_CONN58_1,
+ I_TDM_IN_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN58,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN58,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN58,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN58,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN58,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN58,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN58,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN58,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN58_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN58_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN58_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN58_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH2 Switch", AFE_CONN59_1,
+ I_TDM_IN_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN59,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN59,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN59,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN59,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN59,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN59,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN59,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN59,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN59_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN59_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN59_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN59_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH3 Switch", AFE_CONN60_1,
+ I_TDM_IN_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN60,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN60,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN60,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN60,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN60,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN60,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN60,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN60,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN60_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN60_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN60_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN60_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH4 Switch", AFE_CONN61_1,
+ I_TDM_IN_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN61,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN61,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN61,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN61,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN61,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN61,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN61,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN61,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN61_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN61_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN61_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN61_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch5_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH5 Switch", AFE_CONN62_1,
+ I_TDM_IN_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN62,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN62,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN62,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN62,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN62,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN62,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN62,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN62,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN62_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN62_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN62_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN62_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch6_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH6 Switch", AFE_CONN63_1,
+ I_TDM_IN_CH6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN63,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN63,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN63,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN63,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN63,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN63,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN63,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN63,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN63_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN63_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN63_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN63_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch7_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH7 Switch", AFE_CONN64_1,
+ I_TDM_IN_CH7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN64,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN64,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN64,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN64,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1v", AFE_CONN64,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN64,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN64,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN64,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN64_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN64_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN64_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN64_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch8_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("TDM_IN_CH8 Switch", AFE_CONN65_1,
+ I_TDM_IN_CH8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN65,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN65,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN65,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN65,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN65,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN65,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN65,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN65,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN65_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN65_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN65_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN65_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch9_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN66,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN66,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN66,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN66,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN66,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN66,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN66,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN66,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN66_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN66_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN66_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN66_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch10_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN67,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN67,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN67,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN67,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN67,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN67,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN67,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN67,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN67_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN67_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN67_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN67_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch11_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN68,
+ I_I2S0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1 Switch", AFE_CONN68,
+ I_I2S2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN68,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN68,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN68,
+ I_DL12_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN68,
+ I_DL12_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN68,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN68,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN68_1,
+ I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN68_1,
+ I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH1 Switch", AFE_CONN68_1,
+ I_SRC_1_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH1 Switch", AFE_CONN68_1,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new hw_cm1_ch12_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN69,
+ I_I2S0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2 Switch", AFE_CONN69,
+ I_I2S2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN69,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN69,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN69,
+ I_DL12_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN69,
+ I_DL12_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN69,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN69,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN69_1,
+ I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN69_1,
+ I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC1_OUT_CH2 Switch", AFE_CONN69_1,
+ I_SRC_1_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC2_OUT_CH2 Switch", AFE_CONN69_1,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+/* ADDA UL MUX */
+enum {
+ UL5_IN_MUX_CM1 = 0,
+ UL5_IN_MUX_NORMAL,
+ UL5_IN_MUX_MASK = 0x1,
+};
+
+static const char * const ul5_in_mux_map[] = {
+ "UL5_IN_FROM_CM1", "UL5_IN_FROM_Normal"
+};
+
+static int ul5_in_map_value[] = {
+ UL5_IN_MUX_CM1,
+ UL5_IN_MUX_NORMAL,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(ul5_in_mux_map_enum,
+ AFE_CM1_CON,
+ VUL3_BYPASS_CM_SFT,
+ VUL3_BYPASS_CM_MASK,
+ ul5_in_mux_map,
+ ul5_in_map_value);
+
+static const struct snd_kcontrol_new ul5_in_mux_control =
+ SOC_DAPM_ENUM("UL5_IN_MUX Select", ul5_in_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mt8186_memif_widgets[] = {
+ /* inter-connections */
+ SND_SOC_DAPM_MIXER("UL1_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch1_mix, ARRAY_SIZE(memif_ul1_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL1_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch2_mix, ARRAY_SIZE(memif_ul1_ch2_mix)),
+ SND_SOC_DAPM_MIXER("UL1_CH3", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch3_mix, ARRAY_SIZE(memif_ul1_ch3_mix)),
+ SND_SOC_DAPM_MIXER("UL1_CH4", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch4_mix, ARRAY_SIZE(memif_ul1_ch4_mix)),
+
+ SND_SOC_DAPM_MIXER("UL2_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul2_ch1_mix, ARRAY_SIZE(memif_ul2_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL2_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul2_ch2_mix, ARRAY_SIZE(memif_ul2_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL3_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul3_ch1_mix, ARRAY_SIZE(memif_ul3_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL3_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul3_ch2_mix, ARRAY_SIZE(memif_ul3_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL4_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul4_ch1_mix, ARRAY_SIZE(memif_ul4_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL4_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul4_ch2_mix, ARRAY_SIZE(memif_ul4_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL5_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul5_ch1_mix, ARRAY_SIZE(memif_ul5_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL5_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul5_ch2_mix, ARRAY_SIZE(memif_ul5_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL6_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul6_ch1_mix, ARRAY_SIZE(memif_ul6_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL6_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul6_ch2_mix, ARRAY_SIZE(memif_ul6_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL7_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul7_ch1_mix, ARRAY_SIZE(memif_ul7_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL7_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul7_ch2_mix, ARRAY_SIZE(memif_ul7_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL8_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul8_ch1_mix, ARRAY_SIZE(memif_ul8_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL8_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul8_ch2_mix, ARRAY_SIZE(memif_ul8_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL5_2CH", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("HW_CM1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* CM1 en*/
+ SND_SOC_DAPM_SUPPLY_S("CM1_EN", 0, AFE_CM1_CON,
+ CHANNEL_MERGE0_EN_SFT, 0, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("HW_CM1_CH1", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch1_mix, ARRAY_SIZE(hw_cm1_ch1_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH2", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch2_mix, ARRAY_SIZE(hw_cm1_ch2_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH3", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch3_mix, ARRAY_SIZE(hw_cm1_ch3_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH4", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch4_mix, ARRAY_SIZE(hw_cm1_ch4_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH5", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch5_mix, ARRAY_SIZE(hw_cm1_ch5_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH6", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch6_mix, ARRAY_SIZE(hw_cm1_ch6_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH7", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch7_mix, ARRAY_SIZE(hw_cm1_ch7_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH8", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch8_mix, ARRAY_SIZE(hw_cm1_ch8_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH9", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch9_mix, ARRAY_SIZE(hw_cm1_ch9_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH10", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch10_mix, ARRAY_SIZE(hw_cm1_ch10_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH11", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch11_mix, ARRAY_SIZE(hw_cm1_ch11_mix)),
+ SND_SOC_DAPM_MIXER("HW_CM1_CH12", SND_SOC_NOPM, 0, 0,
+ hw_cm1_ch12_mix, ARRAY_SIZE(hw_cm1_ch12_mix)),
+
+ SND_SOC_DAPM_MUX("UL5_IN_MUX", SND_SOC_NOPM, 0, 0,
+ &ul5_in_mux_control),
+
+ SND_SOC_DAPM_INPUT("UL1_VIRTUAL_INPUT"),
+ SND_SOC_DAPM_INPUT("UL2_VIRTUAL_INPUT"),
+ SND_SOC_DAPM_INPUT("UL3_VIRTUAL_INPUT"),
+ SND_SOC_DAPM_INPUT("UL4_VIRTUAL_INPUT"),
+ SND_SOC_DAPM_INPUT("UL5_VIRTUAL_INPUT"),
+ SND_SOC_DAPM_INPUT("UL6_VIRTUAL_INPUT"),
+};
+
+static const struct snd_soc_dapm_route mt8186_memif_routes[] = {
+ {"UL1", NULL, "UL1_CH1"},
+ {"UL1", NULL, "UL1_CH2"},
+ {"UL1", NULL, "UL1_CH3"},
+ {"UL1", NULL, "UL1_CH4"},
+ {"UL1_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH1", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH2", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH3", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH3", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH4", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH4", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL1_CH1", "TDM_IN_CH1 Switch", "TDM IN"},
+ {"UL1_CH2", "TDM_IN_CH2 Switch", "TDM IN"},
+ {"UL1_CH3", "TDM_IN_CH3 Switch", "TDM IN"},
+ {"UL1_CH4", "TDM_IN_CH4 Switch", "TDM IN"},
+
+ {"UL2", NULL, "UL2_CH1"},
+ {"UL2", NULL, "UL2_CH2"},
+
+ /* cannot connect FE to FE directly */
+ {"UL2_CH1", "DL1_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL1_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL12_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL12_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL6_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL6_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL2_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL2_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL3_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL3_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL4_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL4_CH2 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH1", "DL5_CH1 Switch", "Hostless_UL2 UL"},
+ {"UL2_CH2", "DL5_CH2 Switch", "Hostless_UL2 UL"},
+
+ {"Hostless_UL2 UL", NULL, "UL2_VIRTUAL_INPUT"},
+
+ {"UL2_CH1", "I2S0_CH1 Switch", "I2S0"},
+ {"UL2_CH2", "I2S0_CH2 Switch", "I2S0"},
+ {"UL2_CH1", "I2S2_CH1 Switch", "I2S2"},
+ {"UL2_CH2", "I2S2_CH2 Switch", "I2S2"},
+
+ {"UL2_CH1", "PCM_1_CAP_CH1 Switch", "PCM 1 Capture"},
+ {"UL2_CH2", "PCM_1_CAP_CH2 Switch", "PCM 1 Capture"},
+
+ {"UL2_CH1", "CONNSYS_I2S_CH1 Switch", "Connsys I2S"},
+ {"UL2_CH2", "CONNSYS_I2S_CH2 Switch", "Connsys I2S"},
+
+ {"UL2_CH1", "SRC_1_OUT_CH1 Switch", "HW_SRC_1_Out"},
+ {"UL2_CH2", "SRC_1_OUT_CH2 Switch", "HW_SRC_1_Out"},
+
+ {"UL3", NULL, "UL3_CH1"},
+ {"UL3", NULL, "UL3_CH2"},
+ {"UL3_CH1", "CONNSYS_I2S_CH1 Switch", "Connsys I2S"},
+ {"UL3_CH2", "CONNSYS_I2S_CH2 Switch", "Connsys I2S"},
+
+ {"UL4", NULL, "UL4_CH1"},
+ {"UL4", NULL, "UL4_CH2"},
+ {"UL4_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL4_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL4_CH1", "I2S0_CH1 Switch", "I2S0"},
+ {"UL4_CH2", "I2S0_CH2 Switch", "I2S0"},
+
+ {"UL5", NULL, "UL5_IN_MUX"},
+ {"UL5_IN_MUX", "UL5_IN_FROM_Normal", "UL5_2CH"},
+ {"UL5_IN_MUX", "UL5_IN_FROM_CM1", "HW_CM1"},
+ {"UL5_2CH", NULL, "UL5_CH1"},
+ {"UL5_2CH", NULL, "UL5_CH2"},
+ {"UL5_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL5_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"HW_CM1", NULL, "CM1_EN"},
+ {"HW_CM1", NULL, "HW_CM1_CH1"},
+ {"HW_CM1", NULL, "HW_CM1_CH2"},
+ {"HW_CM1", NULL, "HW_CM1_CH3"},
+ {"HW_CM1", NULL, "HW_CM1_CH4"},
+ {"HW_CM1", NULL, "HW_CM1_CH5"},
+ {"HW_CM1", NULL, "HW_CM1_CH6"},
+ {"HW_CM1", NULL, "HW_CM1_CH7"},
+ {"HW_CM1", NULL, "HW_CM1_CH8"},
+ {"HW_CM1", NULL, "HW_CM1_CH9"},
+ {"HW_CM1", NULL, "HW_CM1_CH10"},
+ {"HW_CM1", NULL, "HW_CM1_CH11"},
+ {"HW_CM1", NULL, "HW_CM1_CH12"},
+ {"HW_CM1_CH1", "TDM_IN_CH1 Switch", "TDM IN"},
+ {"HW_CM1_CH2", "TDM_IN_CH2 Switch", "TDM IN"},
+ {"HW_CM1_CH3", "TDM_IN_CH3 Switch", "TDM IN"},
+ {"HW_CM1_CH4", "TDM_IN_CH4 Switch", "TDM IN"},
+ {"HW_CM1_CH5", "TDM_IN_CH5 Switch", "TDM IN"},
+ {"HW_CM1_CH6", "TDM_IN_CH6 Switch", "TDM IN"},
+ {"HW_CM1_CH7", "TDM_IN_CH7 Switch", "TDM IN"},
+ {"HW_CM1_CH8", "TDM_IN_CH8 Switch", "TDM IN"},
+ {"HW_CM1_CH9", "DL1_CH1 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH10", "DL1_CH2 Switch", "Hostless_UL5 UL"},
+
+ {"HW_CM1_CH3", "DL1_CH1 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH4", "DL1_CH2 Switch", "Hostless_UL5 UL"},
+
+ {"HW_CM1_CH3", "DL3_CH1 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH4", "DL3_CH2 Switch", "Hostless_UL5 UL"},
+
+ {"HW_CM1_CH5", "HW_SRC1_OUT_CH1 Switch", "HW_SRC_1_Out"},
+ {"HW_CM1_CH6", "HW_SRC1_OUT_CH2 Switch", "HW_SRC_1_Out"},
+
+ {"HW_CM1_CH9", "DL12_CH1 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH10", "DL12_CH2 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH11", "DL12_CH3 Switch", "Hostless_UL5 UL"},
+ {"HW_CM1_CH12", "DL12_CH4 Switch", "Hostless_UL5 UL"},
+
+ {"Hostless_UL5 UL", NULL, "UL5_VIRTUAL_INPUT"},
+
+ {"UL6", NULL, "UL6_CH1"},
+ {"UL6", NULL, "UL6_CH2"},
+
+ {"UL6_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL6_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL6_CH1", "DL1_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL1_CH2 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH1", "DL2_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL2_CH2 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH1", "DL12_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL12_CH2 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH1", "DL6_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL6_CH2 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH1", "DL3_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL3_CH2 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH1", "DL4_CH1 Switch", "Hostless_UL6 UL"},
+ {"UL6_CH2", "DL4_CH2 Switch", "Hostless_UL6 UL"},
+ {"Hostless_UL6 UL", NULL, "UL6_VIRTUAL_INPUT"},
+ {"UL6_CH1", "PCM_1_CAP_CH1 Switch", "PCM 1 Capture"},
+ {"UL6_CH2", "PCM_1_CAP_CH2 Switch", "PCM 1 Capture"},
+ {"UL6_CH1", "GAIN1_OUT_CH1 Switch", "HW Gain 1 Out"},
+ {"UL6_CH2", "GAIN1_OUT_CH2 Switch", "HW Gain 1 Out"},
+
+ {"UL7", NULL, "UL7_CH1"},
+ {"UL7", NULL, "UL7_CH2"},
+ {"UL7_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL7_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+ {"UL7_CH1", "HW_GAIN2_OUT_CH1 Switch", "HW Gain 2 Out"},
+ {"UL7_CH2", "HW_GAIN2_OUT_CH2 Switch", "HW Gain 2 Out"},
+ {"UL7_CH1", "HW_SRC_2_OUT_CH1 Switch", "HW_SRC_2_Out"},
+ {"UL7_CH2", "HW_SRC_2_OUT_CH2 Switch", "HW_SRC_2_Out"},
+
+ {"UL8", NULL, "UL8_CH1"},
+ {"UL8", NULL, "UL8_CH2"},
+ {"UL8_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"UL8_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+
+ {"HW_GAIN2_IN_CH1", "ADDA_UL_CH1 Switch", "ADDA_UL_Mux"},
+ {"HW_GAIN2_IN_CH2", "ADDA_UL_CH2 Switch", "ADDA_UL_Mux"},
+};
+
+static const struct mtk_base_memif_data memif_data[MT8186_MEMIF_NUM] = {
+ [MT8186_MEMIF_DL1] = {
+ .name = "DL1",
+ .id = MT8186_MEMIF_DL1,
+ .reg_ofs_base = AFE_DL1_BASE,
+ .reg_ofs_cur = AFE_DL1_CUR,
+ .reg_ofs_end = AFE_DL1_END,
+ .reg_ofs_base_msb = AFE_DL1_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL1_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL1_END_MSB,
+ .fs_reg = AFE_DL1_CON0,
+ .fs_shift = DL1_MODE_SFT,
+ .fs_maskbit = DL1_MODE_MASK,
+ .mono_reg = AFE_DL1_CON0,
+ .mono_shift = DL1_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL1_ON_SFT,
+ .hd_reg = AFE_DL1_CON0,
+ .hd_shift = DL1_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL1_CON0,
+ .hd_align_mshift = DL1_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL1_CON0,
+ .pbuf_mask = DL1_PBUF_SIZE_MASK,
+ .pbuf_shift = DL1_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL1_CON0,
+ .minlen_mask = DL1_MINLEN_MASK,
+ .minlen_shift = DL1_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL12] = {
+ .name = "DL12",
+ .id = MT8186_MEMIF_DL12,
+ .reg_ofs_base = AFE_DL12_BASE,
+ .reg_ofs_cur = AFE_DL12_CUR,
+ .reg_ofs_end = AFE_DL12_END,
+ .reg_ofs_base_msb = AFE_DL12_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL12_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL12_END_MSB,
+ .fs_reg = AFE_DL12_CON0,
+ .fs_shift = DL12_MODE_SFT,
+ .fs_maskbit = DL12_MODE_MASK,
+ .mono_reg = AFE_DL12_CON0,
+ .mono_shift = DL12_MONO_SFT,
+ .quad_ch_reg = AFE_DL12_CON0,
+ .quad_ch_mask = DL12_4CH_EN_MASK,
+ .quad_ch_shift = DL12_4CH_EN_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL12_ON_SFT,
+ .hd_reg = AFE_DL12_CON0,
+ .hd_shift = DL12_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL12_CON0,
+ .hd_align_mshift = DL12_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL12_CON0,
+ .pbuf_mask = DL12_PBUF_SIZE_MASK,
+ .pbuf_shift = DL12_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL12_CON0,
+ .minlen_mask = DL12_MINLEN_MASK,
+ .minlen_shift = DL12_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL2] = {
+ .name = "DL2",
+ .id = MT8186_MEMIF_DL2,
+ .reg_ofs_base = AFE_DL2_BASE,
+ .reg_ofs_cur = AFE_DL2_CUR,
+ .reg_ofs_end = AFE_DL2_END,
+ .reg_ofs_base_msb = AFE_DL2_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL2_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL2_END_MSB,
+ .fs_reg = AFE_DL2_CON0,
+ .fs_shift = DL2_MODE_SFT,
+ .fs_maskbit = DL2_MODE_MASK,
+ .mono_reg = AFE_DL2_CON0,
+ .mono_shift = DL2_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL2_ON_SFT,
+ .hd_reg = AFE_DL2_CON0,
+ .hd_shift = DL2_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL2_CON0,
+ .hd_align_mshift = DL2_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL2_CON0,
+ .pbuf_mask = DL2_PBUF_SIZE_MASK,
+ .pbuf_shift = DL2_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL2_CON0,
+ .minlen_mask = DL2_MINLEN_MASK,
+ .minlen_shift = DL2_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL3] = {
+ .name = "DL3",
+ .id = MT8186_MEMIF_DL3,
+ .reg_ofs_base = AFE_DL3_BASE,
+ .reg_ofs_cur = AFE_DL3_CUR,
+ .reg_ofs_end = AFE_DL3_END,
+ .reg_ofs_base_msb = AFE_DL3_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL3_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL3_END_MSB,
+ .fs_reg = AFE_DL3_CON0,
+ .fs_shift = DL3_MODE_SFT,
+ .fs_maskbit = DL3_MODE_MASK,
+ .mono_reg = AFE_DL3_CON0,
+ .mono_shift = DL3_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL3_ON_SFT,
+ .hd_reg = AFE_DL3_CON0,
+ .hd_shift = DL3_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL3_CON0,
+ .hd_align_mshift = DL3_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL3_CON0,
+ .pbuf_mask = DL3_PBUF_SIZE_MASK,
+ .pbuf_shift = DL3_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL3_CON0,
+ .minlen_mask = DL3_MINLEN_MASK,
+ .minlen_shift = DL3_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL4] = {
+ .name = "DL4",
+ .id = MT8186_MEMIF_DL4,
+ .reg_ofs_base = AFE_DL4_BASE,
+ .reg_ofs_cur = AFE_DL4_CUR,
+ .reg_ofs_end = AFE_DL4_END,
+ .reg_ofs_base_msb = AFE_DL4_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL4_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL4_END_MSB,
+ .fs_reg = AFE_DL4_CON0,
+ .fs_shift = DL4_MODE_SFT,
+ .fs_maskbit = DL4_MODE_MASK,
+ .mono_reg = AFE_DL4_CON0,
+ .mono_shift = DL4_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL4_ON_SFT,
+ .hd_reg = AFE_DL4_CON0,
+ .hd_shift = DL4_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL4_CON0,
+ .hd_align_mshift = DL4_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL4_CON0,
+ .pbuf_mask = DL4_PBUF_SIZE_MASK,
+ .pbuf_shift = DL4_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL4_CON0,
+ .minlen_mask = DL4_MINLEN_MASK,
+ .minlen_shift = DL4_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL5] = {
+ .name = "DL5",
+ .id = MT8186_MEMIF_DL5,
+ .reg_ofs_base = AFE_DL5_BASE,
+ .reg_ofs_cur = AFE_DL5_CUR,
+ .reg_ofs_end = AFE_DL5_END,
+ .reg_ofs_base_msb = AFE_DL5_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL5_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL5_END_MSB,
+ .fs_reg = AFE_DL5_CON0,
+ .fs_shift = DL5_MODE_SFT,
+ .fs_maskbit = DL5_MODE_MASK,
+ .mono_reg = AFE_DL5_CON0,
+ .mono_shift = DL5_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL5_ON_SFT,
+ .hd_reg = AFE_DL5_CON0,
+ .hd_shift = DL5_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL5_CON0,
+ .hd_align_mshift = DL5_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL5_CON0,
+ .pbuf_mask = DL5_PBUF_SIZE_MASK,
+ .pbuf_shift = DL5_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL5_CON0,
+ .minlen_mask = DL5_MINLEN_MASK,
+ .minlen_shift = DL5_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL6] = {
+ .name = "DL6",
+ .id = MT8186_MEMIF_DL6,
+ .reg_ofs_base = AFE_DL6_BASE,
+ .reg_ofs_cur = AFE_DL6_CUR,
+ .reg_ofs_end = AFE_DL6_END,
+ .reg_ofs_base_msb = AFE_DL6_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL6_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL6_END_MSB,
+ .fs_reg = AFE_DL6_CON0,
+ .fs_shift = DL6_MODE_SFT,
+ .fs_maskbit = DL6_MODE_MASK,
+ .mono_reg = AFE_DL6_CON0,
+ .mono_shift = DL6_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL6_ON_SFT,
+ .hd_reg = AFE_DL6_CON0,
+ .hd_shift = DL6_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL6_CON0,
+ .hd_align_mshift = DL6_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL6_CON0,
+ .pbuf_mask = DL6_PBUF_SIZE_MASK,
+ .pbuf_shift = DL6_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL6_CON0,
+ .minlen_mask = DL6_MINLEN_MASK,
+ .minlen_shift = DL6_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL7] = {
+ .name = "DL7",
+ .id = MT8186_MEMIF_DL7,
+ .reg_ofs_base = AFE_DL7_BASE,
+ .reg_ofs_cur = AFE_DL7_CUR,
+ .reg_ofs_end = AFE_DL7_END,
+ .reg_ofs_base_msb = AFE_DL7_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL7_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL7_END_MSB,
+ .fs_reg = AFE_DL7_CON0,
+ .fs_shift = DL7_MODE_SFT,
+ .fs_maskbit = DL7_MODE_MASK,
+ .mono_reg = AFE_DL7_CON0,
+ .mono_shift = DL7_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL7_ON_SFT,
+ .hd_reg = AFE_DL7_CON0,
+ .hd_shift = DL7_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL7_CON0,
+ .hd_align_mshift = DL7_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL7_CON0,
+ .pbuf_mask = DL7_PBUF_SIZE_MASK,
+ .pbuf_shift = DL7_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL7_CON0,
+ .minlen_mask = DL7_MINLEN_MASK,
+ .minlen_shift = DL7_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_DL8] = {
+ .name = "DL8",
+ .id = MT8186_MEMIF_DL8,
+ .reg_ofs_base = AFE_DL8_BASE,
+ .reg_ofs_cur = AFE_DL8_CUR,
+ .reg_ofs_end = AFE_DL8_END,
+ .reg_ofs_base_msb = AFE_DL8_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_DL8_CUR_MSB,
+ .reg_ofs_end_msb = AFE_DL8_END_MSB,
+ .fs_reg = AFE_DL8_CON0,
+ .fs_shift = DL8_MODE_SFT,
+ .fs_maskbit = DL8_MODE_MASK,
+ .mono_reg = AFE_DL8_CON0,
+ .mono_shift = DL8_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = DL8_ON_SFT,
+ .hd_reg = AFE_DL8_CON0,
+ .hd_shift = DL8_HD_MODE_SFT,
+ .hd_align_reg = AFE_DL8_CON0,
+ .hd_align_mshift = DL8_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .pbuf_reg = AFE_DL8_CON0,
+ .pbuf_mask = DL8_PBUF_SIZE_MASK,
+ .pbuf_shift = DL8_PBUF_SIZE_SFT,
+ .minlen_reg = AFE_DL8_CON0,
+ .minlen_mask = DL8_MINLEN_MASK,
+ .minlen_shift = DL8_MINLEN_SFT,
+ },
+ [MT8186_MEMIF_VUL12] = {
+ .name = "VUL12",
+ .id = MT8186_MEMIF_VUL12,
+ .reg_ofs_base = AFE_VUL12_BASE,
+ .reg_ofs_cur = AFE_VUL12_CUR,
+ .reg_ofs_end = AFE_VUL12_END,
+ .reg_ofs_base_msb = AFE_VUL12_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL12_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL12_END_MSB,
+ .fs_reg = AFE_VUL12_CON0,
+ .fs_shift = VUL12_MODE_SFT,
+ .fs_maskbit = VUL12_MODE_MASK,
+ .mono_reg = AFE_VUL12_CON0,
+ .mono_shift = VUL12_MONO_SFT,
+ .quad_ch_reg = AFE_VUL12_CON0,
+ .quad_ch_mask = VUL12_4CH_EN_MASK,
+ .quad_ch_shift = VUL12_4CH_EN_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL12_ON_SFT,
+ .hd_reg = AFE_VUL12_CON0,
+ .hd_shift = VUL12_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL12_CON0,
+ .hd_align_mshift = VUL12_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_VUL2] = {
+ .name = "VUL2",
+ .id = MT8186_MEMIF_VUL2,
+ .reg_ofs_base = AFE_VUL2_BASE,
+ .reg_ofs_cur = AFE_VUL2_CUR,
+ .reg_ofs_end = AFE_VUL2_END,
+ .reg_ofs_base_msb = AFE_VUL2_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL2_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL2_END_MSB,
+ .fs_reg = AFE_VUL2_CON0,
+ .fs_shift = VUL2_MODE_SFT,
+ .fs_maskbit = VUL2_MODE_MASK,
+ .mono_reg = AFE_VUL2_CON0,
+ .mono_shift = VUL2_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL2_ON_SFT,
+ .hd_reg = AFE_VUL2_CON0,
+ .hd_shift = VUL2_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL2_CON0,
+ .hd_align_mshift = VUL2_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_AWB] = {
+ .name = "AWB",
+ .id = MT8186_MEMIF_AWB,
+ .reg_ofs_base = AFE_AWB_BASE,
+ .reg_ofs_cur = AFE_AWB_CUR,
+ .reg_ofs_end = AFE_AWB_END,
+ .reg_ofs_base_msb = AFE_AWB_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_AWB_CUR_MSB,
+ .reg_ofs_end_msb = AFE_AWB_END_MSB,
+ .fs_reg = AFE_AWB_CON0,
+ .fs_shift = AWB_MODE_SFT,
+ .fs_maskbit = AWB_MODE_MASK,
+ .mono_reg = AFE_AWB_CON0,
+ .mono_shift = AWB_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = AWB_ON_SFT,
+ .hd_reg = AFE_AWB_CON0,
+ .hd_shift = AWB_HD_MODE_SFT,
+ .hd_align_reg = AFE_AWB_CON0,
+ .hd_align_mshift = AWB_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_AWB2] = {
+ .name = "AWB2",
+ .id = MT8186_MEMIF_AWB2,
+ .reg_ofs_base = AFE_AWB2_BASE,
+ .reg_ofs_cur = AFE_AWB2_CUR,
+ .reg_ofs_end = AFE_AWB2_END,
+ .reg_ofs_base_msb = AFE_AWB2_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_AWB2_CUR_MSB,
+ .reg_ofs_end_msb = AFE_AWB2_END_MSB,
+ .fs_reg = AFE_AWB2_CON0,
+ .fs_shift = AWB2_MODE_SFT,
+ .fs_maskbit = AWB2_MODE_MASK,
+ .mono_reg = AFE_AWB2_CON0,
+ .mono_shift = AWB2_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = AWB2_ON_SFT,
+ .hd_reg = AFE_AWB2_CON0,
+ .hd_shift = AWB2_HD_MODE_SFT,
+ .hd_align_reg = AFE_AWB2_CON0,
+ .hd_align_mshift = AWB2_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_VUL3] = {
+ .name = "VUL3",
+ .id = MT8186_MEMIF_VUL3,
+ .reg_ofs_base = AFE_VUL3_BASE,
+ .reg_ofs_cur = AFE_VUL3_CUR,
+ .reg_ofs_end = AFE_VUL3_END,
+ .reg_ofs_base_msb = AFE_VUL3_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL3_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL3_END_MSB,
+ .fs_reg = AFE_VUL3_CON0,
+ .fs_shift = VUL3_MODE_SFT,
+ .fs_maskbit = VUL3_MODE_MASK,
+ .mono_reg = AFE_VUL3_CON0,
+ .mono_shift = VUL3_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL3_ON_SFT,
+ .hd_reg = AFE_VUL3_CON0,
+ .hd_shift = VUL3_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL3_CON0,
+ .hd_align_mshift = VUL3_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_VUL4] = {
+ .name = "VUL4",
+ .id = MT8186_MEMIF_VUL4,
+ .reg_ofs_base = AFE_VUL4_BASE,
+ .reg_ofs_cur = AFE_VUL4_CUR,
+ .reg_ofs_end = AFE_VUL4_END,
+ .reg_ofs_base_msb = AFE_VUL4_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL4_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL4_END_MSB,
+ .fs_reg = AFE_VUL4_CON0,
+ .fs_shift = VUL4_MODE_SFT,
+ .fs_maskbit = VUL4_MODE_MASK,
+ .mono_reg = AFE_VUL4_CON0,
+ .mono_shift = VUL4_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL4_ON_SFT,
+ .hd_reg = AFE_VUL4_CON0,
+ .hd_shift = VUL4_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL4_CON0,
+ .hd_align_mshift = VUL4_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_VUL5] = {
+ .name = "VUL5",
+ .id = MT8186_MEMIF_VUL5,
+ .reg_ofs_base = AFE_VUL5_BASE,
+ .reg_ofs_cur = AFE_VUL5_CUR,
+ .reg_ofs_end = AFE_VUL5_END,
+ .reg_ofs_base_msb = AFE_VUL5_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL5_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL5_END_MSB,
+ .fs_reg = AFE_VUL5_CON0,
+ .fs_shift = VUL5_MODE_SFT,
+ .fs_maskbit = VUL5_MODE_MASK,
+ .mono_reg = AFE_VUL5_CON0,
+ .mono_shift = VUL5_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL5_ON_SFT,
+ .hd_reg = AFE_VUL5_CON0,
+ .hd_shift = VUL5_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL5_CON0,
+ .hd_align_mshift = VUL5_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+ [MT8186_MEMIF_VUL6] = {
+ .name = "VUL6",
+ .id = MT8186_MEMIF_VUL6,
+ .reg_ofs_base = AFE_VUL6_BASE,
+ .reg_ofs_cur = AFE_VUL6_CUR,
+ .reg_ofs_end = AFE_VUL6_END,
+ .reg_ofs_base_msb = AFE_VUL6_BASE_MSB,
+ .reg_ofs_cur_msb = AFE_VUL6_CUR_MSB,
+ .reg_ofs_end_msb = AFE_VUL6_END_MSB,
+ .fs_reg = AFE_VUL6_CON0,
+ .fs_shift = VUL6_MODE_SFT,
+ .fs_maskbit = VUL6_MODE_MASK,
+ .mono_reg = AFE_VUL6_CON0,
+ .mono_shift = VUL6_MONO_SFT,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = VUL6_ON_SFT,
+ .hd_reg = AFE_VUL6_CON0,
+ .hd_shift = VUL6_HD_MODE_SFT,
+ .hd_align_reg = AFE_VUL6_CON0,
+ .hd_align_mshift = VUL6_HALIGN_SFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ },
+};
+
+static const struct mtk_base_irq_data irq_data[MT8186_IRQ_NUM] = {
+ [MT8186_IRQ_0] = {
+ .id = MT8186_IRQ_0,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT0,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ0_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ0_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ0_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ0_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_1] = {
+ .id = MT8186_IRQ_1,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT1,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ1_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ1_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ1_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ1_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_2] = {
+ .id = MT8186_IRQ_2,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT2,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ2_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ2_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ2_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ2_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_3] = {
+ .id = MT8186_IRQ_3,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT3,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ3_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ3_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ3_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ3_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_4] = {
+ .id = MT8186_IRQ_4,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT4,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ4_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ4_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ4_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ4_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_5] = {
+ .id = MT8186_IRQ_5,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT5,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ5_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ5_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ5_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ5_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_6] = {
+ .id = MT8186_IRQ_6,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT6,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ6_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ6_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ6_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ6_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_7] = {
+ .id = MT8186_IRQ_7,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT7,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON1,
+ .irq_fs_shift = IRQ7_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ7_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ7_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ7_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_8] = {
+ .id = MT8186_IRQ_8,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT8,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ8_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ8_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ8_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ8_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_9] = {
+ .id = MT8186_IRQ_9,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT9,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ9_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ9_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ9_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ9_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_10] = {
+ .id = MT8186_IRQ_10,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT10,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ10_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ10_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ10_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ10_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_11] = {
+ .id = MT8186_IRQ_11,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT11,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ11_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ11_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ11_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ11_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_12] = {
+ .id = MT8186_IRQ_12,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT12,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ12_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ12_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ12_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ12_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_13] = {
+ .id = MT8186_IRQ_13,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT13,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ13_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ13_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ13_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ13_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_14] = {
+ .id = MT8186_IRQ_14,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT14,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ14_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ14_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ14_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ14_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_15] = {
+ .id = MT8186_IRQ_15,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT15,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON2,
+ .irq_fs_shift = IRQ15_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ15_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ15_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ15_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_16] = {
+ .id = MT8186_IRQ_16,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT16,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ16_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ16_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ16_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ16_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_17] = {
+ .id = MT8186_IRQ_17,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT17,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ17_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ17_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ17_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ17_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_18] = {
+ .id = MT8186_IRQ_18,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT18,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ18_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ18_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ18_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ18_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_19] = {
+ .id = MT8186_IRQ_19,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT19,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ19_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ19_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ19_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ19_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_20] = {
+ .id = MT8186_IRQ_20,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT20,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ20_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ20_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ20_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ20_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_21] = {
+ .id = MT8186_IRQ_21,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT21,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ21_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ21_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ21_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ21_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_22] = {
+ .id = MT8186_IRQ_22,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT22,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ22_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ22_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ22_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ22_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_23] = {
+ .id = MT8186_IRQ_23,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT23,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON3,
+ .irq_fs_shift = IRQ23_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ23_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ23_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ23_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_24] = {
+ .id = MT8186_IRQ_24,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT24,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON4,
+ .irq_fs_shift = IRQ24_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ24_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ24_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ24_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_25] = {
+ .id = MT8186_IRQ_25,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT25,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON4,
+ .irq_fs_shift = IRQ25_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ25_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ25_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ25_MCU_CLR_SFT,
+ },
+ [MT8186_IRQ_26] = {
+ .id = MT8186_IRQ_26,
+ .irq_cnt_reg = AFE_IRQ_MCU_CNT26,
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
+ .irq_fs_reg = AFE_IRQ_MCU_CON4,
+ .irq_fs_shift = IRQ26_MCU_MODE_SFT,
+ .irq_fs_maskbit = IRQ26_MCU_MODE_MASK,
+ .irq_en_reg = AFE_IRQ_MCU_CON0,
+ .irq_en_shift = IRQ26_MCU_ON_SFT,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = IRQ26_MCU_CLR_SFT,
+ },
+};
+
+static const int memif_irq_usage[MT8186_MEMIF_NUM] = {
+ /* TODO: verify each memif & irq */
+ [MT8186_MEMIF_DL1] = MT8186_IRQ_0,
+ [MT8186_MEMIF_DL2] = MT8186_IRQ_1,
+ [MT8186_MEMIF_DL3] = MT8186_IRQ_2,
+ [MT8186_MEMIF_DL4] = MT8186_IRQ_3,
+ [MT8186_MEMIF_DL5] = MT8186_IRQ_4,
+ [MT8186_MEMIF_DL6] = MT8186_IRQ_5,
+ [MT8186_MEMIF_DL7] = MT8186_IRQ_6,
+ [MT8186_MEMIF_DL8] = MT8186_IRQ_7,
+ [MT8186_MEMIF_DL12] = MT8186_IRQ_9,
+ [MT8186_MEMIF_VUL12] = MT8186_IRQ_10,
+ [MT8186_MEMIF_VUL2] = MT8186_IRQ_11,
+ [MT8186_MEMIF_AWB] = MT8186_IRQ_12,
+ [MT8186_MEMIF_AWB2] = MT8186_IRQ_13,
+ [MT8186_MEMIF_VUL3] = MT8186_IRQ_14,
+ [MT8186_MEMIF_VUL4] = MT8186_IRQ_15,
+ [MT8186_MEMIF_VUL5] = MT8186_IRQ_16,
+ [MT8186_MEMIF_VUL6] = MT8186_IRQ_17,
+};
+
+static bool mt8186_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /* these auto-gen reg has read-only bit, so put it as volatile */
+ /* volatile reg cannot be cached, so cannot be set when power off */
+ switch (reg) {
+ case AUDIO_TOP_CON0: /* reg bit controlled by CCF */
+ case AUDIO_TOP_CON1: /* reg bit controlled by CCF */
+ case AUDIO_TOP_CON2:
+ case AUDIO_TOP_CON3:
+ case AFE_DL1_CUR_MSB:
+ case AFE_DL1_CUR:
+ case AFE_DL1_END:
+ case AFE_DL2_CUR_MSB:
+ case AFE_DL2_CUR:
+ case AFE_DL2_END:
+ case AFE_DL3_CUR_MSB:
+ case AFE_DL3_CUR:
+ case AFE_DL3_END:
+ case AFE_DL4_CUR_MSB:
+ case AFE_DL4_CUR:
+ case AFE_DL4_END:
+ case AFE_DL12_CUR_MSB:
+ case AFE_DL12_CUR:
+ case AFE_DL12_END:
+ case AFE_ADDA_SRC_DEBUG_MON0:
+ case AFE_ADDA_SRC_DEBUG_MON1:
+ case AFE_ADDA_UL_SRC_MON0:
+ case AFE_ADDA_UL_SRC_MON1:
+ case AFE_SECURE_CON0:
+ case AFE_SRAM_BOUND:
+ case AFE_SECURE_CON1:
+ case AFE_VUL_CUR_MSB:
+ case AFE_VUL_CUR:
+ case AFE_VUL_END:
+ case AFE_SIDETONE_MON:
+ case AFE_SIDETONE_CON0:
+ case AFE_SIDETONE_COEFF:
+ case AFE_VUL2_CUR_MSB:
+ case AFE_VUL2_CUR:
+ case AFE_VUL2_END:
+ case AFE_VUL3_CUR_MSB:
+ case AFE_VUL3_CUR:
+ case AFE_VUL3_END:
+ case AFE_I2S_MON:
+ case AFE_DAC_MON:
+ case AFE_IRQ0_MCU_CNT_MON:
+ case AFE_IRQ6_MCU_CNT_MON:
+ case AFE_VUL4_CUR_MSB:
+ case AFE_VUL4_CUR:
+ case AFE_VUL4_END:
+ case AFE_VUL12_CUR_MSB:
+ case AFE_VUL12_CUR:
+ case AFE_VUL12_END:
+ case AFE_IRQ3_MCU_CNT_MON:
+ case AFE_IRQ4_MCU_CNT_MON:
+ case AFE_IRQ_MCU_STATUS:
+ case AFE_IRQ_MCU_CLR:
+ case AFE_IRQ_MCU_MON2:
+ case AFE_IRQ1_MCU_CNT_MON:
+ case AFE_IRQ2_MCU_CNT_MON:
+ case AFE_IRQ5_MCU_CNT_MON:
+ case AFE_IRQ7_MCU_CNT_MON:
+ case AFE_IRQ_MCU_MISS_CLR:
+ case AFE_GAIN1_CUR:
+ case AFE_GAIN2_CUR:
+ case AFE_SRAM_DELSEL_CON1:
+ case PCM_INTF_CON2:
+ case FPGA_CFG0:
+ case FPGA_CFG1:
+ case FPGA_CFG2:
+ case FPGA_CFG3:
+ case AUDIO_TOP_DBG_MON0:
+ case AUDIO_TOP_DBG_MON1:
+ case AFE_IRQ8_MCU_CNT_MON:
+ case AFE_IRQ11_MCU_CNT_MON:
+ case AFE_IRQ12_MCU_CNT_MON:
+ case AFE_IRQ9_MCU_CNT_MON:
+ case AFE_IRQ10_MCU_CNT_MON:
+ case AFE_IRQ13_MCU_CNT_MON:
+ case AFE_IRQ14_MCU_CNT_MON:
+ case AFE_IRQ15_MCU_CNT_MON:
+ case AFE_IRQ16_MCU_CNT_MON:
+ case AFE_IRQ17_MCU_CNT_MON:
+ case AFE_IRQ18_MCU_CNT_MON:
+ case AFE_IRQ19_MCU_CNT_MON:
+ case AFE_IRQ20_MCU_CNT_MON:
+ case AFE_IRQ21_MCU_CNT_MON:
+ case AFE_IRQ22_MCU_CNT_MON:
+ case AFE_IRQ23_MCU_CNT_MON:
+ case AFE_IRQ24_MCU_CNT_MON:
+ case AFE_IRQ25_MCU_CNT_MON:
+ case AFE_IRQ26_MCU_CNT_MON:
+ case AFE_IRQ31_MCU_CNT_MON:
+ case AFE_CBIP_MON0:
+ case AFE_CBIP_SLV_MUX_MON0:
+ case AFE_CBIP_SLV_DECODER_MON0:
+ case AFE_ADDA6_MTKAIF_MON0:
+ case AFE_ADDA6_MTKAIF_MON1:
+ case AFE_AWB_CUR_MSB:
+ case AFE_AWB_CUR:
+ case AFE_AWB_END:
+ case AFE_AWB2_CUR_MSB:
+ case AFE_AWB2_CUR:
+ case AFE_AWB2_END:
+ case AFE_DAI_CUR_MSB:
+ case AFE_DAI_CUR:
+ case AFE_DAI_END:
+ case AFE_DAI2_CUR_MSB:
+ case AFE_DAI2_CUR:
+ case AFE_DAI2_END:
+ case AFE_ADDA6_SRC_DEBUG_MON0:
+ case AFE_ADD6A_UL_SRC_MON0:
+ case AFE_ADDA6_UL_SRC_MON1:
+ case AFE_MOD_DAI_CUR_MSB:
+ case AFE_MOD_DAI_CUR:
+ case AFE_MOD_DAI_END:
+ case AFE_AWB_RCH_MON:
+ case AFE_AWB_LCH_MON:
+ case AFE_VUL_RCH_MON:
+ case AFE_VUL_LCH_MON:
+ case AFE_VUL12_RCH_MON:
+ case AFE_VUL12_LCH_MON:
+ case AFE_VUL2_RCH_MON:
+ case AFE_VUL2_LCH_MON:
+ case AFE_DAI_DATA_MON:
+ case AFE_MOD_DAI_DATA_MON:
+ case AFE_DAI2_DATA_MON:
+ case AFE_AWB2_RCH_MON:
+ case AFE_AWB2_LCH_MON:
+ case AFE_VUL3_RCH_MON:
+ case AFE_VUL3_LCH_MON:
+ case AFE_VUL4_RCH_MON:
+ case AFE_VUL4_LCH_MON:
+ case AFE_VUL5_RCH_MON:
+ case AFE_VUL5_LCH_MON:
+ case AFE_VUL6_RCH_MON:
+ case AFE_VUL6_LCH_MON:
+ case AFE_DL1_RCH_MON:
+ case AFE_DL1_LCH_MON:
+ case AFE_DL2_RCH_MON:
+ case AFE_DL2_LCH_MON:
+ case AFE_DL12_RCH1_MON:
+ case AFE_DL12_LCH1_MON:
+ case AFE_DL12_RCH2_MON:
+ case AFE_DL12_LCH2_MON:
+ case AFE_DL3_RCH_MON:
+ case AFE_DL3_LCH_MON:
+ case AFE_DL4_RCH_MON:
+ case AFE_DL4_LCH_MON:
+ case AFE_DL5_RCH_MON:
+ case AFE_DL5_LCH_MON:
+ case AFE_DL6_RCH_MON:
+ case AFE_DL6_LCH_MON:
+ case AFE_DL7_RCH_MON:
+ case AFE_DL7_LCH_MON:
+ case AFE_DL8_RCH_MON:
+ case AFE_DL8_LCH_MON:
+ case AFE_VUL5_CUR_MSB:
+ case AFE_VUL5_CUR:
+ case AFE_VUL5_END:
+ case AFE_VUL6_CUR_MSB:
+ case AFE_VUL6_CUR:
+ case AFE_VUL6_END:
+ case AFE_ADDA_DL_SDM_FIFO_MON:
+ case AFE_ADDA_DL_SRC_LCH_MON:
+ case AFE_ADDA_DL_SRC_RCH_MON:
+ case AFE_ADDA_DL_SDM_OUT_MON:
+ case AFE_CONNSYS_I2S_MON:
+ case AFE_ASRC_2CH_CON0:
+ case AFE_ASRC_2CH_CON2:
+ case AFE_ASRC_2CH_CON3:
+ case AFE_ASRC_2CH_CON4:
+ case AFE_ASRC_2CH_CON5:
+ case AFE_ASRC_2CH_CON7:
+ case AFE_ASRC_2CH_CON8:
+ case AFE_ASRC_2CH_CON12:
+ case AFE_ASRC_2CH_CON13:
+ case AFE_ADDA_MTKAIF_MON0:
+ case AFE_ADDA_MTKAIF_MON1:
+ case AFE_AUD_PAD_TOP:
+ case AFE_DL_NLE_R_MON0:
+ case AFE_DL_NLE_R_MON1:
+ case AFE_DL_NLE_R_MON2:
+ case AFE_DL_NLE_L_MON0:
+ case AFE_DL_NLE_L_MON1:
+ case AFE_DL_NLE_L_MON2:
+ case AFE_GENERAL1_ASRC_2CH_CON0:
+ case AFE_GENERAL1_ASRC_2CH_CON2:
+ case AFE_GENERAL1_ASRC_2CH_CON3:
+ case AFE_GENERAL1_ASRC_2CH_CON4:
+ case AFE_GENERAL1_ASRC_2CH_CON5:
+ case AFE_GENERAL1_ASRC_2CH_CON7:
+ case AFE_GENERAL1_ASRC_2CH_CON8:
+ case AFE_GENERAL1_ASRC_2CH_CON12:
+ case AFE_GENERAL1_ASRC_2CH_CON13:
+ case AFE_GENERAL2_ASRC_2CH_CON0:
+ case AFE_GENERAL2_ASRC_2CH_CON2:
+ case AFE_GENERAL2_ASRC_2CH_CON3:
+ case AFE_GENERAL2_ASRC_2CH_CON4:
+ case AFE_GENERAL2_ASRC_2CH_CON5:
+ case AFE_GENERAL2_ASRC_2CH_CON7:
+ case AFE_GENERAL2_ASRC_2CH_CON8:
+ case AFE_GENERAL2_ASRC_2CH_CON12:
+ case AFE_GENERAL2_ASRC_2CH_CON13:
+ case AFE_DL5_CUR_MSB:
+ case AFE_DL5_CUR:
+ case AFE_DL5_END:
+ case AFE_DL6_CUR_MSB:
+ case AFE_DL6_CUR:
+ case AFE_DL6_END:
+ case AFE_DL7_CUR_MSB:
+ case AFE_DL7_CUR:
+ case AFE_DL7_END:
+ case AFE_DL8_CUR_MSB:
+ case AFE_DL8_CUR:
+ case AFE_DL8_END:
+ case AFE_PROT_SIDEBAND_MON:
+ case AFE_DOMAIN_SIDEBAND0_MON:
+ case AFE_DOMAIN_SIDEBAND1_MON:
+ case AFE_DOMAIN_SIDEBAND2_MON:
+ case AFE_DOMAIN_SIDEBAND3_MON:
+ case AFE_APLL1_TUNER_CFG: /* [20:31] is monitor */
+ case AFE_APLL2_TUNER_CFG: /* [20:31] is monitor */
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config mt8186_afe_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .volatile_reg = mt8186_is_volatile_reg,
+
+ .max_register = AFE_MAX_REGISTER,
+ .num_reg_defaults_raw = AFE_MAX_REGISTER,
+
+ .cache_type = REGCACHE_FLAT,
+};
+
+static irqreturn_t mt8186_afe_irq_handler(int irq_id, void *dev)
+{
+ struct mtk_base_afe *afe = dev;
+ struct mtk_base_afe_irq *irq;
+ unsigned int status;
+ unsigned int status_mcu;
+ unsigned int mcu_en;
+ int ret;
+ int i;
+
+ /* get irq that is sent to MCU */
+ ret = regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en);
+ if (ret) {
+ dev_err(afe->dev, "%s, get irq direction fail, ret %d", __func__, ret);
+ return ret;
+ }
+
+ ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status);
+ /* only care IRQ which is sent to MCU */
+ status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS;
+
+ if (ret || status_mcu == 0) {
+ dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x, mcu_en 0x%x\n",
+ __func__, ret, status, mcu_en);
+
+ goto err_irq;
+ }
+
+ for (i = 0; i < MT8186_MEMIF_NUM; i++) {
+ struct mtk_base_afe_memif *memif = &afe->memif[i];
+
+ if (!memif->substream)
+ continue;
+
+ if (memif->irq_usage < 0)
+ continue;
+
+ irq = &afe->irqs[memif->irq_usage];
+
+ if (status_mcu & (1 << irq->irq_data->irq_en_shift))
+ snd_pcm_period_elapsed(memif->substream);
+ }
+
+err_irq:
+ /* clear irq */
+ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, status_mcu);
+
+ return IRQ_HANDLED;
+}
+
+static int mt8186_afe_runtime_suspend(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ unsigned int value = 0;
+ int ret;
+
+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+ goto skip_regmap;
+
+ /* disable AFE */
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
+
+ ret = regmap_read_poll_timeout(afe->regmap,
+ AFE_DAC_MON,
+ value,
+ (value & AFE_ON_RETM_MASK_SFT) == 0,
+ 20,
+ 1 * 1000 * 1000);
+ if (ret) {
+ dev_err(afe->dev, "%s(), ret %d\n", __func__, ret);
+ return ret;
+ }
+
+ /* make sure all irq status are cleared */
+ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, 0xffffffff);
+ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, 0xffffffff);
+
+ /* reset sgen */
+ regmap_write(afe->regmap, AFE_SINEGEN_CON0, 0x0);
+ regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2,
+ INNER_LOOP_BACK_MODE_MASK_SFT,
+ 0x3f << INNER_LOOP_BACK_MODE_SFT);
+
+ /* cache only */
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+skip_regmap:
+ mt8186_afe_disable_cgs(afe);
+ mt8186_afe_disable_clock(afe);
+
+ return 0;
+}
+
+static int mt8186_afe_runtime_resume(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ ret = mt8186_afe_enable_clock(afe);
+ if (ret)
+ return ret;
+
+ ret = mt8186_afe_enable_cgs(afe);
+ if (ret)
+ return ret;
+
+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+ goto skip_regmap;
+
+ regcache_cache_only(afe->regmap, false);
+ regcache_sync(afe->regmap);
+
+ /* enable audio sys DCM for power saving */
+ regmap_update_bits(afe_priv->infracfg, PERI_BUS_DCM_CTRL, BIT(29), BIT(29));
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, BIT(29), BIT(29));
+
+ /* force cpu use 8_24 format when writing 32bit data */
+ regmap_update_bits(afe->regmap, AFE_MEMIF_CON0, CPU_HD_ALIGN_MASK_SFT, 0);
+
+ /* set all output port to 24bit */
+ regmap_write(afe->regmap, AFE_CONN_24BIT, 0xffffffff);
+ regmap_write(afe->regmap, AFE_CONN_24BIT_1, 0xffffffff);
+
+ /* enable AFE */
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, AUDIO_AFE_ON_MASK_SFT, BIT(0));
+
+skip_regmap:
+ return 0;
+}
+
+static int mt8186_afe_component_probe(struct snd_soc_component *component)
+{
+ mtk_afe_add_sub_dai_control(component);
+ mt8186_add_misc_control(component);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver mt8186_afe_component = {
+ .name = AFE_PCM_NAME,
+ .pcm_construct = mtk_afe_pcm_new,
+ .pointer = mtk_afe_pcm_pointer,
+ .probe = mt8186_afe_component_probe,
+};
+
+static int mt8186_dai_memif_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mt8186_memif_dai_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mt8186_memif_dai_driver);
+
+ dai->controls = mt8186_pcm_kcontrols;
+ dai->num_controls = ARRAY_SIZE(mt8186_pcm_kcontrols);
+ dai->dapm_widgets = mt8186_memif_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mt8186_memif_widgets);
+ dai->dapm_routes = mt8186_memif_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mt8186_memif_routes);
+ return 0;
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+ mt8186_dai_adda_register,
+ mt8186_dai_i2s_register,
+ mt8186_dai_tdm_register,
+ mt8186_dai_hw_gain_register,
+ mt8186_dai_src_register,
+ mt8186_dai_pcm_register,
+ mt8186_dai_hostless_register,
+ mt8186_dai_memif_register,
+};
+
+static int mt8186_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+ struct mtk_base_afe *afe;
+ struct mt8186_afe_private *afe_priv;
+ struct resource *res;
+ struct reset_control *rstc;
+ struct device *dev = &pdev->dev;
+ int i, ret, irq_id;
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34));
+ if (ret)
+ return ret;
+
+ afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
+ if (!afe)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, afe);
+
+ afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv), GFP_KERNEL);
+ if (!afe->platform_priv)
+ return -ENOMEM;
+
+ afe_priv = afe->platform_priv;
+ afe->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ afe->base_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(afe->base_addr))
+ return PTR_ERR(afe->base_addr);
+
+ /* init audio related clock */
+ ret = mt8186_init_clock(afe);
+ if (ret) {
+ dev_err(dev, "init clock error, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, mt8186_deinit_clock, (void *)afe);
+ if (ret)
+ return ret;
+
+ /* init memif */
+ afe->memif_32bit_supported = 0;
+ afe->memif_size = MT8186_MEMIF_NUM;
+ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), GFP_KERNEL);
+ if (!afe->memif)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->memif_size; i++) {
+ afe->memif[i].data = &memif_data[i];
+ afe->memif[i].irq_usage = memif_irq_usage[i];
+ afe->memif[i].const_irq = 1;
+ }
+
+ mutex_init(&afe->irq_alloc_lock); /* needed when dynamic irq */
+
+ /* init irq */
+ afe->irqs_size = MT8186_IRQ_NUM;
+ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
+ GFP_KERNEL);
+
+ if (!afe->irqs)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->irqs_size; i++)
+ afe->irqs[i].irq_data = &irq_data[i];
+
+ /* request irq */
+ irq_id = platform_get_irq(pdev, 0);
+ if (irq_id <= 0)
+ return dev_err_probe(dev, irq_id < 0 ? irq_id : -ENXIO,
+ "no irq found");
+
+ ret = devm_request_irq(dev, irq_id, mt8186_afe_irq_handler,
+ IRQF_TRIGGER_NONE,
+ "Afe_ISR_Handle", (void *)afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n");
+
+ ret = enable_irq_wake(irq_id);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "enable_irq_wake %d\n", irq_id);
+
+ /* init sub_dais */
+ INIT_LIST_HEAD(&afe->sub_dais);
+
+ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
+ ret = dai_register_cbs[i](afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "dai register i %d fail\n", i);
+ }
+
+ /* init dai_driver and component_driver */
+ ret = mtk_afe_combine_sub_dai(afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n");
+
+ /* reset controller to reset audio regs before regmap cache */
+ rstc = devm_reset_control_get_exclusive(dev, "audiosys");
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc), "could not get audiosys reset\n");
+
+ ret = reset_control_reset(rstc);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to trigger audio reset\n");
+
+ /* enable clock for regcache get default value from hw */
+ afe_priv->pm_runtime_bypass_reg_ctl = true;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to resume device\n");
+
+ afe->regmap = devm_regmap_init_mmio(dev, afe->base_addr,
+ &mt8186_afe_regmap_config);
+ if (IS_ERR(afe->regmap)) {
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_disable;
+ }
+
+ /* others */
+ afe->mtk_afe_hardware = &mt8186_afe_hardware;
+ afe->memif_fs = mt8186_memif_fs;
+ afe->irq_fs = mt8186_irq_fs;
+ afe->get_dai_fs = mt8186_get_dai_fs;
+ afe->get_memif_pbuf_size = mt8186_get_memif_pbuf_size;
+
+ afe->runtime_resume = mt8186_afe_runtime_resume;
+ afe->runtime_suspend = mt8186_afe_runtime_suspend;
+
+ /* register platform */
+ dev_dbg(dev, "%s(), devm_snd_soc_register_component\n", __func__);
+
+ ret = devm_snd_soc_register_component(dev,
+ &mt8186_afe_component,
+ afe->dai_drivers,
+ afe->num_dai_drivers);
+ if (ret) {
+ dev_err(dev, "err_dai_component\n");
+ goto err_pm_disable;
+ }
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret) {
+ pm_runtime_get_noresume(dev);
+ dev_err(dev, "failed to suspend device: %d\n", ret);
+ goto err_pm_disable;
+ }
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
+
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_put_noidle(dev);
+ pm_runtime_set_suspended(dev);
+
+ return ret;
+}
+
+static const struct of_device_id mt8186_afe_pcm_dt_match[] = {
+ { .compatible = "mediatek,mt8186-sound", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt8186_afe_pcm_dt_match);
+
+static const struct dev_pm_ops mt8186_afe_pm_ops = {
+ SET_RUNTIME_PM_OPS(mt8186_afe_runtime_suspend,
+ mt8186_afe_runtime_resume, NULL)
+};
+
+static struct platform_driver mt8186_afe_pcm_driver = {
+ .driver = {
+ .name = "mt8186-audio",
+ .of_match_table = mt8186_afe_pcm_dt_match,
+ .pm = &mt8186_afe_pm_ops,
+ },
+ .probe = mt8186_afe_pcm_dev_probe,
+};
+
+module_platform_driver(mt8186_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8186");
+MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
index 6be6d4f3b585..266704556f37 100644
--- a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
@@ -75,8 +75,7 @@ static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
struct mt8186_afe_private *afe_priv = afe->platform_priv;
int dai_id;
- if (strncmp(name, "aud_dac_hires_clk", 7) == 0 ||
- strncmp(name, "aud_adc_hires_clk", 7) == 0)
+ if (strncmp(name, "aud_dac", 7) == 0 || strncmp(name, "aud_adc", 7) == 0)
dai_id = MT8186_DAI_ADDA;
else
return NULL;
@@ -655,11 +654,6 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
__func__, id, substream->stream, rate);
- if (!adda_priv) {
- dev_err(afe->dev, "%s(), adda_priv == NULL", __func__);
- return -EINVAL;
- }
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
unsigned int dl_src2_con0;
unsigned int dl_src2_con1;
diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
index 5c1290b950e8..ec79e2f2a54d 100644
--- a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
@@ -119,12 +119,6 @@ static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol,
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
return 0;
@@ -148,12 +142,6 @@ static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol,
__func__, kcontrol->id.name, hd_en);
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
if (i2s_priv->low_jitter_en == hd_en)
return 0;
@@ -377,11 +365,6 @@ static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,
i2s_priv = get_i2s_priv_by_name(afe, w->name);
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
@@ -442,11 +425,6 @@ static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
i2s_priv = get_i2s_priv_by_name(afe, w->name);
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
@@ -566,12 +544,6 @@ static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return 0;
- }
-
if (i2s_priv->share_i2s_id < 0)
return 0;
@@ -587,12 +559,6 @@ static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return 0;
- }
-
if (get_i2s_id_by_name(afe, sink->name) ==
get_i2s_id_by_name(afe, source->name))
return i2s_priv->low_jitter_en;
@@ -618,15 +584,8 @@ static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
int i2s_need_apll;
i2s_priv = get_i2s_priv_by_name(afe, w->name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return 0;
- }
-
/* which apll */
cur_apll = mt8186_get_apll_by_name(afe, source->name);
-
/* choose APLL from i2s rate */
i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate);
@@ -642,12 +601,6 @@ static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return 0;
- }
-
if (get_i2s_id_by_name(afe, sink->name) ==
get_i2s_id_by_name(afe, source->name))
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
@@ -672,12 +625,6 @@ static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
int cur_apll;
i2s_priv = get_i2s_priv_by_name(afe, w->name);
-
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return 0;
- }
-
/* which apll */
cur_apll = mt8186_get_apll_by_name(afe, source->name);
@@ -980,11 +927,6 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n",
__func__, i2s_id, rate, format);
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
i2s_priv->rate = rate;
switch (i2s_id) {
@@ -1053,11 +995,6 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
int apll;
int apll_rate;
- if (!i2s_priv) {
- dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
- return -EINVAL;
- }
-
if (dir != SND_SOC_CLOCK_OUT) {
dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
return -EINVAL;
diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
index 0b0032ecfe6d..41221a66111c 100644
--- a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
@@ -287,11 +287,6 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct mt8186_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id];
- if (!pcm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
/* DAI mode*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
index c6ead7c252f0..4148dceb3a4c 100644
--- a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
@@ -106,11 +106,6 @@ static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
@@ -138,11 +133,6 @@ static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
__func__, w->name, event, dai_id);
@@ -215,11 +205,6 @@ static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return 0;
- }
-
return (tdm_priv->mclk_rate > 0) ? 1 : 0;
}
@@ -250,11 +235,6 @@ static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return 0;
- }
-
return tdm_priv->low_jitter_en;
}
@@ -270,11 +250,6 @@ static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
int cur_apll;
int tdm_need_apll;
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return 0;
- }
-
/* which apll */
cur_apll = mt8186_get_apll_by_name(afe, source->name);
@@ -303,11 +278,6 @@ static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol,
int dai_id = get_tdm_id_by_name(kcontrol->id.name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;
return 0;
@@ -332,11 +302,6 @@ static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol,
dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
__func__, kcontrol->id.name, hd_en);
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
if (tdm_priv->low_jitter_en == hd_en)
return 0;
@@ -421,22 +386,14 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
unsigned int tran_rate;
unsigned int tran_relatch_rate;
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
tdm_priv->rate = rate;
-
tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id);
tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate);
/* calculate mclk_rate, if not set explicitly */
if (!tdm_priv->mclk_rate) {
tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
- mtk_dai_tdm_cal_mclk(afe,
- tdm_priv,
- tdm_priv->mclk_rate);
+ mtk_dai_tdm_cal_mclk(afe, tdm_priv, tdm_priv->mclk_rate);
}
/* ETDM_IN1_CON0 */
@@ -508,11 +465,6 @@ static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
struct mt8186_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
if (dir != SND_SOC_CLOCK_IN) {
dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
return -EINVAL;
@@ -529,11 +481,6 @@ static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct mt8186_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
- if (!tdm_priv) {
- dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
- return -EINVAL;
- }
-
/* DAI mode*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
new file mode 100644
index 000000000000..4e66603d4cdb
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-mt6366-common.c
+// -- MT8186 MT6366 ALSA common driver
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+//
+#include <sound/soc.h>
+
+#include "../../codecs/mt6358.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-mt6366-common.h"
+
+int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_afe =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+ int ret;
+
+ /* set mtkaif protocol */
+ mt6358_set_mtkaif_protocol(cmpnt_codec,
+ MT6358_MTKAIF_PROTOCOL_1);
+ afe_priv->mtkaif_protocol = MT6358_MTKAIF_PROTOCOL_1;
+
+ ret = snd_soc_dapm_sync(dapm);
+ if (ret) {
+ dev_err(rtd->dev, "failed to snd_soc_dapm_sync\n");
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt8186_mt6366_init);
+
+int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *link,
+ struct device_node *node,
+ char *link_name)
+{
+ int ret;
+
+ if (node && strcmp(link->name, link_name) == 0) {
+ ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link);
+ if (ret < 0)
+ return dev_err_probe(card->dev, ret, "get dai link codecs fail\n");
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt8186_mt6366_card_set_be_link);
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
new file mode 100644
index 000000000000..907d8f5e46b1
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8186-mt6366-common.h
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+ */
+
+#ifndef _MT8186_MT6366_COMMON_H_
+#define _MT8186_MT6366_COMMON_H_
+
+int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd);
+int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *link,
+ struct device_node *node,
+ char *link_name);
+#endif
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
new file mode 100644
index 000000000000..387f25cad809
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
@@ -0,0 +1,1002 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-mt6366-da7219-max98357.c
+// -- MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+//
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../../codecs/da7219-aad.h"
+#include "../../codecs/da7219.h"
+#include "../../codecs/mt6358.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-mt6366-common.h"
+
+#define DA7219_CODEC_DAI "da7219-hifi"
+#define DA7219_DEV_NAME "da7219.5-001a"
+
+struct mt8186_mt6366_da7219_max98357_priv {
+ struct snd_soc_jack headset_jack, hdmi_jack;
+};
+
+static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = {
+ {
+ .dlc = COMP_CODEC_CONF("mt6358-sound"),
+ .name_prefix = "Mt6366",
+ },
+ {
+ .dlc = COMP_CODEC_CONF("bt-sco"),
+ .name_prefix = "Mt8186 bt",
+ },
+ {
+ .dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
+ .name_prefix = "Mt8186 hdmi",
+ },
+};
+
+static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mt8186_mt6366_da7219_max98357_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &priv->headset_jack;
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ int ret;
+
+ /* Enable Headset and 4 Buttons Jack detection */
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3 | SND_JACK_LINEOUT,
+ jack);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+
+ da7219_aad_jack_det(cmpnt_codec, &priv->headset_jack);
+
+ return 0;
+}
+
+static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai;
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 256;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+ unsigned int freq;
+ int ret, j;
+
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0,
+ mclk_fs, SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret);
+ return ret;
+ }
+
+ for_each_rtd_codec_dais(rtd, j, codec_dai) {
+ if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ DA7219_CLKSRC_MCLK,
+ mclk_fs,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(rtd->dev, "failed to set sysclk: %d\n",
+ ret);
+ return ret;
+ }
+
+ if ((rate % 8000) == 0)
+ freq = DA7219_PLL_FREQ_OUT_98304;
+ else
+ freq = DA7219_PLL_FREQ_OUT_90316;
+
+ ret = snd_soc_dai_set_pll(codec_dai, 0,
+ DA7219_SYSCLK_PLL_SRM,
+ 0, freq);
+ if (ret) {
+ dev_err(rtd->dev, "failed to start PLL: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai;
+ int ret = 0, j;
+
+ for_each_rtd_codec_dais(rtd, j, codec_dai) {
+ if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
+ ret = snd_soc_dai_set_pll(codec_dai,
+ 0, DA7219_SYSCLK_MCLK, 0, 0);
+ if (ret < 0) {
+ dev_err(rtd->dev, "failed to stop PLL: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8186_da7219_i2s_ops = {
+ .hw_params = mt8186_da7219_i2s_hw_params,
+ .hw_free = mt8186_da7219_i2s_hw_free,
+};
+
+static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mt8186_mt6366_da7219_max98357_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ int ret;
+
+ ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
+ if (ret) {
+ dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
+
+static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params,
+ snd_pcm_format_t fmt)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
+
+ /* fix BE i2s channel to 2 channel */
+ channels->min = 2;
+ channels->max = 2;
+
+ /* clean param mask first */
+ snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+ params_set_format(params, fmt);
+
+ return 0;
+}
+
+static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
+}
+
+static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
+}
+
+static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 2
+ };
+ 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,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = {
+ .startup = mt8186_mt6366_da7219_max98357_playback_startup,
+};
+
+static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 1, 2
+ };
+ 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,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = {
+ .startup = mt8186_mt6366_da7219_max98357_capture_startup,
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(playback1,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback12,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback2,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback3,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback4,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback5,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback6,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback7,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback8,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture1,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture2,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture3,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture4,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture5,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture6,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture7,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* hostless */
+SND_SOC_DAILINK_DEFS(hostless_lpbk,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_fm,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src1,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src_bargein,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* BE */
+SND_SOC_DAILINK_DEFS(adda,
+ DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
+ "mt6358-snd-codec-aif1"),
+ COMP_CODEC("dmic-codec",
+ "dmic-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s0,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s1,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s2,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s3,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_gain1,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_gain2,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_src1,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_src2,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(connsys_i2s,
+ DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(pcm1,
+ DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(tdm_in,
+ DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* hostless */
+SND_SOC_DAILINK_DEFS(hostless_ul1,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul2,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul3,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul5,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul6,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = {
+ /* Front End DAI links */
+ {
+ .name = "Playback_1",
+ .stream_name = "Playback_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_da7219_max98357_playback_ops,
+ SND_SOC_DAILINK_REG(playback1),
+ },
+ {
+ .name = "Playback_12",
+ .stream_name = "Playback_12",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback12),
+ },
+ {
+ .name = "Playback_2",
+ .stream_name = "Playback_2",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ SND_SOC_DAILINK_REG(playback2),
+ },
+ {
+ .name = "Playback_3",
+ .stream_name = "Playback_3",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_da7219_max98357_playback_ops,
+ SND_SOC_DAILINK_REG(playback3),
+ },
+ {
+ .name = "Playback_4",
+ .stream_name = "Playback_4",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback4),
+ },
+ {
+ .name = "Playback_5",
+ .stream_name = "Playback_5",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback5),
+ },
+ {
+ .name = "Playback_6",
+ .stream_name = "Playback_6",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback6),
+ },
+ {
+ .name = "Playback_7",
+ .stream_name = "Playback_7",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback7),
+ },
+ {
+ .name = "Playback_8",
+ .stream_name = "Playback_8",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback8),
+ },
+ {
+ .name = "Capture_1",
+ .stream_name = "Capture_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture1),
+ },
+ {
+ .name = "Capture_2",
+ .stream_name = "Capture_2",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_da7219_max98357_capture_ops,
+ SND_SOC_DAILINK_REG(capture2),
+ },
+ {
+ .name = "Capture_3",
+ .stream_name = "Capture_3",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture3),
+ },
+ {
+ .name = "Capture_4",
+ .stream_name = "Capture_4",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_da7219_max98357_capture_ops,
+ SND_SOC_DAILINK_REG(capture4),
+ },
+ {
+ .name = "Capture_5",
+ .stream_name = "Capture_5",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture5),
+ },
+ {
+ .name = "Capture_6",
+ .stream_name = "Capture_6",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ SND_SOC_DAILINK_REG(capture6),
+ },
+ {
+ .name = "Capture_7",
+ .stream_name = "Capture_7",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture7),
+ },
+ {
+ .name = "Hostless_LPBK",
+ .stream_name = "Hostless_LPBK",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_lpbk),
+ },
+ {
+ .name = "Hostless_FM",
+ .stream_name = "Hostless_FM",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_fm),
+ },
+ {
+ .name = "Hostless_SRC_1",
+ .stream_name = "Hostless_SRC_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src1),
+ },
+ {
+ .name = "Hostless_SRC_Bargein",
+ .stream_name = "Hostless_SRC_Bargein",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src_bargein),
+ },
+ {
+ .name = "Hostless_HW_Gain_AAudio",
+ .stream_name = "Hostless_HW_Gain_AAudio",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
+ },
+ {
+ .name = "Hostless_SRC_AAudio",
+ .stream_name = "Hostless_SRC_AAudio",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src_aaudio),
+ },
+ /* Back End DAI links */
+ {
+ .name = "Primary Codec",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .init = mt8186_mt6366_init,
+ SND_SOC_DAILINK_REG(adda),
+ },
+ {
+ .name = "I2S3",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_IB_IF |
+ SND_SOC_DAIFMT_CBM_CFM,
+ .dpcm_playback = 1,
+ .ignore_suspend = 1,
+ .init = mt8186_mt6366_da7219_max98357_hdmi_init,
+ .be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2s3),
+ },
+ {
+ .name = "I2S0",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ .ops = &mt8186_da7219_i2s_ops,
+ SND_SOC_DAILINK_REG(i2s0),
+ },
+ {
+ .name = "I2S1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ .init = mt8186_da7219_init,
+ .ops = &mt8186_da7219_i2s_ops,
+ SND_SOC_DAILINK_REG(i2s1),
+ },
+ {
+ .name = "I2S2",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2s2),
+ },
+ {
+ .name = "HW Gain 1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_gain1),
+ },
+ {
+ .name = "HW Gain 2",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_gain2),
+ },
+ {
+ .name = "HW_SRC_1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_src1),
+ },
+ {
+ .name = "HW_SRC_2",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_src2),
+ },
+ {
+ .name = "CONNSYS_I2S",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(connsys_i2s),
+ },
+ {
+ .name = "PCM 1",
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_IF,
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(pcm1),
+ },
+ {
+ .name = "TDM IN",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(tdm_in),
+ },
+ /* dummy BE for ul memif to record from dl memif */
+ {
+ .name = "Hostless_UL1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul1),
+ },
+ {
+ .name = "Hostless_UL2",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul2),
+ },
+ {
+ .name = "Hostless_UL3",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul3),
+ },
+ {
+ .name = "Hostless_UL5",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul5),
+ },
+ {
+ .name = "Hostless_UL6",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul6),
+ },
+};
+
+static const struct snd_soc_dapm_widget
+mt8186_mt6366_da7219_max98357_widgets[] = {
+ SND_SOC_DAPM_SPK("Speakers", NULL),
+ SND_SOC_DAPM_OUTPUT("HDMI1"),
+};
+
+static const struct snd_soc_dapm_route
+mt8186_mt6366_da7219_max98357_routes[] = {
+ /* SPK */
+ { "Speakers", NULL, "Speaker"},
+ /* HDMI */
+ { "HDMI1", NULL, "TX"},
+};
+
+static const struct snd_kcontrol_new
+mt8186_mt6366_da7219_max98357_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speakers"),
+ SOC_DAPM_PIN_SWITCH("HDMI1"),
+};
+
+static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = {
+ .name = "mt8186_mt6366_da7219_max98357",
+ .owner = THIS_MODULE,
+ .dai_link = mt8186_mt6366_da7219_max98357_dai_links,
+ .num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links),
+ .controls = mt8186_mt6366_da7219_max98357_controls,
+ .num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls),
+ .dapm_widgets = mt8186_mt6366_da7219_max98357_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets),
+ .dapm_routes = mt8186_mt6366_da7219_max98357_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes),
+ .codec_conf = mt8186_mt6366_da7219_max98357_codec_conf,
+ .num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf),
+};
+
+static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct snd_soc_dai_link *dai_link;
+ struct mt8186_mt6366_da7219_max98357_priv *priv;
+ struct device_node *platform_node, *headset_codec, *playback_codec;
+ int ret, i;
+
+ card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
+ if (!card)
+ return -EINVAL;
+ card->dev = &pdev->dev;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
+ if (!platform_node) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
+ return ret;
+ }
+
+ playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
+ if (!playback_codec) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
+ goto err_playback_codec;
+ }
+
+ headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
+ if (!headset_codec) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
+ goto err_headset_codec;
+ }
+
+ for_each_card_prelinks(card, i, dai_link) {
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ if (!dai_link->platforms->name)
+ dai_link->platforms->of_node = platform_node;
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+
+ snd_soc_card_set_drvdata(card, priv);
+
+ ret = mt8186_afe_gpio_init(&pdev->dev);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
+ goto err_probe;
+ }
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret)
+ dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
+
+err_probe:
+ of_node_put(headset_codec);
+err_headset_codec:
+ of_node_put(playback_codec);
+err_playback_codec:
+ of_node_put(platform_node);
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = {
+ { .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound",
+ .data = &mt8186_mt6366_da7219_max98357_soc_card,
+ },
+ {}
+};
+#endif
+
+static struct platform_driver mt8186_mt6366_da7219_max98357_driver = {
+ .driver = {
+ .name = "mt8186_mt6366_da7219_max98357",
+#if IS_ENABLED(CONFIG_OF)
+ .of_match_table = mt8186_mt6366_da7219_max98357_dt_match,
+#endif
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = mt8186_mt6366_da7219_max98357_dev_probe,
+};
+
+module_platform_driver(mt8186_mt6366_da7219_max98357_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver");
+MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card");
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
new file mode 100644
index 000000000000..891146fd6c2b
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
@@ -0,0 +1,978 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-mt6366-rt1019-rt5682s.c
+// -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+//
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/rt5682.h>
+#include <sound/soc.h>
+
+#include "../../codecs/mt6358.h"
+#include "../../codecs/rt5682.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-mt6366-common.h"
+
+#define RT1019_CODEC_DAI "HiFi"
+#define RT1019_DEV0_NAME "rt1019p"
+
+#define RT5682S_CODEC_DAI "rt5682s-aif1"
+#define RT5682S_DEV0_NAME "rt5682s.5-001a"
+
+struct mt8186_mt6366_rt1019_rt5682s_priv {
+ struct snd_soc_jack headset_jack, hdmi_jack;
+};
+
+static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = {
+ {
+ .dlc = COMP_CODEC_CONF("mt6358-sound"),
+ .name_prefix = "Mt6366",
+ },
+ {
+ .dlc = COMP_CODEC_CONF("bt-sco"),
+ .name_prefix = "Mt8186 bt",
+ },
+ {
+ .dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
+ .name_prefix = "Mt8186 hdmi",
+ },
+};
+
+static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mt8186_mt6366_rt1019_rt5682s_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &priv->headset_jack;
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ int ret;
+
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3,
+ jack);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+ return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+}
+
+static int mt8186_rt5682s_i2s_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 *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 128;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+ int bitwidth;
+ int ret;
+
+ bitwidth = snd_pcm_format_width(params_format(params));
+ if (bitwidth < 0) {
+ dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+ return bitwidth;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+ if (ret) {
+ dev_err(card->dev, "failed to set tdm slot\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
+ RT5682_PLL1_S_BCLK1,
+ params_rate(params) * 64,
+ params_rate(params) * 512);
+ if (ret) {
+ dev_err(card->dev, "failed to set pll\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ RT5682_SCLK_S_PLL1,
+ params_rate(params) * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(card->dev, "failed to set sysclk\n");
+ return ret;
+ }
+
+ return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = {
+ .hw_params = mt8186_rt5682s_i2s_hw_params,
+};
+
+static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mt8186_mt6366_rt1019_rt5682s_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ int ret;
+
+ ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
+ if (ret) {
+ dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
+
+static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params,
+ snd_pcm_format_t fmt)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
+
+ /* fix BE i2s channel to 2 channel */
+ channels->min = 2;
+ channels->max = 2;
+
+ /* clean param mask first */
+ snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+ params_set_format(params, fmt);
+
+ return 0;
+}
+
+static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
+}
+
+static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
+}
+
+static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 2
+ };
+ 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,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = {
+ .startup = mt8186_mt6366_rt1019_rt5682s_playback_startup,
+};
+
+static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 1, 2
+ };
+ 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,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = {
+ .startup = mt8186_mt6366_rt1019_rt5682s_capture_startup,
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(playback1,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback12,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback2,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback3,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback4,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback5,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback6,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback7,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(playback8,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture1,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture2,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture3,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture4,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture5,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture6,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(capture7,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* hostless */
+SND_SOC_DAILINK_DEFS(hostless_lpbk,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_fm,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src1,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src_bargein,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* BE */
+SND_SOC_DAILINK_DEFS(adda,
+ DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
+ "mt6358-snd-codec-aif1"),
+ COMP_CODEC("dmic-codec",
+ "dmic-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s0,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s1,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s2,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s3,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_gain1,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_gain2,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_src1,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hw_src2,
+ DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(connsys_i2s,
+ DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(pcm1,
+ DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(tdm_in,
+ DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* hostless */
+SND_SOC_DAILINK_DEFS(hostless_ul1,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul2,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul3,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul5,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_ul6,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
+ DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
+ /* Front End DAI links */
+ {
+ .name = "Playback_1",
+ .stream_name = "Playback_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
+ SND_SOC_DAILINK_REG(playback1),
+ },
+ {
+ .name = "Playback_12",
+ .stream_name = "Playback_12",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback12),
+ },
+ {
+ .name = "Playback_2",
+ .stream_name = "Playback_2",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ SND_SOC_DAILINK_REG(playback2),
+ },
+ {
+ .name = "Playback_3",
+ .stream_name = "Playback_3",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
+ SND_SOC_DAILINK_REG(playback3),
+ },
+ {
+ .name = "Playback_4",
+ .stream_name = "Playback_4",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback4),
+ },
+ {
+ .name = "Playback_5",
+ .stream_name = "Playback_5",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback5),
+ },
+ {
+ .name = "Playback_6",
+ .stream_name = "Playback_6",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback6),
+ },
+ {
+ .name = "Playback_7",
+ .stream_name = "Playback_7",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback7),
+ },
+ {
+ .name = "Playback_8",
+ .stream_name = "Playback_8",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(playback8),
+ },
+ {
+ .name = "Capture_1",
+ .stream_name = "Capture_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture1),
+ },
+ {
+ .name = "Capture_2",
+ .stream_name = "Capture_2",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
+ SND_SOC_DAILINK_REG(capture2),
+ },
+ {
+ .name = "Capture_3",
+ .stream_name = "Capture_3",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture3),
+ },
+ {
+ .name = "Capture_4",
+ .stream_name = "Capture_4",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
+ SND_SOC_DAILINK_REG(capture4),
+ },
+ {
+ .name = "Capture_5",
+ .stream_name = "Capture_5",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture5),
+ },
+ {
+ .name = "Capture_6",
+ .stream_name = "Capture_6",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_format = 1,
+ .dpcm_merged_chan = 1,
+ .dpcm_merged_rate = 1,
+ SND_SOC_DAILINK_REG(capture6),
+ },
+ {
+ .name = "Capture_7",
+ .stream_name = "Capture_7",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(capture7),
+ },
+ {
+ .name = "Hostless_LPBK",
+ .stream_name = "Hostless_LPBK",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_lpbk),
+ },
+ {
+ .name = "Hostless_FM",
+ .stream_name = "Hostless_FM",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_fm),
+ },
+ {
+ .name = "Hostless_SRC_1",
+ .stream_name = "Hostless_SRC_1",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src1),
+ },
+ {
+ .name = "Hostless_SRC_Bargein",
+ .stream_name = "Hostless_SRC_Bargein",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src_bargein),
+ },
+ {
+ .name = "Hostless_HW_Gain_AAudio",
+ .stream_name = "Hostless_HW_Gain_AAudio",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
+ },
+ {
+ .name = "Hostless_SRC_AAudio",
+ .stream_name = "Hostless_SRC_AAudio",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_src_aaudio),
+ },
+ /* Back End DAI links */
+ {
+ .name = "Primary Codec",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .init = mt8186_mt6366_init,
+ SND_SOC_DAILINK_REG(adda),
+ },
+ {
+ .name = "I2S3",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_IB_IF |
+ SND_SOC_DAIFMT_CBM_CFM,
+ .dpcm_playback = 1,
+ .ignore_suspend = 1,
+ .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init,
+ .be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2s3),
+ },
+ {
+ .name = "I2S0",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ .ops = &mt8186_rt5682s_i2s_ops,
+ SND_SOC_DAILINK_REG(i2s0),
+ },
+ {
+ .name = "I2S1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ .init = mt8186_rt5682s_init,
+ .ops = &mt8186_rt5682s_i2s_ops,
+ SND_SOC_DAILINK_REG(i2s1),
+ },
+ {
+ .name = "I2S2",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2s2),
+ },
+ {
+ .name = "HW Gain 1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_gain1),
+ },
+ {
+ .name = "HW Gain 2",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_gain2),
+ },
+ {
+ .name = "HW_SRC_1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_src1),
+ },
+ {
+ .name = "HW_SRC_2",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hw_src2),
+ },
+ {
+ .name = "CONNSYS_I2S",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(connsys_i2s),
+ },
+ {
+ .name = "PCM 1",
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_IF,
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(pcm1),
+ },
+ {
+ .name = "TDM IN",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(tdm_in),
+ },
+ /* dummy BE for ul memif to record from dl memif */
+ {
+ .name = "Hostless_UL1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul1),
+ },
+ {
+ .name = "Hostless_UL2",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul2),
+ },
+ {
+ .name = "Hostless_UL3",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul3),
+ },
+ {
+ .name = "Hostless_UL5",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul5),
+ },
+ {
+ .name = "Hostless_UL6",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(hostless_ul6),
+ },
+};
+
+static const struct snd_soc_dapm_widget
+mt8186_mt6366_rt1019_rt5682s_widgets[] = {
+ SND_SOC_DAPM_SPK("Speakers", NULL),
+ SND_SOC_DAPM_OUTPUT("HDMI1"),
+};
+
+static const struct snd_soc_dapm_route
+mt8186_mt6366_rt1019_rt5682s_routes[] = {
+ /* SPK */
+ { "Speakers", NULL, "Speaker" },
+ /* HDMI */
+ { "HDMI1", NULL, "TX" },
+};
+
+static const struct snd_kcontrol_new
+mt8186_mt6366_rt1019_rt5682s_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speakers"),
+ SOC_DAPM_PIN_SWITCH("HDMI1"),
+};
+
+static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = {
+ .name = "mt8186_mt6366_rt1019_rt5682s",
+ .owner = THIS_MODULE,
+ .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links,
+ .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links),
+ .controls = mt8186_mt6366_rt1019_rt5682s_controls,
+ .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls),
+ .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets),
+ .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes),
+ .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf,
+ .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
+};
+
+static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct snd_soc_dai_link *dai_link;
+ struct mt8186_mt6366_rt1019_rt5682s_priv *priv;
+ struct device_node *platform_node, *headset_codec, *playback_codec;
+ int ret, i;
+
+ card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
+ if (!card)
+ return -EINVAL;
+ card->dev = &pdev->dev;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
+ if (!platform_node) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
+ return ret;
+ }
+
+ playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
+ if (!playback_codec) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
+ goto err_playback_codec;
+ }
+
+ headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
+ if (!headset_codec) {
+ ret = -EINVAL;
+ dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
+ goto err_headset_codec;
+ }
+
+ for_each_card_prelinks(card, i, dai_link) {
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
+ dai_link->name);
+ goto err_probe;
+ }
+
+ if (!dai_link->platforms->name)
+ dai_link->platforms->of_node = platform_node;
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+
+ snd_soc_card_set_drvdata(card, priv);
+
+ ret = mt8186_afe_gpio_init(&pdev->dev);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
+ goto err_probe;
+ }
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret)
+ dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
+
+err_probe:
+ of_node_put(headset_codec);
+err_headset_codec:
+ of_node_put(playback_codec);
+err_playback_codec:
+ of_node_put(platform_node);
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = {
+ { .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound",
+ .data = &mt8186_mt6366_rt1019_rt5682s_soc_card,
+ },
+ {}
+};
+#endif
+
+static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = {
+ .driver = {
+ .name = "mt8186_mt6366_rt1019_rt5682s",
+#if IS_ENABLED(CONFIG_OF)
+ .of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match,
+#endif
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = mt8186_mt6366_rt1019_rt5682s_dev_probe,
+};
+
+module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver");
+MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card");
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
index 54a00b0699b1..c530e3fc27e4 100644
--- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
@@ -20,6 +20,8 @@
#include "../../codecs/rt1011.h"
#include "../../codecs/rt5682.h"
#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-dsp-sof-common.h"
+#include "../common/mtk-soc-card.h"
#include "mt8195-afe-clk.h"
#include "mt8195-afe-common.h"
@@ -54,13 +56,6 @@ struct mt8195_card_data {
unsigned long quirk;
};
-struct sof_conn_stream {
- const char *normal_link;
- const char *sof_link;
- const char *sof_dma;
- int stream_dir;
-};
-
struct mt8195_mt6359_priv {
struct snd_soc_jack headset_jack;
struct snd_soc_jack dp_jack;
@@ -374,7 +369,8 @@ static const struct snd_soc_ops mt8195_dptx_ops = {
static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
{
- struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+ struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
int ret;
@@ -389,7 +385,8 @@ static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
{
- struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+ struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
int ret;
@@ -555,7 +552,8 @@ static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
- struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+ struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &priv->headset_jack;
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
@@ -722,7 +720,8 @@ static int mt8195_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
{
struct snd_soc_component *component = dapm->component;
- struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(card);
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
+ struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
int ret;
/*
@@ -1321,175 +1320,24 @@ static struct snd_soc_card mt8195_mt6359_soc_card = {
static int mt8195_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai_link *sof_dai_link = NULL;
- struct snd_soc_pcm_runtime *runtime;
- struct snd_soc_dai *cpu_dai;
- int i, j, ret = 0;
-
- for (i = 0; i < ARRAY_SIZE(g_sof_conn_streams); i++) {
- const struct sof_conn_stream *conn = &g_sof_conn_streams[i];
-
- if (strcmp(rtd->dai_link->name, conn->normal_link))
- continue;
-
- for_each_card_rtds(card, runtime) {
- if (strcmp(runtime->dai_link->name, conn->sof_link))
- continue;
-
- for_each_rtd_cpu_dais(runtime, j, cpu_dai) {
- if (cpu_dai->stream_active[conn->stream_dir] > 0) {
- sof_dai_link = runtime->dai_link;
- break;
- }
- }
- break;
- }
+ int ret;
- if (sof_dai_link && sof_dai_link->be_hw_params_fixup)
- ret = sof_dai_link->be_hw_params_fixup(runtime, params);
-
- break;
- }
+ ret = mtk_sof_dai_link_fixup(rtd, params);
if (!strcmp(rtd->dai_link->name, "ETDM2_IN_BE") ||
!strcmp(rtd->dai_link->name, "ETDM1_OUT_BE")) {
- mt8195_etdm_hw_params_fixup(runtime, params);
+ mt8195_etdm_hw_params_fixup(rtd, params);
}
return ret;
}
-static int mt8195_mt6359_card_late_probe(struct snd_soc_card *card)
-{
- struct snd_soc_pcm_runtime *runtime;
- struct snd_soc_component *sof_comp = NULL;
- int i;
-
- /* 1. find sof component */
- for_each_card_rtds(card, runtime) {
- for (i = 0; i < runtime->num_components; i++) {
- if (!runtime->components[i]->driver->name)
- continue;
- if (!strcmp(runtime->components[i]->driver->name, "sof-audio-component")) {
- sof_comp = runtime->components[i];
- break;
- }
- }
- }
-
- if (!sof_comp) {
- dev_info(card->dev, " probe without component\n");
- return 0;
- }
- /* 2. add route path and fixup callback */
- for (i = 0; i < ARRAY_SIZE(g_sof_conn_streams); i++) {
- const struct sof_conn_stream *conn = &g_sof_conn_streams[i];
- struct snd_soc_pcm_runtime *sof_rtd = NULL;
- struct snd_soc_pcm_runtime *normal_rtd = NULL;
- struct snd_soc_pcm_runtime *rtd = NULL;
-
- for_each_card_rtds(card, rtd) {
- if (!strcmp(rtd->dai_link->name, conn->sof_link)) {
- sof_rtd = rtd;
- continue;
- }
- if (!strcmp(rtd->dai_link->name, conn->normal_link)) {
- normal_rtd = rtd;
- continue;
- }
- if (normal_rtd && sof_rtd)
- break;
- }
- if (normal_rtd && sof_rtd) {
- int j;
- struct snd_soc_dai *cpu_dai;
-
- for_each_rtd_cpu_dais(sof_rtd, j, cpu_dai) {
- struct snd_soc_dapm_route route;
- struct snd_soc_dapm_path *p = NULL;
- struct snd_soc_dapm_widget *play_widget =
- cpu_dai->playback_widget;
- struct snd_soc_dapm_widget *cap_widget =
- cpu_dai->capture_widget;
- memset(&route, 0, sizeof(route));
- if (conn->stream_dir == SNDRV_PCM_STREAM_CAPTURE &&
- cap_widget) {
- snd_soc_dapm_widget_for_each_sink_path(cap_widget, p) {
- route.source = conn->sof_dma;
- route.sink = p->sink->name;
- snd_soc_dapm_add_routes(&card->dapm, &route, 1);
- }
- } else if (conn->stream_dir == SNDRV_PCM_STREAM_PLAYBACK &&
- play_widget){
- snd_soc_dapm_widget_for_each_source_path(play_widget, p) {
- route.source = p->source->name;
- route.sink = conn->sof_dma;
- snd_soc_dapm_add_routes(&card->dapm, &route, 1);
- }
- } else {
- dev_err(cpu_dai->dev, "stream dir and widget not pair\n");
- }
- }
- normal_rtd->dai_link->be_hw_params_fixup = mt8195_dai_link_fixup;
- }
- }
-
- return 0;
-}
-
-static int mt8195_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
- const char *propname)
-{
- struct device *dev = card->dev;
- struct snd_soc_dai_link *link;
- const char *dai_name = NULL;
- int i, j, ret, num_links;
-
- num_links = of_property_count_strings(np, "mediatek,dai-link");
-
- if (num_links < 0 || num_links > ARRAY_SIZE(mt8195_mt6359_dai_links)) {
- dev_dbg(dev, "number of dai-link is invalid\n");
- return -EINVAL;
- }
-
- card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
- if (!card->dai_link)
- return -ENOMEM;
-
- card->num_links = 0;
- link = card->dai_link;
-
- for (i = 0; i < num_links; i++) {
- ret = of_property_read_string_index(np, propname, i, &dai_name);
- if (ret) {
- dev_dbg(dev, "ASoC: Property '%s' index %d could not be read: %d\n",
- propname, i, ret);
- return -EINVAL;
- }
-
- for (j = 0; j < ARRAY_SIZE(mt8195_mt6359_dai_links); j++) {
- if (!strcmp(dai_name, mt8195_mt6359_dai_links[j].name)) {
- memcpy(link, &mt8195_mt6359_dai_links[j],
- sizeof(struct snd_soc_dai_link));
- link++;
- card->num_links++;
- break;
- }
- }
- }
-
- if (card->num_links != num_links)
- return -EINVAL;
-
- return 0;
-}
-
static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8195_mt6359_soc_card;
struct snd_soc_dai_link *dai_link;
- struct mt8195_mt6359_priv *priv;
+ struct mtk_soc_card_data *soc_card_data;
+ struct mt8195_mt6359_priv *mach_priv;
struct device_node *platform_node, *adsp_node, *dp_node, *hdmi_node;
struct mt8195_card_data *card_data;
int is5682s = 0;
@@ -1512,17 +1360,41 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
if (strstr(card->name, "_5682s"))
is5682s = 1;
+ soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL);
+ if (!soc_card_data)
+ return -ENOMEM;
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
+ mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL);
+ if (!mach_priv)
return -ENOMEM;
+ soc_card_data->mach_priv = mach_priv;
+
+ adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
+ if (adsp_node) {
+ struct mtk_sof_priv *sof_priv;
+
+ sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
+ if (!sof_priv) {
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+ sof_priv->conn_streams = g_sof_conn_streams;
+ sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
+ sof_priv->sof_dai_link_fixup = mt8195_dai_link_fixup;
+ soc_card_data->sof_priv = sof_priv;
+ card->late_probe = mtk_sof_card_late_probe;
+ sof_on = 1;
+ }
+
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
- ret = mt8195_dailink_parse_of(card, pdev->dev.of_node,
- "mediatek,dai-link");
+ ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
+ "mediatek,dai-link",
+ mt8195_mt6359_dai_links,
+ ARRAY_SIZE(mt8195_mt6359_dai_links));
if (ret) {
dev_dbg(&pdev->dev, "Parse dai-link fail\n");
- return -EINVAL;
+ goto err_parse_of;
}
} else {
if (!sof_on)
@@ -1533,13 +1405,10 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
"mediatek,platform", 0);
if (!platform_node) {
dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_platform_node;
}
- adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
- if (adsp_node)
- sof_on = 1;
-
dp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,dptx-codec", 0);
hdmi_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,hdmi-codec", 0);
@@ -1612,17 +1481,17 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
}
}
- if (sof_on)
- card->late_probe = mt8195_mt6359_card_late_probe;
-
- snd_soc_card_set_drvdata(card, priv);
+ snd_soc_card_set_drvdata(card, soc_card_data);
ret = devm_snd_soc_register_card(&pdev->dev, card);
of_node_put(platform_node);
- of_node_put(adsp_node);
of_node_put(dp_node);
of_node_put(hdmi_node);
+err_kzalloc:
+err_parse_of:
+err_platform_node:
+ of_node_put(adsp_node);
return ret;
}
diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c
index 01f383888b62..1530e98df165 100644
--- a/sound/soc/qcom/qdsp6/q6adm.c
+++ b/sound/soc/qcom/qdsp6/q6adm.c
@@ -217,7 +217,7 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx)
idx = find_first_zero_bit(&adm->copp_bitmap[port_idx],
MAX_COPPS_PER_PORT);
- if (idx > MAX_COPPS_PER_PORT)
+ if (idx >= MAX_COPPS_PER_PORT)
return ERR_PTR(-EBUSY);
c = kzalloc(sizeof(*c), GFP_ATOMIC);
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index 9251d8548965..195780f75d05 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -513,7 +513,7 @@ int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac,
return 0;
}
- buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_ATOMIC);
+ buf = kcalloc(periods, sizeof(*buf), GFP_ATOMIC);
if (!buf) {
spin_unlock_irqrestore(&ac->lock, flags);
return -ENOMEM;
diff --git a/sound/soc/sof/intel/atom.c b/sound/soc/sof/intel/atom.c
index ff5900b155dc..bd9789b483b1 100644
--- a/sound/soc/sof/intel/atom.c
+++ b/sound/soc/sof/intel/atom.c
@@ -274,22 +274,22 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
const char *ssp_str)
{
const char *tplg_filename = NULL;
- char *filename;
- char *split_ext;
+ const char *split_ext;
+ char *filename, *tmp;
- filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
+ filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
if (!filename)
return NULL;
/* this assumes a .tplg extension */
- split_ext = strsep(&filename, ".");
- if (split_ext) {
+ tmp = filename;
+ split_ext = strsep(&tmp, ".");
+ if (split_ext)
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s-%s.tplg",
split_ext, ssp_str);
- if (!tplg_filename)
- return NULL;
- }
+ kfree(filename);
+
return tplg_filename;
}
diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c
index 31e85d4aae8c..56a533c63cb0 100644
--- a/sound/soc/sof/intel/hda-probes.c
+++ b/sound/soc/sof/intel/hda-probes.c
@@ -25,9 +25,9 @@ hda_compr_get_stream(struct snd_compr_stream *cstream)
return cstream->runtime->private_data;
}
-static int hda_probes_compr_assign(struct sof_client_dev *cdev,
- struct snd_compr_stream *cstream,
- struct snd_soc_dai *dai, u32 *stream_id)
+static int hda_probes_compr_startup(struct sof_client_dev *cdev,
+ struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai, u32 *stream_id)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
struct hdac_ext_stream *hext_stream;
@@ -45,9 +45,9 @@ static int hda_probes_compr_assign(struct sof_client_dev *cdev,
return 0;
}
-static int hda_probes_compr_free(struct sof_client_dev *cdev,
- struct snd_compr_stream *cstream,
- struct snd_soc_dai *dai)
+static int hda_probes_compr_shutdown(struct sof_client_dev *cdev,
+ struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai)
{
struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
@@ -127,8 +127,8 @@ static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
/* SOF client implementation */
static const struct sof_probes_host_ops hda_probes_ops = {
- .assign = hda_probes_compr_assign,
- .free = hda_probes_compr_free,
+ .startup = hda_probes_compr_startup,
+ .shutdown = hda_probes_compr_shutdown,
.set_params = hda_probes_compr_set_params,
.trigger = hda_probes_compr_trigger,
.pointer = hda_probes_compr_pointer,
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 4531e1ee5ed0..b58662faa4aa 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -411,6 +411,11 @@ int hda_dsp_iccmax_stream_hw_params(struct snd_sof_dev *sdev, struct hdac_ext_st
return -ENODEV;
}
+ if (!dmab) {
+ dev_err(sdev->dev, "error: no dma buffer allocated!\n");
+ return -ENODEV;
+ }
+
if (hstream->posbuf)
*hstream->posbuf = 0;
@@ -485,16 +490,16 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
return -ENODEV;
}
- /* decouple host and link DMA */
- mask = 0x1 << hstream->index;
- snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
- mask, mask);
-
if (!dmab) {
dev_err(sdev->dev, "error: no dma buffer allocated!\n");
return -ENODEV;
}
+ /* decouple host and link DMA */
+ mask = 0x1 << hstream->index;
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
+ mask, mask);
+
/* clear stream status */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
SOF_HDA_CL_DMA_SD_INT_MASK |
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index b7fa95ea1090..8639ea63a10d 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -776,13 +776,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
return tplg_filename;
}
-static int dmic_topology_fixup(struct snd_sof_dev *sdev,
- const char **tplg_filename,
- const char *idisp_str,
- int *dmic_found)
+static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev,
+ const char **tplg_filename,
+ const char *idisp_str,
+ int *dmic_found,
+ bool tplg_fixup)
{
- const char *default_tplg_filename = *tplg_filename;
- const char *fixed_tplg_filename;
const char *dmic_str;
int dmic_num;
@@ -808,14 +807,19 @@ static int dmic_topology_fixup(struct snd_sof_dev *sdev,
break;
}
- fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
- idisp_str, dmic_str);
- if (!fixed_tplg_filename)
- return -ENOMEM;
+ if (tplg_fixup) {
+ const char *default_tplg_filename = *tplg_filename;
+ const char *fixed_tplg_filename;
+
+ fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
+ idisp_str, dmic_str);
+ if (!fixed_tplg_filename)
+ return -ENOMEM;
+ *tplg_filename = fixed_tplg_filename;
+ }
dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
*dmic_found = dmic_num;
- *tplg_filename = fixed_tplg_filename;
return 0;
}
@@ -1221,6 +1225,8 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
* - one external HDAudio codec
*/
if (!*mach && codec_num <= 2) {
+ bool tplg_fixup;
+
hda_mach = snd_soc_acpi_intel_hda_machines;
dev_info(bus->dev, "using HDA machine driver %s now\n",
@@ -1232,8 +1238,15 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
idisp_str = "";
/* topology: use the info from hda_machines */
- tplg_filename = hda_mach->sof_tplg_filename;
- ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
+ if (pdata->tplg_filename) {
+ tplg_fixup = false;
+ tplg_filename = pdata->tplg_filename;
+ } else {
+ tplg_fixup = true;
+ tplg_filename = hda_mach->sof_tplg_filename;
+ }
+ ret = dmic_detect_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num,
+ tplg_fixup);
if (ret < 0)
return;
@@ -1397,30 +1410,37 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
}
if (mach && mach->link_mask) {
int dmic_num = 0;
+ bool tplg_fixup;
+ const char *tplg_filename;
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
- pdata->fw_filename = pdata->desc->default_fw_filename[pdata->ipc_type];
- pdata->tplg_filename = mach->sof_tplg_filename;
+
+ if (pdata->tplg_filename) {
+ tplg_fixup = false;
+ } else {
+ tplg_fixup = true;
+ tplg_filename = mach->sof_tplg_filename;
+ }
/*
* DMICs use up to 4 pins and are typically pin-muxed with SoundWire
- * link 2 and 3, thus we only try to enable dmics if all conditions
- * are true:
- * a) link 2 and 3 are not used by SoundWire
+ * link 2 and 3, or link 1 and 2, thus we only try to enable dmics
+ * if all conditions are true:
+ * a) 2 or fewer links are used by SoundWire
* b) the NHLT table reports the presence of microphones
*/
- if (!(mach->link_mask & GENMASK(3, 2))) {
- const char *tplg_filename = mach->sof_tplg_filename;
+ if (hweight_long(mach->link_mask) <= 2) {
int ret;
- ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num);
+ ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "",
+ &dmic_num, tplg_fixup);
if (ret < 0)
return NULL;
-
- pdata->tplg_filename = tplg_filename;
}
+ if (tplg_fixup)
+ pdata->tplg_filename = tplg_filename;
mach->mach_params.dmic_num = dmic_num;
dev_dbg(sdev->dev,
@@ -1466,18 +1486,22 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
mach = snd_soc_acpi_find_machine(desc->machines);
if (mach) {
bool add_extension = false;
+ bool tplg_fixup = false;
/*
* If tplg file name is overridden, use it instead of
* the one set in mach table
*/
- if (!sof_pdata->tplg_filename)
+ if (!sof_pdata->tplg_filename) {
sof_pdata->tplg_filename = mach->sof_tplg_filename;
+ tplg_fixup = true;
+ }
/* report to machine driver if any DMICs are found */
mach->mach_params.dmic_num = check_dmic_num(sdev);
- if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER &&
+ if (tplg_fixup &&
+ mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER &&
mach->mach_params.dmic_num) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s%d%s",
@@ -1500,8 +1524,10 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
/* report SSP link mask to machine driver */
mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev);
- if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
+ if (tplg_fixup &&
+ mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
mach->mach_params.i2s_link_mask) {
+ const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata);
int ssp_num;
if (hweight_long(mach->mach_params.i2s_link_mask) > 1 &&
@@ -1511,6 +1537,12 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
/* fls returns 1-based results, SSPs indices are 0-based */
ssp_num = fls(mach->mach_params.i2s_link_mask) - 1;
+ if (ssp_num >= chip->ssp_count) {
+ dev_err(sdev->dev, "Invalid SSP %d, max on this platform is %d\n",
+ ssp_num, chip->ssp_count);
+ return NULL;
+ }
+
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s%d",
sof_pdata->tplg_filename,
@@ -1523,7 +1555,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
add_extension = true;
}
- if (add_extension) {
+ if (tplg_fixup && add_extension) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s",
sof_pdata->tplg_filename,
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
index a5e244ea0688..96239ebb1eed 100644
--- a/sound/soc/sof/intel/mtl.c
+++ b/sound/soc/sof/intel/mtl.c
@@ -372,20 +372,9 @@ static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
(dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_RESET_TIMEOUT_US);
- if (ret < 0) {
+ if (ret < 0)
dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
__func__);
- return ret;
- }
-
- /* did core power up ? */
- dspcxctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
- if ((dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
- != MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK) {
- dev_err(sdev->dev, "power up core failed core %d adspcs %#x\n",
- core, dspcxctl);
- ret = -EIO;
- }
return ret;
}
diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c
index c573e7593808..bf423ca4e97b 100644
--- a/sound/soc/sof/ipc3-loader.c
+++ b/sound/soc/sof/ipc3-loader.c
@@ -109,7 +109,7 @@ static int ipc3_fw_ext_man_get_config_data(struct snd_sof_dev *sdev,
return 0;
}
-static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw)
+static ssize_t ipc3_fw_ext_man_size(struct snd_sof_dev *sdev, const struct firmware *fw)
{
const struct sof_ext_man_header *head;
@@ -131,6 +131,8 @@ static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw)
return head->full_size;
/* otherwise given fw don't have an extended manifest */
+ dev_dbg(sdev->dev, "Unexpected extended manifest magic number: %#x\n",
+ head->magic);
return 0;
}
@@ -147,7 +149,7 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
head = (struct sof_ext_man_header *)fw->data;
remaining = head->full_size - head->header_size;
- ext_man_size = ipc3_fw_ext_man_size(fw);
+ ext_man_size = ipc3_fw_ext_man_size(sdev, fw);
/* Assert firmware starts with extended manifest */
if (ext_man_size <= 0)
diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
index b97e63d3724a..9c6a84bdeca7 100644
--- a/sound/soc/sof/ipc3-pcm.c
+++ b/sound/soc/sof/ipc3-pcm.c
@@ -115,6 +115,9 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
pcm.params.no_stream_position = 1;
}
+ if (platform_params->cont_update_posn)
+ pcm.params.cont_update_posn = 1;
+
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
/* send hw_params IPC to the DSP */
diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
index 6a702f9dc065..732872395980 100644
--- a/sound/soc/sof/ipc4-pcm.c
+++ b/sound/soc/sof/ipc4-pcm.c
@@ -179,6 +179,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name);
+ struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc4_copier *ipc4_copier;
@@ -201,6 +202,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
snd_mask_none(fmt);
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
+ rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency;
+ rate->max = rate->min;
+
/*
* Set trigger order for capture to SND_SOC_DPCM_TRIGGER_PRE. This is required
* to ensure that the BE DAI pipeline gets stopped/suspended before the FE DAI
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 22ea628d78d0..af072b484a60 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = {
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
};
+/* SRC */
+static const struct sof_topology_token src_tokens[] = {
+ {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+ offsetof(struct sof_ipc4_src, sink_rate)},
+};
+
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
@@ -134,6 +140,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
+ [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
};
static void sof_ipc4_dbg_audio_format(struct device *dev,
@@ -307,6 +314,7 @@ static int sof_ipc4_widget_set_module_info(struct snd_sof_widget *swidget)
static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ipc4_msg *msg)
{
struct sof_ipc4_fw_module *fw_module;
+ uint32_t type;
int ret;
ret = sof_ipc4_widget_set_module_info(swidget);
@@ -323,6 +331,9 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_
msg->extension = SOF_IPC4_MOD_EXT_PPL_ID(swidget->pipeline_id);
msg->extension |= SOF_IPC4_MOD_EXT_CORE_ID(swidget->core);
+ type = fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP ? 1 : 0;
+ msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type);
+
return 0;
}
@@ -740,6 +751,58 @@ err:
return ret;
}
+static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
+{
+ struct snd_soc_component *scomp = swidget->scomp;
+ struct sof_ipc4_src *src;
+ int ret;
+
+ dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
+
+ src = kzalloc(sizeof(*src), GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+
+ swidget->private = src;
+
+ /* The out_audio_fmt in topology is ignored as it is not required by SRC */
+ ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false);
+ if (ret)
+ goto err;
+
+ ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
+ swidget->num_tuples, sizeof(src), 1);
+ if (ret) {
+ dev_err(scomp->dev, "Parsing SRC tokens failed\n");
+ goto err;
+ }
+
+ dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);
+
+ ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ sof_ipc4_free_audio_fmt(&src->available_fmt);
+ kfree(src);
+ swidget->private = NULL;
+ return ret;
+}
+
+static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
+{
+ struct sof_ipc4_src *src = swidget->private;
+
+ if (!src)
+ return;
+
+ sof_ipc4_free_audio_fmt(&src->available_fmt);
+ kfree(swidget->private);
+ swidget->private = NULL;
+}
+
static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
{
struct sof_ipc4_mixer *mixer = swidget->private;
@@ -891,7 +954,6 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev,
static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
{
- struct sof_ipc4_fw_module *fw_module = swidget->module_info;
struct sof_ipc4_copier *ipc4_copier = NULL;
struct snd_sof_widget *pipe_widget;
struct sof_ipc4_pipeline *pipeline;
@@ -925,8 +987,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
ipc4_copier->ipc_config_data = NULL;
ipc4_copier->ipc_config_size = 0;
}
-
- ida_free(&fw_module->m_ida, swidget->instance_id);
}
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
@@ -1254,15 +1314,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
/* update pipeline memory usage */
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &copier_data->base_config);
- /* assign instance ID */
- return sof_ipc4_widget_assign_instance_id(sdev, swidget);
-}
-
-static void sof_ipc4_unprepare_generic_module(struct snd_sof_widget *swidget)
-{
- struct sof_ipc4_fw_module *fw_module = swidget->module_info;
-
- ida_free(&fw_module->m_ida, swidget->instance_id);
+ return 0;
}
static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
@@ -1287,8 +1339,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
/* update pipeline memory usage */
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &gain->base_config);
- /* assign instance ID */
- return sof_ipc4_widget_assign_instance_id(sdev, swidget);
+ return 0;
}
static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
@@ -1314,8 +1365,38 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
/* update pipeline memory usage */
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &mixer->base_config);
- /* assign instance ID */
- return sof_ipc4_widget_assign_instance_id(sdev, swidget);
+ return 0;
+}
+
+static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
+ struct snd_pcm_hw_params *fe_params,
+ struct snd_sof_platform_stream_params *platform_params,
+ struct snd_pcm_hw_params *pipeline_params, int dir)
+{
+ struct snd_soc_component *scomp = swidget->scomp;
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+ struct sof_ipc4_src *src = swidget->private;
+ struct snd_interval *rate;
+ int ret;
+
+ src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt;
+
+ /* output format is not required to be sent to the FW for SRC */
+ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config,
+ NULL, pipeline_params, &src->available_fmt,
+ sizeof(src->base_config));
+ if (ret < 0)
+ return ret;
+
+ /* update pipeline memory usage */
+ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config);
+
+ /* update pipeline_params for sink widgets */
+ rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->min = src->sink_rate;
+ rate->max = rate->min;
+
+ return 0;
}
static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
@@ -1373,9 +1454,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
u32 ipc_size = 0;
int ret;
- dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n",
- swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
-
switch (swidget->id) {
case snd_soc_dapm_scheduler:
pipeline = swidget->private;
@@ -1430,21 +1508,37 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
msg = &mixer->msg;
break;
}
+ case snd_soc_dapm_src:
+ {
+ struct sof_ipc4_src *src = swidget->private;
+
+ ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate);
+ ipc_data = src;
+
+ msg = &src->msg;
+ break;
+ }
default:
dev_err(sdev->dev, "widget type %d not supported", swidget->id);
return -EINVAL;
}
if (swidget->id != snd_soc_dapm_scheduler) {
+ ret = sof_ipc4_widget_assign_instance_id(sdev, swidget);
+ if (ret < 0) {
+ dev_err(sdev->dev, "failed to assign instance id for %s\n",
+ swidget->widget->name);
+ return ret;
+ }
pipeline = pipe_widget->private;
msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK;
msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id);
msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
msg->extension |= ipc_size >> 2;
- msg->extension &= ~SOF_IPC4_MOD_EXT_DOMAIN_MASK;
- msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(pipeline->lp_mode);
}
+ dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n",
+ swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
msg->data_size = ipc_size;
msg->data_ptr = ipc_data;
@@ -1458,6 +1552,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
{
+ struct sof_ipc4_fw_module *fw_module = swidget->module_info;
int ret = 0;
/* freeing a pipeline frees all the widgets associated with it */
@@ -1480,6 +1575,8 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
pipeline->mem_usage = 0;
pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED;
+ } else {
+ ida_free(&fw_module->m_ida, swidget->instance_id);
}
return ret;
@@ -1766,6 +1863,15 @@ static enum sof_tokens mixer_token_list[] = {
SOF_COMP_EXT_TOKENS,
};
+static enum sof_tokens src_token_list[] = {
+ SOF_COMP_TOKENS,
+ SOF_SRC_TOKENS,
+ SOF_AUDIO_FMT_NUM_TOKENS,
+ SOF_IN_AUDIO_FORMAT_TOKENS,
+ SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS,
+ SOF_COMP_EXT_TOKENS,
+};
+
static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
host_token_list, ARRAY_SIZE(host_token_list), NULL,
@@ -1789,11 +1895,15 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
[snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga,
pga_token_list, ARRAY_SIZE(pga_token_list), NULL,
sof_ipc4_prepare_gain_module,
- sof_ipc4_unprepare_generic_module},
+ NULL},
[snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer,
mixer_token_list, ARRAY_SIZE(mixer_token_list),
NULL, sof_ipc4_prepare_mixer_module,
- sof_ipc4_unprepare_generic_module},
+ NULL},
+ [snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
+ src_token_list, ARRAY_SIZE(src_token_list),
+ NULL, sof_ipc4_prepare_src_module,
+ NULL},
};
const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h
index 3bc2fe38c733..0aa87a8add5d 100644
--- a/sound/soc/sof/ipc4-topology.h
+++ b/sound/soc/sof/ipc4-topology.h
@@ -15,7 +15,18 @@
#define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12)
#define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1)))
-#define SOF_IPC4_MODULE_LL BIT(5)
+#define SOF_IPC4_MODULE_LOAD_TYPE GENMASK(3, 0)
+#define SOF_IPC4_MODULE_AUTO_START BIT(4)
+/*
+ * Two module schedule domains in fw :
+ * LL domain - Low latency domain
+ * DP domain - Data processing domain
+ * The LL setting should be equal to !DP setting
+ */
+#define SOF_IPC4_MODULE_LL BIT(5)
+#define SOF_IPC4_MODULE_DP BIT(6)
+#define SOF_IPC4_MODULE_LIB_CODE BIT(7)
+
#define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12
#define SOF_IPC4_PIPELINE_OBJECT_SIZE 448
#define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128
@@ -242,4 +253,18 @@ struct sof_ipc4_mixer {
struct sof_ipc4_msg msg;
};
+/**
+ * struct sof_ipc4_src SRC config data
+ * @base_config: IPC base config data
+ * @sink_rate: Output rate for sink module
+ * @available_fmt: Available audio format
+ * @msg: IPC4 message struct containing header and data info
+ */
+struct sof_ipc4_src {
+ struct sof_ipc4_base_module_cfg base_config;
+ uint32_t sink_rate;
+ struct sof_ipc4_available_audio_format available_fmt;
+ struct sof_ipc4_msg msg;
+};
+
#endif
diff --git a/sound/soc/sof/mediatek/mt8195/mt8195-loader.c b/sound/soc/sof/mediatek/mt8195/mt8195-loader.c
index ed18d6379e92..4be99ff4ebd3 100644
--- a/sound/soc/sof/mediatek/mt8195/mt8195-loader.c
+++ b/sound/soc/sof/mediatek/mt8195/mt8195-loader.c
@@ -21,7 +21,7 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
/* pull high StatVectorSel to use AltResetVec (set bit4 to 1) */
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
- DSP_RESET_SW, DSP_RESET_SW);
+ STATVECTOR_SEL, STATVECTOR_SEL);
/* toggle DReset & BReset */
/* pull high DReset & BReset */
@@ -29,6 +29,9 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
ADSP_BRESET_SW | ADSP_DRESET_SW,
ADSP_BRESET_SW | ADSP_DRESET_SW);
+ /* delay 10 DSP cycles at 26M about 1us by IP vendor's suggestion */
+ udelay(1);
+
/* pull low DReset & BReset */
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
ADSP_BRESET_SW | ADSP_DRESET_SW,
@@ -46,11 +49,13 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
void sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
{
- /* Clear to 0 firstly */
- snd_sof_dsp_write(sdev, DSP_REG_BAR, DSP_RESET_SW, 0x0);
-
/* RUN_STALL pull high again to reset */
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
ADSP_RUNSTALL, ADSP_RUNSTALL);
+
+ /* pull high DReset & BReset */
+ snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
+ ADSP_BRESET_SW | ADSP_DRESET_SW,
+ ADSP_BRESET_SW | ADSP_DRESET_SW);
}
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index e7e78d1a8ec3..eb246b823461 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -270,9 +270,9 @@ static int sof_probes_compr_startup(struct snd_compr_stream *cstream,
if (ret)
return ret;
- ret = ops->assign(cdev, cstream, dai, &priv->extractor_stream_tag);
+ ret = ops->startup(cdev, cstream, dai, &priv->extractor_stream_tag);
if (ret) {
- dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
+ dev_err(dai->dev, "Failed to startup probe stream: %d\n", ret);
priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID;
sof_client_core_module_put(cdev);
}
@@ -310,7 +310,7 @@ exit:
priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID;
snd_compr_free_pages(cstream);
- ret = ops->free(cdev, cstream, dai);
+ ret = ops->shutdown(cdev, cstream, dai);
sof_client_core_module_put(cdev);
@@ -709,7 +709,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev,
ops = dev->platform_data;
- if (!ops->assign || !ops->free || !ops->set_params || !ops->trigger ||
+ if (!ops->startup || !ops->shutdown || !ops->set_params || !ops->trigger ||
!ops->pointer) {
dev_err(dev, "missing platform callback(s)\n");
return -ENODEV;
diff --git a/sound/soc/sof/sof-client-probes.h b/sound/soc/sof/sof-client-probes.h
index 0f9ed4569fd3..9e43f3c444f8 100644
--- a/sound/soc/sof/sof-client-probes.h
+++ b/sound/soc/sof/sof-client-probes.h
@@ -14,10 +14,10 @@ struct snd_soc_dai;
* DSP and host, like HDA.
*/
struct sof_probes_host_ops {
- int (*assign)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
- struct snd_soc_dai *dai, u32 *stream_id);
- int (*free)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
- struct snd_soc_dai *dai);
+ int (*startup)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai, u32 *stream_id);
+ int (*shutdown)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai);
int (*set_params)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
struct snd_compr_params *params,
struct snd_soc_dai *dai);
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 8bbc94907c62..823583086279 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -126,6 +126,7 @@ struct snd_sof_platform_stream_params {
bool use_phy_address;
u32 phy_addr;
bool no_ipc_position;
+ bool cont_update_posn;
};
/*