linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516
@ 2019-05-02 12:10 Fabien Parent
  2019-05-02 12:10 ` [PATCH 1/5] ASoC: mediatek: make agent_disable, msb & hd fields optional Fabien Parent
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

This patch series add a basic PCM driver for MediaTek MT8516 with only
support for ADDA Playback & Recording for now.

Fabien Parent (5):
  ASoC: mediatek: make agent_disable, msb & hd fields optional
  dt-bindings: sound: Add MT8516 AFE PCM bindings
  ASoC: mediatek: Add MT8516 PCM driver
  ASoC: mediatek: mt8516: Add ADDA DAI driver
  ASoC: mediatek: mt8516: register ADDA DAI

 .../bindings/sound/mt8516-afe-pcm.txt         |  28 +
 sound/soc/mediatek/Kconfig                    |  10 +
 sound/soc/mediatek/Makefile                   |   1 +
 sound/soc/mediatek/common/mtk-afe-fe-dai.c    |  23 +-
 sound/soc/mediatek/mt8516/Makefile            |   7 +
 sound/soc/mediatek/mt8516/mt8516-afe-common.h |  18 +
 sound/soc/mediatek/mt8516/mt8516-afe-pcm.c    | 794 ++++++++++++++++++
 sound/soc/mediatek/mt8516/mt8516-afe-regs.h   | 218 +++++
 sound/soc/mediatek/mt8516/mt8516-dai-adda.c   | 316 +++++++
 9 files changed, 1406 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt
 create mode 100644 sound/soc/mediatek/mt8516/Makefile
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-regs.h
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-dai-adda.c

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] ASoC: mediatek: make agent_disable, msb & hd fields optional
  2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
@ 2019-05-02 12:10 ` Fabien Parent
  2019-05-02 12:10 ` [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings Fabien Parent
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

Not every SoC have the following registers: agent_disable_reg,
msg_reg, and hd_reg. Make them optional in order to allow more
SoC to use the common DAI FE code.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
 sound/soc/mediatek/common/mtk-afe-fe-dai.c | 23 +++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index cf4978be062f..f39f5d8c4244 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -47,10 +47,13 @@ int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
 
 	snd_pcm_hw_constraint_step(substream->runtime, 0,
 				   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
+
 	/* enable agent */
-	mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
-			       1 << memif->data->agent_disable_shift,
-			       0 << memif->data->agent_disable_shift);
+	if (memif->data->agent_disable_shift >= 0)
+		mtk_regmap_update_bits(afe->regmap,
+				       memif->data->agent_disable_reg,
+				       1 << memif->data->agent_disable_shift,
+				       0 << memif->data->agent_disable_shift);
 
 	snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
 
@@ -143,9 +146,10 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
 			 memif->phys_buf_addr + memif->buffer_size - 1);
 
 	/* set MSB to 33-bit */
-	mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
-			       1 << memif->data->msb_shift,
-			       msb_at_bit33 << memif->data->msb_shift);
+	if (memif->data->msb_shift >= 0)
+		mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
+				       1 << memif->data->msb_shift,
+				       msb_at_bit33 << memif->data->msb_shift);
 
 	/* set channel */
 	if (memif->data->mono_shift >= 0) {
@@ -269,9 +273,10 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
-			       1 << memif->data->hd_shift,
-			       hd_audio << memif->data->hd_shift);
+	if (memif->data->hd_shift >= 0)
+		mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
+				       1 << memif->data->hd_shift,
+				       hd_audio << memif->data->hd_shift);
 
 	return 0;
 }
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings
  2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
  2019-05-02 12:10 ` [PATCH 1/5] ASoC: mediatek: make agent_disable, msb & hd fields optional Fabien Parent
@ 2019-05-02 12:10 ` Fabien Parent
  2019-05-14 20:31   ` Rob Herring
  2019-05-02 12:10 ` [PATCH 3/5] ASoC: mediatek: Add MT8516 PCM driver Fabien Parent
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

Add documentation for the bindings of the MT8516 AFE PCM driver.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
 .../bindings/sound/mt8516-afe-pcm.txt         | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt

diff --git a/Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt
new file mode 100644
index 000000000000..c5fb3c55a7f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt
@@ -0,0 +1,28 @@
+Mediatek AFE PCM controller for mt8516
+
+Required properties:
+- compatible:  "mediatek,mt8516-audio"
+- interrupts: should contain AFE interrupt
+- clocks: Must contain an entry for each entry in clock-names
+- clock-names: should have these clock names:
+		"top_pdn_audio",
+		"aud_dac_clk",
+		"aud_dac_predis_clk",
+		"aud_adc_clk";
+
+Example:
+
+
+	afe: mt8516-afe-pcm@11140000  {
+		compatible = "mediatek,mt8516-audio";
+		reg = <0 0x11140000 0 0x1000>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_AUDIO>,
+			 <&audiotop CLK_AUD_DAC>,
+			 <&audiotop CLK_AUD_DAC_PREDIS>,
+			 <&audiotop CLK_AUD_ADC>;
+		clock-names = "top_pdn_audio",
+			      "aud_dac_clk",
+			      "aud_dac_predis_clk",
+			      "aud_adc_clk";
+	};
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] ASoC: mediatek: Add MT8516 PCM driver
  2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
  2019-05-02 12:10 ` [PATCH 1/5] ASoC: mediatek: make agent_disable, msb & hd fields optional Fabien Parent
  2019-05-02 12:10 ` [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings Fabien Parent
@ 2019-05-02 12:10 ` Fabien Parent
  2019-05-02 12:10 ` [PATCH 4/5] ASoC: mediatek: mt8516: Add ADDA DAI driver Fabien Parent
  2019-05-02 12:10 ` [PATCH 5/5] ASoC: mediatek: mt8516: register ADDA DAI Fabien Parent
  4 siblings, 0 replies; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

This commit adds the PCM driver for the MediaTek MT8516 SoC.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
 sound/soc/mediatek/Kconfig                  |  10 +
 sound/soc/mediatek/Makefile                 |   1 +
 sound/soc/mediatek/mt8516/Makefile          |   6 +
 sound/soc/mediatek/mt8516/mt8516-afe-pcm.c  | 792 ++++++++++++++++++++
 sound/soc/mediatek/mt8516/mt8516-afe-regs.h | 218 ++++++
 5 files changed, 1027 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8516/Makefile
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-regs.h

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index b35410e4020e..f0bae957d475 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -116,6 +116,16 @@ config SND_SOC_MT8183
 	  Select Y if you have such device.
 	  If unsure select "N".
 
+config SND_SOC_MT8516
+	tristate "ASoC support for Mediatek MT8516 chip"
+	depends on ARCH_MEDIATEK
+	select SND_SOC_MEDIATEK
+	help
+	  This adds ASoC platform driver support for Mediatek MT8516 chip
+	  that can be used with other 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 76032cae6d51..a48500d69a8b 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -4,3 +4,4 @@ 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_MT8516) += mt8516/
diff --git a/sound/soc/mediatek/mt8516/Makefile b/sound/soc/mediatek/mt8516/Makefile
new file mode 100644
index 000000000000..6e49b01d02c2
--- /dev/null
+++ b/sound/soc/mediatek/mt8516/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+snd-soc-mt8516-afe-objs := \
+	mt8516-afe-pcm.o
+
+obj-$(CONFIG_SND_SOC_MT8516) += snd-soc-mt8516-afe.o
diff --git a/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c b/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
new file mode 100644
index 000000000000..84fbb5dbbd14
--- /dev/null
+++ b/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Copyright (c) 2019 MediaTek, Inc
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include "mt8516-afe-regs.h"
+
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-afe-fe-dai.h"
+#include "../common/mtk-base-afe.h"
+
+enum {
+	MT8516_AFE_MEMIF_DL1,
+	MT8516_AFE_MEMIF_DL2,
+	MT8516_AFE_MEMIF_VUL,
+	MT8516_AFE_MEMIF_DAI,
+	MT8516_AFE_MEMIF_AWB,
+	MT8516_AFE_MEMIF_MOD_DAI,
+	MT8516_AFE_MEMIF_HDMI,
+	MT8516_AFE_MEMIF_TDM_IN,
+	MT8516_AFE_MEMIF_MULTILINE_IN,
+	MT8516_AFE_MEMIF_NUM,
+};
+
+enum {
+	MT8516_AFE_IRQ_1 = 0,
+	MT8516_AFE_IRQ_2,
+	MT8516_AFE_IRQ_5, /* dedicated for HDMI */
+	MT8516_AFE_IRQ_7,
+	MT8516_AFE_IRQ_10, /* dedicated for TDM IN */
+	MT8516_AFE_IRQ_13, /* dedicated for ULM*/
+	MT8516_AFE_IRQ_NUM
+};
+
+struct mt8516_afe_rate {
+	unsigned int rate;
+	unsigned int regvalue;
+};
+
+static const struct mt8516_afe_rate mt8516_afe_i2s_rates[] = {
+	{ .rate = 8000, .regvalue = 0 },
+	{ .rate = 11025, .regvalue = 1 },
+	{ .rate = 12000, .regvalue = 2 },
+	{ .rate = 16000, .regvalue = 4 },
+	{ .rate = 22050, .regvalue = 5 },
+	{ .rate = 24000, .regvalue = 6 },
+	{ .rate = 32000, .regvalue = 8 },
+	{ .rate = 44100, .regvalue = 9 },
+	{ .rate = 48000, .regvalue = 10 },
+	{ .rate = 88000, .regvalue = 11 },
+	{ .rate = 96000, .regvalue = 12 },
+	{ .rate = 176400, .regvalue = 13 },
+	{ .rate = 192000, .regvalue = 14 },
+};
+
+static int mt8516_afe_i2s_fs(struct snd_pcm_substream *substream,
+				unsigned int sample_rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt8516_afe_i2s_rates); i++)
+		if (mt8516_afe_i2s_rates[i].rate == sample_rate)
+			return mt8516_afe_i2s_rates[i].regvalue;
+
+	return -EINVAL;
+}
+
+
+static int mt8516_afe_irq_fs(struct snd_pcm_substream *substream,
+		      unsigned int rate)
+{
+	return mt8516_afe_i2s_fs(substream, rate);
+}
+
+static const unsigned int mt8516_afe_backup_list[] = {
+	AUDIO_TOP_CON0,
+	AUDIO_TOP_CON1,
+	AUDIO_TOP_CON3,
+	AFE_CONN0,
+	AFE_CONN1,
+	AFE_CONN2,
+	AFE_CONN3,
+	AFE_CONN5,
+	AFE_CONN_24BIT,
+	AFE_I2S_CON,
+	AFE_I2S_CON1,
+	AFE_I2S_CON2,
+	AFE_I2S_CON3,
+	AFE_ADDA_PREDIS_CON0,
+	AFE_ADDA_PREDIS_CON1,
+	AFE_ADDA_DL_SRC2_CON0,
+	AFE_ADDA_DL_SRC2_CON1,
+	AFE_ADDA_UL_SRC_CON0,
+	AFE_ADDA_UL_SRC_CON0,
+	AFE_ADDA_NEWIF_CFG1,
+	AFE_ADDA_TOP_CON0,
+	AFE_ADDA_UL_DL_CON0,
+	AFE_MEMIF_PBUF_SIZE,
+	AFE_MEMIF_PBUF2_SIZE,
+	AFE_DAC_CON0,
+	AFE_DAC_CON1,
+	AFE_DL1_BASE,
+	AFE_DL1_END,
+	AFE_DL2_BASE,
+	AFE_DL2_END,
+	AFE_VUL_BASE,
+	AFE_VUL_END,
+	AFE_AWB_BASE,
+	AFE_AWB_END,
+	AFE_DAI_BASE,
+	AFE_DAI_END,
+	AFE_HDMI_OUT_BASE,
+	AFE_HDMI_OUT_END,
+	AFE_HDMI_IN_2CH_BASE,
+	AFE_HDMI_IN_2CH_END,
+};
+
+static const struct snd_pcm_hardware mt8516_afe_hardware = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_RESUME |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.buffer_bytes_max = 1024 * 1024,
+	.period_bytes_min = 256,
+	.period_bytes_max = 512 * 1024,
+	.periods_min = 2,
+	.periods_max = 256,
+	.fifo_size = 0,
+};
+
+static const struct snd_kcontrol_new mt8516_afe_o03_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN1, 21, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN1, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8516_afe_o04_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN2, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN2, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8516_afe_o09_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN5, 8, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8516_afe_o10_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN5, 13, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN3, 3, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget mt8516_memif_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I07", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I08", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0,
+			   mt8516_afe_o03_mix, ARRAY_SIZE(mt8516_afe_o03_mix)),
+	SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0,
+			   mt8516_afe_o04_mix, ARRAY_SIZE(mt8516_afe_o04_mix)),
+	SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0,
+			   mt8516_afe_o09_mix, ARRAY_SIZE(mt8516_afe_o09_mix)),
+	SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0,
+			   mt8516_afe_o10_mix, ARRAY_SIZE(mt8516_afe_o10_mix)),
+};
+
+static const struct snd_soc_dapm_route mt8516_memif_routes[] = {
+	/* downlink */
+	{"I05", NULL, "DL1"},
+	{"I06", NULL, "DL1"},
+	{"I07", NULL, "DL2"},
+	{"I08", NULL, "DL2"},
+	{"O03", "I05 Switch", "I05"},
+	{"O04", "I06 Switch", "I06"},
+	{"O03", "I07 Switch", "I07"},
+	{"O04", "I08 Switch", "I08"},
+
+	/* uplink */
+	{"I03", NULL, "AIN Mux"},
+	{"I04", NULL, "AIN Mux"},
+
+	{"O09", "I03 Switch", "I03"},
+	{"O10", "I04 Switch", "I04"},
+	{"VUL", NULL, "O09"},
+	{"VUL", NULL, "O10"},
+};
+
+static struct mtk_base_irq_data mt8516_irq_data[MT8516_AFE_IRQ_NUM] = {
+	[MT8516_AFE_IRQ_1] = {
+		.id = MT8516_AFE_IRQ_1,
+		.irq_cnt_reg = AFE_IRQ_CNT1,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 4,
+		.irq_fs_maskbit = 0xf,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 0,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 0,
+	},
+	[MT8516_AFE_IRQ_2] = {
+		.id = MT8516_AFE_IRQ_2,
+		.irq_cnt_reg = AFE_IRQ_CNT2,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 8,
+		.irq_fs_maskbit = 0xf,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 1,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 1,
+	},
+	[MT8516_AFE_IRQ_5] = {
+		.id = MT8516_AFE_IRQ_5,
+		.irq_cnt_reg = AFE_IRQ_CNT5,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = -1,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 3,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 4,
+	},
+	[MT8516_AFE_IRQ_7] = {
+		.id = MT8516_AFE_IRQ_7,
+		.irq_cnt_reg = AFE_IRQ_CNT7,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 24,
+		.irq_fs_maskbit = 0xf,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 14,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 6,
+	},
+	[MT8516_AFE_IRQ_10] = {
+		.id = MT8516_AFE_IRQ_10,
+		.irq_cnt_reg = AFE_IRQ_CNT10,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = -1,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 4,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 9,
+	},
+	[MT8516_AFE_IRQ_13] = {
+		.id = MT8516_AFE_IRQ_13,
+		.irq_cnt_reg = AFE_IRQ_CNT13,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = -1,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 7,
+		.irq_clr_reg = AFE_IRQ_CLR,
+		.irq_clr_shift = 12,
+	},
+};
+
+static struct mtk_base_afe_irq mt8516_irqs[MT8516_AFE_IRQ_NUM] = {
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_1] },
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_2] },
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_5] },
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_7] },
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_10] },
+	{ .irq_data = &mt8516_irq_data[MT8516_AFE_IRQ_13] },
+};
+
+static struct mtk_base_memif_data mt8516_memif_data[MT8516_AFE_MEMIF_NUM] = {
+	[MT8516_AFE_MEMIF_DL1] = {
+		.name = "DL1",
+		.id = MT8516_AFE_MEMIF_DL1,
+		.reg_ofs_base = AFE_DL1_BASE,
+		.reg_ofs_cur = AFE_DL1_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 0,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 21,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 1,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_DL2] = {
+		.name = "DL2",
+		.id = MT8516_AFE_MEMIF_DL2,
+		.reg_ofs_base = AFE_DL2_BASE,
+		.reg_ofs_cur = AFE_DL2_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 4,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 22,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 2,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_VUL] = {
+		.name = "VUL",
+		.id = MT8516_AFE_MEMIF_VUL,
+		.reg_ofs_base = AFE_VUL_BASE,
+		.reg_ofs_cur = AFE_VUL_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 16,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 27,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 3,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_DAI] = {
+		.name = "DAI",
+		.id = MT8516_AFE_MEMIF_DAI,
+		.reg_ofs_base = AFE_DAI_BASE,
+		.reg_ofs_cur = AFE_DAI_CUR,
+		.fs_reg = AFE_DAC_CON0,
+		.fs_shift = 24,
+		.fs_maskbit = 0x3,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = -1,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 4,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_AWB] = {
+		.name = "AWB",
+		.id = MT8516_AFE_MEMIF_AWB,
+		.reg_ofs_base = AFE_AWB_BASE,
+		.reg_ofs_cur = AFE_AWB_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 12,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 24,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 6,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_MOD_DAI] = {
+		.name = "MOD_DAI",
+		.id = MT8516_AFE_MEMIF_MOD_DAI,
+		.reg_ofs_base = AFE_MOD_PCM_BASE,
+		.reg_ofs_cur = AFE_MOD_PCM_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 30,
+		.fs_maskbit = 0x3,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = -1,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 7,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_HDMI] = {
+		.name = "HDMI",
+		.id = MT8516_AFE_MEMIF_HDMI,
+		.reg_ofs_base = AFE_HDMI_OUT_BASE,
+		.reg_ofs_cur = AFE_HDMI_OUT_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = -1,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = -1,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = -1,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_TDM_IN] = {
+		.name = "TDM_IN",
+		.id = MT8516_AFE_MEMIF_TDM_IN,
+		.reg_ofs_base = AFE_HDMI_IN_2CH_BASE,
+		.reg_ofs_cur = AFE_HDMI_IN_2CH_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = -1,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = -1,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = -1,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+	[MT8516_AFE_MEMIF_MULTILINE_IN] = {
+		.name = "ULM",
+		.id = MT8516_AFE_MEMIF_MULTILINE_IN,
+		.reg_ofs_base = SPDIFIN_BASE_ADR,
+		.reg_ofs_cur = SPDIFIN_CUR_ADR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = -1,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = -1,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = -1,
+		.hd_shift = -1,
+		.msb_shift = -1,
+		.agent_disable_shift = -1,
+	},
+};
+
+struct mtk_base_afe_memif mt8516_memif[] = {
+	[MT8516_AFE_MEMIF_DL1] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_DL1],
+		.irq_usage = MT8516_AFE_IRQ_1,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_DL2] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_DL2],
+		.irq_usage = MT8516_AFE_IRQ_7,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_VUL] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_VUL],
+		.irq_usage = MT8516_AFE_IRQ_2,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_DAI] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_DAI],
+		.irq_usage = MT8516_AFE_IRQ_2,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_AWB] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_AWB],
+		.irq_usage = MT8516_AFE_IRQ_2,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_MOD_DAI] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_MOD_DAI],
+		.irq_usage = MT8516_AFE_IRQ_2,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_HDMI] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_HDMI],
+		.irq_usage = MT8516_AFE_IRQ_5,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_TDM_IN] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_TDM_IN],
+		.irq_usage = MT8516_AFE_IRQ_10,
+		.const_irq = 1,
+	},
+	[MT8516_AFE_MEMIF_MULTILINE_IN] = {
+		.data = &mt8516_memif_data[MT8516_AFE_MEMIF_MULTILINE_IN],
+		.data = &mt8516_memif_data[8],
+		.irq_usage = MT8516_AFE_IRQ_13,
+		.const_irq = 1,
+	},
+};
+
+static const struct regmap_config mt8516_afe_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = ABB_AFE_SDM_TEST,
+	.cache_type = REGCACHE_NONE,
+};
+
+static irqreturn_t mt8516_afe_irq_handler(int irq, void *dev_id)
+{
+	struct mtk_base_afe *afe = dev_id;
+	unsigned int reg_value;
+	unsigned int memif_status;
+	int i, ret;
+
+	ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &reg_value);
+	if (ret) {
+		reg_value = AFE_IRQ_STATUS_BITS;
+		goto exit_irq;
+	}
+
+	ret = regmap_read(afe->regmap, AFE_DAC_CON0, &memif_status);
+	if (ret) {
+		reg_value = AFE_IRQ_STATUS_BITS;
+		goto exit_irq;
+	}
+
+	for (i = 0; i < MT8516_AFE_MEMIF_NUM; i++) {
+		struct mtk_base_afe_memif *memif = &afe->memif[i];
+		struct snd_pcm_substream *substream = memif->substream;
+		unsigned int irq_clr_shift =
+			afe->irqs[memif->irq_usage].irq_data->irq_clr_shift;
+		unsigned int enable_shift = memif->data->enable_shift;
+
+		if (!substream)
+			continue;
+
+		if (!(reg_value & (1 << irq_clr_shift)))
+			continue;
+
+		if (enable_shift >= 0 && !((1 << enable_shift) & memif_status))
+			continue;
+
+		snd_pcm_period_elapsed(substream);
+	}
+
+exit_irq:
+	regmap_write(afe->regmap, AFE_IRQ_CLR, reg_value & AFE_IRQ_STATUS_BITS);
+
+	return IRQ_HANDLED;
+}
+
+static struct snd_soc_dai_driver mt8516_memif_dai_driver[] = {
+	/* FE DAIs: memory intefaces to CPU */
+	{
+		.name = "DL1",
+		.id = MT8516_AFE_MEMIF_DL1,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.playback = {
+			.stream_name = "DL1",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "DL2",
+		.id = MT8516_AFE_MEMIF_DL2,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.playback = {
+			.stream_name = "DL2",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "VUL",
+		.id = MT8516_AFE_MEMIF_VUL,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.capture = {
+			.stream_name = "VUL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "DAI",
+		.id = MT8516_AFE_MEMIF_DAI,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.capture = {
+			.stream_name = "DAI",
+			.channels_min = 1,
+			.channels_max = 1,
+			.rates = SNDRV_PCM_RATE_8000 |
+				 SNDRV_PCM_RATE_16000 |
+				 SNDRV_PCM_RATE_32000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "HDMI",
+		.id = MT8516_AFE_MEMIF_HDMI,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.playback = {
+			.stream_name = "HDMI",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "TDM_IN",
+		.id = MT8516_AFE_MEMIF_TDM_IN,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.capture = {
+			.stream_name = "TDM_IN",
+			.channels_min = 2,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	}, {
+		.name = "ULM",
+		.id = MT8516_AFE_MEMIF_MULTILINE_IN,
+		.suspend = mtk_afe_dai_suspend,
+		.resume = mtk_afe_dai_resume,
+		.capture = {
+			.stream_name = "MULTILINE_IN",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_32000
+				| SNDRV_PCM_RATE_44100
+				| SNDRV_PCM_RATE_48000
+				| SNDRV_PCM_RATE_88200
+				| SNDRV_PCM_RATE_96000
+				| SNDRV_PCM_RATE_176400
+				| SNDRV_PCM_RATE_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE
+				| SNDRV_PCM_FMTBIT_S24_LE
+				| SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mtk_afe_fe_ops,
+	},
+};
+
+static int mt8516_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 = mt8516_memif_dai_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mt8516_memif_dai_driver);
+
+	dai->dapm_widgets = mt8516_memif_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mt8516_memif_widgets);
+	dai->dapm_routes = mt8516_memif_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mt8516_memif_routes);
+
+	return 0;
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+	mt8516_dai_memif_register,
+};
+
+static int mt8516_afe_component_probe(struct snd_soc_component *component)
+{
+	return mtk_afe_add_sub_dai_control(component);
+}
+
+static const struct snd_soc_component_driver mt8516_afe_component = {
+	.name = AFE_PCM_NAME,
+	.ops = &mtk_afe_pcm_ops,
+	.pcm_new = mtk_afe_pcm_new,
+	.pcm_free = mtk_afe_pcm_free,
+	.probe = mt8516_afe_component_probe,
+};
+
+static int mt8516_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+	int ret, i;
+	unsigned int irq_id;
+	struct mtk_base_afe *afe;
+	struct resource *res;
+	struct device_node *np = pdev->dev.of_node;
+
+	afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
+	if (!afe)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, afe);
+
+	afe->dev = &pdev->dev;
+
+	irq_id = platform_get_irq(pdev, 0);
+	if (!irq_id) {
+		dev_err(afe->dev, "np %s no irq\n", np->name);
+		return -ENXIO;
+	}
+
+	ret = devm_request_irq(afe->dev, irq_id, mt8516_afe_irq_handler,
+			       0, "Afe_ISR_Handle", (void *)afe);
+	if (ret) {
+		dev_err(afe->dev, "could not request_irq\n");
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(afe->base_addr))
+		return PTR_ERR(afe->base_addr);
+
+	afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
+		&mt8516_afe_regmap_config);
+	if (IS_ERR(afe->regmap))
+		return PTR_ERR(afe->regmap);
+
+	afe->reg_back_up_list = &mt8516_afe_backup_list[0];
+	afe->reg_back_up_list_num = ARRAY_SIZE(mt8516_afe_backup_list);
+
+	/* 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) {
+			dev_warn(afe->dev,
+				 "Failed to register dai register %d, ret %d\n",
+				 i, ret);
+			return ret;
+		}
+	}
+
+	/* init dai_driver and component_driver */
+	ret = mtk_afe_combine_sub_dai(afe);
+	if (ret) {
+		dev_warn(afe->dev, "Failed to combine sub-dais, ret %d\n", ret);
+		return ret;
+	}
+
+	afe->mtk_afe_hardware = &mt8516_afe_hardware;
+
+	afe->irqs = mt8516_irqs;
+	afe->irq_fs = mt8516_afe_irq_fs;
+
+	afe->memif = &mt8516_memif[0];
+	afe->memif_size = ARRAY_SIZE(mt8516_memif);
+	afe->memif_fs = mt8516_afe_i2s_fs;
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &mt8516_afe_component,
+					      afe->dai_drivers,
+					      afe->num_dai_drivers);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mt8516_afe_pcm_dev_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id mt8516_afe_pcm_dt_match[] = {
+	{ .compatible = "mediatek,mt8516-audio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt8516_afe_pcm_dt_match);
+
+static struct platform_driver mt8516_afe_pcm_driver = {
+	.driver = {
+		   .name = "mtk-afe-pcm",
+		   .of_match_table = mt8516_afe_pcm_dt_match,
+	},
+	.probe = mt8516_afe_pcm_dev_probe,
+	.remove = mt8516_afe_pcm_dev_remove,
+};
+
+module_platform_driver(mt8516_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Fabien Parent <fparent@baylibre.com>");
diff --git a/sound/soc/mediatek/mt8516/mt8516-afe-regs.h b/sound/soc/mediatek/mt8516/mt8516-afe-regs.h
new file mode 100644
index 000000000000..0edb19cfecf4
--- /dev/null
+++ b/sound/soc/mediatek/mt8516/mt8516-afe-regs.h
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Copyright (c) 2019 MediaTek, Inc
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#ifndef _MT8516_AFE_REGS_H_
+#define _MT8516_AFE_REGS_H_
+
+#include <linux/bitops.h>
+
+#define AUDIO_TOP_CON0		0x0000
+#define AUDIO_TOP_CON1		0x0004
+#define AUDIO_TOP_CON3		0x000c
+#define AFE_DAC_CON0		0x0010
+#define AFE_DAC_CON1		0x0014
+#define AFE_I2S_CON		0x0018
+#define AFE_I2S_CON1		0x0034
+#define AFE_I2S_CON2		0x0038
+#define AFE_I2S_CON3		0x004c
+#define AFE_DAIBT_CON0          0x001c
+#define AFE_MRGIF_CON           0x003c
+#define AFE_CONN_24BIT		0x006c
+
+#define AFE_CONN0		0x0020
+#define AFE_CONN1		0x0024
+#define AFE_CONN2		0x0028
+#define AFE_CONN3		0x002C
+#define AFE_CONN4		0x0030
+#define AFE_CONN5		0x005C
+
+/* Memory interface */
+#define AFE_DL1_BASE		0x0040
+#define AFE_DL1_CUR		0x0044
+#define AFE_DL1_END		0x0048
+#define AFE_DL2_BASE		0x0050
+#define AFE_DL2_CUR		0x0054
+#define AFE_DL2_END             0x0058
+#define AFE_AWB_BASE		0x0070
+#define AFE_AWB_END             0x0078
+#define AFE_AWB_CUR		0x007c
+#define AFE_VUL_BASE		0x0080
+#define AFE_VUL_CUR		0x008c
+#define AFE_VUL_END		0x0088
+#define AFE_DAI_BASE		0x0090
+#define AFE_DAI_END		0x0098
+#define AFE_DAI_CUR		0x009c
+#define AFE_MOD_PCM_BASE	0x0330
+#define AFE_MOD_PCM_END		0x0338
+#define AFE_MOD_PCM_CUR		0x033c
+#define AFE_HDMI_OUT_BASE	0x0374
+#define AFE_HDMI_OUT_CUR	0x0378
+#define AFE_HDMI_OUT_END	0x037c
+
+#define AFE_MEMIF_MSB           0x00cc
+#define AFE_MEMIF_MON0          0x00d0
+#define AFE_MEMIF_MON1          0x00d4
+#define AFE_MEMIF_MON2          0x00d8
+#define AFE_MEMIF_MON3          0x00dc
+
+#define AFE_ADDA_DL_SRC2_CON0   0x0108
+#define AFE_ADDA_DL_SRC2_CON1   0x010c
+#define AFE_ADDA_UL_SRC_CON0    0x0114
+#define AFE_ADDA_UL_SRC_CON1    0x0118
+#define AFE_ADDA_TOP_CON0	0x0120
+#define AFE_ADDA_UL_DL_CON0     0x0124
+#define AFE_ADDA_NEWIF_CFG0     0x0138
+#define AFE_ADDA_NEWIF_CFG1     0x013c
+#define AFE_ADDA_PREDIS_CON0    0x0260
+#define AFE_ADDA_PREDIS_CON1    0x0264
+
+#define AFE_HDMI_OUT_CON0	0x0370
+
+#define AFE_IRQ_MCU_CON		0x03a0
+#define AFE_IRQ_STATUS		0x03a4
+#define AFE_IRQ_CLR		0x03a8
+#define AFE_IRQ_CNT1		0x03ac
+#define AFE_IRQ_CNT2		0x03b0
+#define AFE_IRQ_MCU_EN		0x03b4
+#define AFE_IRQ_CNT5		0x03bc
+#define AFE_IRQ_CNT7		0x03dc
+#define AFE_IRQ_CNT13		0x0408
+#define AFE_IRQ1_MCU_CNT_MON    0x03c0
+#define AFE_IRQ2_MCU_CNT_MON    0x03c4
+#define AFE_IRQ_MCU_CON2	0x03f8
+
+#define AFE_MEMIF_PBUF_SIZE	0x03d8
+#define AFE_MEMIF_PBUF2_SIZE	0x03ec
+
+#define AFE_ASRC_CON0		0x0500
+
+#define AFE_ASRC_CON13		0x0550
+#define AFE_ASRC_CON14		0x0554
+#define AFE_ASRC_CON15		0x0558
+#define AFE_ASRC_CON16		0x055c
+#define AFE_ASRC_CON17		0x0560
+#define AFE_ASRC_CON18		0x0564
+#define AFE_ASRC_CON19		0x0568
+#define AFE_ASRC_CON20		0x056c
+#define AFE_ASRC_CON21		0x0570
+
+#define AFE_TDM_CON1		0x0548
+#define AFE_TDM_CON2		0x054c
+
+#define AFE_TDM_IN_CON1		0x0588
+#define AFE_TDM_IN_MON2		0x0594
+#define AFE_IRQ_CNT10		0x08dc
+
+#define AFE_HDMI_IN_2CH_CON0	0x09c0
+#define AFE_HDMI_IN_2CH_BASE	0x09c4
+#define AFE_HDMI_IN_2CH_END	0x09c8
+#define AFE_HDMI_IN_2CH_CUR	0x09cc
+
+#define AFE_MEMIF_MON15		0x0d7c
+#define ABB_AFE_SDM_TEST	0x0f4c
+
+#define AFE_IRQ_STATUS_BITS	0x13ff
+
+/* AFE_I2S_CON (0x0018) */
+#define AFE_I2S_CON_PHASE_SHIFT_FIX	BIT(31)
+#define AFE_I2S_CON_BCK_INV			BIT(29)
+#define AFE_I2S_CON_FROM_IO_MUX		BIT(28)
+#define AFE_I2S_CON_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON_LRCK_INV		BIT(5)
+#define AFE_I2S_CON_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON_SRC_SLAVE		BIT(2)
+#define AFE_I2S_CON_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON_EN			BIT(0)
+
+/* AFE_CONN1 (0x0024) */
+#define AFE_CONN1_I03_O03_S		BIT(19)
+
+/* AFE_CONN2 (0x0028) */
+#define AFE_CONN2_I04_O04_S		BIT(4)
+#define AFE_CONN2_I03_O04_S		BIT(3)
+
+/* AFE_I2S_CON1 (0x0034) */
+#define AFE_I2S_CON1_I2S2_TO_PAD	(1 << 18)
+#define AFE_I2S_CON1_TDMOUT_TO_PAD	(0 << 18)
+#define AFE_I2S_CON1_TDMOUT_MUX_MASK	GENMASK(18, 18)
+#define AFE_I2S_CON1_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON1_RATE(x)		(((x) & 0xf) << 8)
+#define AFE_I2S_CON1_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON1_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON1_EN			BIT(0)
+
+/* AFE_I2S_CON2 (0x0038) */
+#define AFE_I2S_CON2_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON2_RATE(x)		(((x) & 0xf) << 8)
+#define AFE_I2S_CON2_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON2_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON2_EN			BIT(0)
+
+/* AFE_I2S_CON3 (0x004C) */
+#define AFE_I2S_CON3_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON3_RATE(x)		(((x) & 0xf) << 8)
+#define AFE_I2S_CON3_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON3_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON3_EN			BIT(0)
+
+/* AFE_CONN_24BIT (0x006c) */
+#define AFE_CONN_24BIT_O10		BIT(10)
+#define AFE_CONN_24BIT_O09		BIT(9)
+#define AFE_CONN_24BIT_O06		BIT(6)
+#define AFE_CONN_24BIT_O05		BIT(5)
+#define AFE_CONN_24BIT_O04		BIT(4)
+#define AFE_CONN_24BIT_O03		BIT(3)
+#define AFE_CONN_24BIT_O02		BIT(2)
+#define AFE_CONN_24BIT_O01		BIT(1)
+#define AFE_CONN_24BIT_O00		BIT(0)
+
+/* AFE_ADDA_UL_SRC_CON0 */
+#define AFE_ADDA_UL_RATE_CH1_SHIFT	17
+#define AFE_ADDA_UL_RATE_CH1_MASK	0x3
+#define AFE_ADDA_UL_RATE_CH2_SHIFT	19
+#define AFE_ADDA_UL_RATE_CH2_MASK	0x3
+
+/* AFE_ADDA_DL_SRC2_CON0 (0x0108) */
+#define AFE_ADDA_DL_8X_UPSAMPLE		(BIT(25) | BIT(24))
+#define AFE_ADDA_DL_MUTE_OFF		(BIT(12) | BIT(11))
+#define AFE_ADDA_DL_VOICE_DATA		BIT(5)
+#define AFE_ADDA_DL_DEGRADE_GAIN	BIT(1)
+#define AFE_ADDA_DL_RATE_SHIFT	28
+
+/* AFE_ASRC_CON0 (0x0500) */
+#define AFE_ASRC_CON0_ASM_ON		BIT(0)
+#define AFE_ASRC_CON0_STR_CLR_MASK	GENMASK(6, 4)
+#define AFE_ASRC_CON0_CLR_TX		(0x1 << 4)
+#define AFE_ASRC_CON0_CLR_RX		(0x2 << 4)
+#define AFE_ASRC_CON0_CLR_I2S		(0x4 << 4)
+
+/* AFE_ASRC_CON13 (0x0550) */
+#define AFE_ASRC_CON13_16BIT		BIT(19)
+#define AFE_ASRC_CON13_MONO		BIT(16)
+
+/* AFE_ASRC_CON16 (0x055c) */
+#define AFE_ASRC_CON16_FC2_CYCLE_MASK		GENMASK(31, 16)
+#define AFE_ASRC_CON16_FC2_CYCLE(x)		(((x) - 1) << 16)
+#define AFE_ASRC_CON16_FC2_AUTO_RST		BIT(14)
+#define AFE_ASRC_CON16_TUNE_FREQ5		BIT(12)
+#define AFE_ASRC_CON16_COMP_FREQ_EN		BIT(11)
+#define AFE_ASRC_CON16_FC2_SEL			GENMASK(9, 8)
+#define AFE_ASRC_CON16_FC2_I2S_IN		(0x1 << 8)
+#define AFE_ASRC_CON16_FC2_DGL_BYPASS		BIT(7)
+#define AFE_ASRC_CON16_FC2_AUTO_RESTART		BIT(2)
+#define AFE_ASRC_CON16_FC2_FREQ			BIT(1)
+#define AFE_ASRC_CON16_FC2_EN			BIT(0)
+
+/* AFE_ADDA_NEWIF_CFG0 (0x0138) */
+#define AFE_ADDA_NEWIF_ADC_VOICE_MODE_SHIFT	10
+#define AFE_ADDA_NEWIF_ADC_VOICE_MODE_CLR	(0x3 << 10)
+
+/* AFE_SPDIF_IN */
+#define SPDIFIN_BASE_ADR			(0x0994)
+#define SPDIFIN_CUR_ADR				(0x09B8)
+
+#endif
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] ASoC: mediatek: mt8516: Add ADDA DAI driver
  2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
                   ` (2 preceding siblings ...)
  2019-05-02 12:10 ` [PATCH 3/5] ASoC: mediatek: Add MT8516 PCM driver Fabien Parent
@ 2019-05-02 12:10 ` Fabien Parent
  2019-05-02 12:10 ` [PATCH 5/5] ASoC: mediatek: mt8516: register ADDA DAI Fabien Parent
  4 siblings, 0 replies; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

Add the ADDA DAI driver for the MediaTek MT8516 SoC.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
 sound/soc/mediatek/mt8516/Makefile            |   3 +-
 sound/soc/mediatek/mt8516/mt8516-afe-common.h |  18 +
 sound/soc/mediatek/mt8516/mt8516-dai-adda.c   | 316 ++++++++++++++++++
 3 files changed, 336 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8516/mt8516-dai-adda.c

diff --git a/sound/soc/mediatek/mt8516/Makefile b/sound/soc/mediatek/mt8516/Makefile
index 6e49b01d02c2..dc05ab45560d 100644
--- a/sound/soc/mediatek/mt8516/Makefile
+++ b/sound/soc/mediatek/mt8516/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 snd-soc-mt8516-afe-objs := \
-	mt8516-afe-pcm.o
+	mt8516-afe-pcm.o \
+	mt8516-dai-adda.o
 
 obj-$(CONFIG_SND_SOC_MT8516) += snd-soc-mt8516-afe.o
diff --git a/sound/soc/mediatek/mt8516/mt8516-afe-common.h b/sound/soc/mediatek/mt8516/mt8516-afe-common.h
new file mode 100644
index 000000000000..e70877c044a4
--- /dev/null
+++ b/sound/soc/mediatek/mt8516/mt8516-afe-common.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#ifndef _MT8516_AFE_COMMON_H_
+#define _MT8516_AFE_COMMON_H_
+
+#include "../common/mtk-base-afe.h"
+
+enum {
+	MT8516_AFE_BE_ADDA,
+};
+
+int mt8516_dai_adda_register(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8516/mt8516-dai-adda.c b/sound/soc/mediatek/mt8516/mt8516-dai-adda.c
new file mode 100644
index 000000000000..76e53772d784
--- /dev/null
+++ b/sound/soc/mediatek/mt8516/mt8516-dai-adda.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Copyright (c) 2019 MediaTek, Inc
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "mt8516-afe-common.h"
+#include "mt8516-afe-regs.h"
+
+enum {
+	MTK_AFE_ADDA_DL_RATE_8K = 0,
+	MTK_AFE_ADDA_DL_RATE_11K = 1,
+	MTK_AFE_ADDA_DL_RATE_12K = 2,
+	MTK_AFE_ADDA_DL_RATE_16K = 3,
+	MTK_AFE_ADDA_DL_RATE_22K = 4,
+	MTK_AFE_ADDA_DL_RATE_24K = 5,
+	MTK_AFE_ADDA_DL_RATE_32K = 6,
+	MTK_AFE_ADDA_DL_RATE_44K = 7,
+	MTK_AFE_ADDA_DL_RATE_48K = 8,
+};
+
+enum {
+	MTK_AFE_ADDA_UL_RATE_8K = 0,
+	MTK_AFE_ADDA_UL_RATE_16K = 1,
+	MTK_AFE_ADDA_UL_RATE_32K = 2,
+	MTK_AFE_ADDA_UL_RATE_48K = 3,
+};
+
+static int mt8516_afe_setup_i2s(struct mtk_base_afe *afe,
+				    struct snd_pcm_substream *substream,
+				    unsigned int rate, int bit_width)
+{
+	int fs = afe->memif_fs(substream, rate);
+	unsigned int val;
+
+	if (bit_width > 16)
+		val |= AFE_I2S_CON1_WLEN_32BIT;
+
+	if (fs < 0)
+		return -EINVAL;
+
+	val = AFE_I2S_CON1_I2S2_TO_PAD |
+	      AFE_I2S_CON1_LOW_JITTER_CLK |
+	      AFE_I2S_CON1_RATE(fs) |
+	      AFE_I2S_CON1_FORMAT_I2S |
+	      AFE_I2S_CON1_EN;
+
+	regmap_write(afe->regmap, AFE_I2S_CON1, val);
+
+	return 0;
+}
+
+static int mt8516_afe_setup_adda_dl(struct mtk_base_afe *afe, unsigned int rate)
+{
+	unsigned int val = AFE_ADDA_DL_8X_UPSAMPLE |
+			   AFE_ADDA_DL_MUTE_OFF |
+			   AFE_ADDA_DL_DEGRADE_GAIN;
+
+	if (rate == 8000 || rate == 16000)
+		val |= AFE_ADDA_DL_VOICE_DATA;
+
+	switch (rate) {
+	case 8000:
+		val |= MTK_AFE_ADDA_DL_RATE_8K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 11025:
+		val |= MTK_AFE_ADDA_DL_RATE_11K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 12000:
+		val |= MTK_AFE_ADDA_DL_RATE_12K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 16000:
+		val |= MTK_AFE_ADDA_DL_RATE_16K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 22050:
+		val |= MTK_AFE_ADDA_DL_RATE_22K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 24000:
+		val |= MTK_AFE_ADDA_DL_RATE_24K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 32000:
+		val |= MTK_AFE_ADDA_DL_RATE_32K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 44100:
+		val |= MTK_AFE_ADDA_DL_RATE_44K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	case 48000:
+		val |= MTK_AFE_ADDA_DL_RATE_48K << AFE_ADDA_DL_RATE_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);
+	regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);
+	regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON0, val);
+	regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON1, 0xf74f0000);
+
+	return 0;
+}
+
+static int mt8516_afe_setup_adda_ul(struct mtk_base_afe *afe, unsigned int rate)
+{
+	unsigned int val = 0;
+	unsigned int val2 = 0;
+
+	switch (rate) {
+	case 8000:
+		val |= MTK_AFE_ADDA_UL_RATE_8K << AFE_ADDA_UL_RATE_CH1_SHIFT;
+		val |= MTK_AFE_ADDA_UL_RATE_8K << AFE_ADDA_UL_RATE_CH2_SHIFT;
+		val2 |= 1 << AFE_ADDA_NEWIF_ADC_VOICE_MODE_SHIFT;
+		break;
+	case 16000:
+		val |= MTK_AFE_ADDA_UL_RATE_16K << AFE_ADDA_UL_RATE_CH1_SHIFT;
+		val |= MTK_AFE_ADDA_UL_RATE_16K << AFE_ADDA_UL_RATE_CH2_SHIFT;
+		val2 |= 1 << AFE_ADDA_NEWIF_ADC_VOICE_MODE_SHIFT;
+		break;
+	case 32000:
+		val |= MTK_AFE_ADDA_UL_RATE_32K << AFE_ADDA_UL_RATE_CH1_SHIFT;
+		val |= MTK_AFE_ADDA_UL_RATE_32K << AFE_ADDA_UL_RATE_CH2_SHIFT;
+		val2 |= 1 << AFE_ADDA_NEWIF_ADC_VOICE_MODE_SHIFT;
+		break;
+	case 48000:
+		val |= MTK_AFE_ADDA_UL_RATE_48K << AFE_ADDA_UL_RATE_CH1_SHIFT;
+		val |= MTK_AFE_ADDA_UL_RATE_48K << AFE_ADDA_UL_RATE_CH2_SHIFT;
+		val2 |= 3 << AFE_ADDA_NEWIF_ADC_VOICE_MODE_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
+		(AFE_ADDA_UL_RATE_CH1_MASK << AFE_ADDA_UL_RATE_CH1_SHIFT) ||
+		(AFE_ADDA_UL_RATE_CH2_MASK << AFE_ADDA_UL_RATE_CH2_MASK), val);
+	regmap_update_bits(afe->regmap, AFE_ADDA_NEWIF_CFG1,
+		AFE_ADDA_NEWIF_ADC_VOICE_MODE_CLR, val2);
+	regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 1, 0);
+
+	return 0;
+}
+
+static void mt8516_afe_adda_shutdown(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	unsigned int stream = substream->stream;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 1, 0);
+		regmap_update_bits(afe->regmap, AFE_I2S_CON1, 1, 0);
+	} else {
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 1, 0);
+	}
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, 1, 0);
+}
+
+static int mt8516_afe_adda_hw_params(struct snd_pcm_substream *substream,
+			  struct snd_pcm_hw_params *params,
+			  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	unsigned int width_val = params_width(params) > 16 ?
+		(AFE_CONN_24BIT_O03 | AFE_CONN_24BIT_O04) : 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
+			   AFE_CONN_24BIT_O03 | AFE_CONN_24BIT_O04, width_val);
+
+	return 0;
+}
+
+static int mt8516_afe_adda_prepare(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	const unsigned int rate = substream->runtime->rate;
+	unsigned int stream = substream->stream;
+	int bit_width = snd_pcm_format_width(substream->runtime->format);
+	int ret;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = mt8516_afe_setup_adda_dl(afe, rate);
+		if (ret)
+			return ret;
+
+		ret = mt8516_afe_setup_i2s(afe, substream, rate, bit_width);
+		if (ret)
+			return ret;
+
+		regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 1, 1);
+	} else {
+		ret = mt8516_afe_setup_adda_ul(afe, rate);
+		if (ret)
+			return ret;
+
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 1, 1);
+	}
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, 1, 1);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mt8516_afe_adda_ops = {
+	.shutdown	= mt8516_afe_adda_shutdown,
+	.hw_params	= mt8516_afe_adda_hw_params,
+	.prepare	= mt8516_afe_adda_prepare,
+};
+
+static const struct snd_kcontrol_new adda_o03_o04_enable_ctl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const char * const ain_text[] = {
+	"INT ADC", "EXT ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(ain_enum, AFE_ADDA_TOP_CON0, 0, ain_text);
+
+static const struct snd_kcontrol_new ain_mux =
+	SOC_DAPM_ENUM("AIN Source", ain_enum);
+
+enum {
+	SUPPLY_SEQ_ADDA_AFE_ON,
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+	SND_SOC_DAPM_MUX("AIN Mux", SND_SOC_NOPM, 0, 0, &ain_mux),
+
+	SND_SOC_DAPM_SWITCH("ADDA O03_O04", SND_SOC_NOPM, 0, 0,
+			    &adda_o03_o04_enable_ctl),
+
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+			      AFE_DAC_CON0, 0, 0,
+			      NULL, 0),
+
+	/* Clocks */
+	SND_SOC_DAPM_CLOCK_SUPPLY("top_pdn_audio"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+	/* playback */
+	{"ADDA O03_O04", "Switch", "O03"},
+	{"ADDA O03_O04", "Switch", "O04"},
+	{"ADDA Playback", NULL, "ADDA O03_O04"},
+
+	/* capture */
+	{"AIN Mux", "INT ADC", "ADDA Capture"},
+
+	/* enable */
+	{"ADDA Playback", NULL, "ADDA Enable"},
+	{"ADDA Capture", NULL, "ADDA Enable"},
+
+	/* clock */
+	{"ADDA Playback", NULL, "aud_dac_clk"},
+	{"ADDA Playback", NULL, "aud_dac_predis_clk"},
+	{"ADDA Playback", NULL, "top_pdn_audio"},
+
+	{"ADDA Capture", NULL, "top_pdn_audio"},
+	{"ADDA Capture", NULL, "aud_adc_clk"},
+};
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+	{
+		.name = "ADDA",
+		.id = MT8516_AFE_BE_ADDA,
+		.playback = {
+			.stream_name = "ADDA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE,
+		},
+		.capture = {
+			.stream_name = "ADDA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000 |
+				 SNDRV_PCM_RATE_16000 |
+				 SNDRV_PCM_RATE_32000 |
+				 SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &mt8516_afe_adda_ops,
+	},
+};
+
+int mt8516_dai_adda_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 = mtk_dai_adda_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+
+	dai->dapm_widgets = mtk_dai_adda_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+	dai->dapm_routes = mtk_dai_adda_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+
+	return 0;
+}
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] ASoC: mediatek: mt8516: register ADDA DAI
  2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
                   ` (3 preceding siblings ...)
  2019-05-02 12:10 ` [PATCH 4/5] ASoC: mediatek: mt8516: Add ADDA DAI driver Fabien Parent
@ 2019-05-02 12:10 ` Fabien Parent
  4 siblings, 0 replies; 7+ messages in thread
From: Fabien Parent @ 2019-05-02 12:10 UTC (permalink / raw)
  To: lgirdwood, broonie, robh+dt, mark.rutland, matthias.bgg, perex,
	tiwai, kaichieh.chuang, shunli.wang
  Cc: devicetree, alsa-devel, linux-kernel, Fabien Parent,
	linux-mediatek, linux-arm-kernel

Register the ADDA DAI driver into the MT8516 PCM driver.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
 sound/soc/mediatek/mt8516/mt8516-afe-pcm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c b/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
index 84fbb5dbbd14..e1fd9290dd8f 100644
--- a/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
+++ b/sound/soc/mediatek/mt8516/mt8516-afe-pcm.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 
+#include "mt8516-afe-common.h"
 #include "mt8516-afe-regs.h"
 
 #include "../common/mtk-afe-platform-driver.h"
@@ -670,6 +671,7 @@ static int mt8516_dai_memif_register(struct mtk_base_afe *afe)
 typedef int (*dai_register_cb)(struct mtk_base_afe *);
 static const dai_register_cb dai_register_cbs[] = {
 	mt8516_dai_memif_register,
+	mt8516_dai_adda_register,
 };
 
 static int mt8516_afe_component_probe(struct snd_soc_component *component)
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings
  2019-05-02 12:10 ` [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings Fabien Parent
@ 2019-05-14 20:31   ` Rob Herring
  0 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2019-05-14 20:31 UTC (permalink / raw)
  To: Fabien Parent
  Cc: mark.rutland, devicetree, alsa-devel, linux-kernel, tiwai,
	lgirdwood, robh+dt, perex, Fabien Parent, broonie, linux-mediatek,
	shunli.wang, matthias.bgg, linux-arm-kernel, kaichieh.chuang

On Thu,  2 May 2019 14:10:38 +0200, Fabien Parent wrote:
> Add documentation for the bindings of the MT8516 AFE PCM driver.
> 
> Signed-off-by: Fabien Parent <fparent@baylibre.com>
> ---
>  .../bindings/sound/mt8516-afe-pcm.txt         | 28 +++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mt8516-afe-pcm.txt
> 

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-05-14 20:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-02 12:10 [PATCH 0/5] ASoC: mediatek: Add basic PCM driver for MT8516 Fabien Parent
2019-05-02 12:10 ` [PATCH 1/5] ASoC: mediatek: make agent_disable, msb & hd fields optional Fabien Parent
2019-05-02 12:10 ` [PATCH 2/5] dt-bindings: sound: Add MT8516 AFE PCM bindings Fabien Parent
2019-05-14 20:31   ` Rob Herring
2019-05-02 12:10 ` [PATCH 3/5] ASoC: mediatek: Add MT8516 PCM driver Fabien Parent
2019-05-02 12:10 ` [PATCH 4/5] ASoC: mediatek: mt8516: Add ADDA DAI driver Fabien Parent
2019-05-02 12:10 ` [PATCH 5/5] ASoC: mediatek: mt8516: register ADDA DAI Fabien Parent

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).