linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC
@ 2022-02-17 13:41 Jiaxin Yu
  2022-02-17 13:41 ` [v2 01/17] ASoC: mediatek: mt6366: add codec driver Jiaxin Yu
                   ` (16 more replies)
  0 siblings, 17 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This series of patches adds support for Mediatek AFE of MT8186 Soc.
Patches are based on broonie tree "for-next" branch.

Changes since v1:
  [v2 01/17]
    - add a new ID to the existing mt6358 codec driver
  [v2 03/17]
    - modify log level in DAPM events
    - use standard numeric control with name ending in Switch
    - return 1 when the value changed in mixer control's .get callback
  [v2 05/17]
    - ending in Switch to the standard on/off controls
    - change to "HW Gain 1 Volume" and "HW Gain 2 Volume"
  [v2 09/17]
    - return an error in the default case rather than just picking one of
      the behaviours when do .set_fmt
    - use the new defines that are _PROVIDER_MASK, _DAIFMT_CBP_CFP and
      _DAIFMT_CBC_CFC
  [v2 10/17]
  [v2 11/17]
    - the clock and gpio are aplit out into separate  patches

  The source file's GPL comment use c++ style, and the header fils's GPL
  comment use c style. We have added "Switch" after the names of all the
  controls that just are simple on/off.

Jiaxin Yu (17):
  ASoC: mediatek: mt6366: add codec driver
  ASoC: mediatek: mt8186: support audsys clock control
  ASoC: mediatek: mt8186: support adda in platform driver
  ASoC: mediatek: mt8186: support hostless in platform driver
  ASoC: mediatek: mt8186: support hw gain in platform driver
  ASoC: mediatek: mt8186: support i2s in platform driver
  ASoC: mediatek: mt8186: support pcm in platform driver
  ASoC: mediatek: mt8186: support src in platform driver
  ASoC: mediatek: mt8186: support tdm in platform driver
  ASoC: mediatek: mt8186: support audio clock control in platform driver
  ASoC: mediatek: mt8186: support gpio control in platform driver
  ASoC: mediatek: mt8186: add platform driver
  dt-bindings: mediatek: mt8186: add audio afe document
  ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and
    max98357
  dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357
    document
  ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and
    rt5682s
  dt-bindings: mediatek: mt8186: add mt8186-mt6366-rt1019-rt5682s
    document

 .../bindings/sound/mt8186-afe-pcm.yaml        |  175 +
 .../sound/mt8186-mt6366-da7219-max98357.yaml  |   47 +
 .../sound/mt8186-mt6366-rt1019-rt5682s.yaml   |   47 +
 sound/soc/codecs/Kconfig                      |    8 +
 sound/soc/codecs/Makefile                     |    1 +
 sound/soc/mediatek/Kconfig                    |   44 +
 sound/soc/mediatek/Makefile                   |    1 +
 sound/soc/mediatek/mt8186/Makefile            |   21 +
 sound/soc/mediatek/mt8186/mt8186-afe-clk.c    |  719 ++++
 sound/soc/mediatek/mt8186/mt8186-afe-clk.h    |  210 +
 sound/soc/mediatek/mt8186/mt8186-afe-common.h |  245 ++
 .../soc/mediatek/mt8186/mt8186-afe-control.c  |  261 ++
 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c   |  210 +
 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h   |   19 +
 sound/soc/mediatek/mt8186/mt8186-afe-pcm.c    | 3029 +++++++++++++++
 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c |  150 +
 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h |   15 +
 .../soc/mediatek/mt8186/mt8186-audsys-clkid.h |   45 +
 sound/soc/mediatek/mt8186/mt8186-dai-adda.c   |  891 +++++
 .../soc/mediatek/mt8186/mt8186-dai-hostless.c |  295 ++
 .../soc/mediatek/mt8186/mt8186-dai-hw-gain.c  |  245 ++
 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c    | 1371 +++++++
 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c    |  432 +++
 sound/soc/mediatek/mt8186/mt8186-dai-src.c    |  758 ++++
 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c    |  713 ++++
 .../mediatek/mt8186/mt8186-interconnection.h  |   69 +
 .../soc/mediatek/mt8186/mt8186-misc-control.c | 1728 +++++++++
 .../mt8186/mt8186-mt6366-da7219-max98357.c    |  910 +++++
 .../mt8186/mt8186-mt6366-rt1019-rt5682s.c     |  894 +++++
 sound/soc/mediatek/mt8186/mt8186-reg.h        | 3433 +++++++++++++++++
 30 files changed, 16986 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
 create mode 100644 sound/soc/mediatek/mt8186/Makefile
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-control.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-src.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-interconnection.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-misc-control.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-reg.h

-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 01/17] ASoC: mediatek: mt6366: add codec driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 02/17] ASoC: mediatek: mt8186: support audsys clock control Jiaxin Yu
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

Mt6366 is a new version of mt6358, and they are same about audio part.
So we can reuse the driver of mt6358.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/codecs/Kconfig  | 8 ++++++++
 sound/soc/codecs/Makefile | 1 +
 2 files changed, 9 insertions(+)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8fa24783ce01..6631094678f5 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_MT6351
 	imply SND_SOC_MT6358
 	imply SND_SOC_MT6359
+	imply SND_SOC_MT6366
 	imply SND_SOC_MT6660
 	imply SND_SOC_NAU8315
 	imply SND_SOC_NAU8540
@@ -1888,6 +1889,13 @@ config SND_SOC_MT6359_ACCDET
 	  for ASoC codec soc-jack detection mechanism.
 	  Select N if you don't have jack on board.
 
+config SND_SOC_MT6366
+	tristate "MediaTek MT6366 Codec"
+	depends on MTK_PMIC_WRAP
+	help
+	  Enable support for the platform which uses MT6366 as
+	  external codec device.
+
 config SND_SOC_MT6660
 	tristate "Mediatek MT6660 Speaker Amplifier"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 42d00aa4ee46..1279684feaf0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -465,6 +465,7 @@ obj-$(CONFIG_SND_SOC_MT6351)	+= snd-soc-mt6351.o
 obj-$(CONFIG_SND_SOC_MT6358)	+= snd-soc-mt6358.o
 obj-$(CONFIG_SND_SOC_MT6359)	+= snd-soc-mt6359.o
 obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o
+obj-$(CONFIG_SND_SOC_MT6366)	+= snd-soc-mt6358.o
 obj-$(CONFIG_SND_SOC_MT6660)	+= snd-soc-mt6660.o
 obj-$(CONFIG_SND_SOC_NAU8315)   += snd-soc-nau8315.o
 obj-$(CONFIG_SND_SOC_NAU8540)   += snd-soc-nau8540.o
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 02/17] ASoC: mediatek: mt8186: support audsys clock control
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
  2022-02-17 13:41 ` [v2 01/17] ASoC: mediatek: mt6366: add codec driver Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-17 13:41 ` [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver Jiaxin Yu
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 audio cg control.
Audio clock gates are registered to CCF for reference count and
clock parent management.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 150 ++++++++++++++++++
 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h |  15 ++
 .../soc/mediatek/mt8186/mt8186-audsys-clkid.h |  45 ++++++
 3 files changed, 210 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h

diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
new file mode 100644
index 000000000000..578969ca91c8
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-audsys-clk.h  --  Mediatek 8186 audsys clock control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include "mt8186-afe-common.h"
+#include "mt8186-audsys-clk.h"
+#include "mt8186-audsys-clkid.h"
+#include "mt8186-reg.h"
+
+struct afe_gate {
+	int id;
+	const char *name;
+	const char *parent_name;
+	int reg;
+	u8 bit;
+	const struct clk_ops *ops;
+	unsigned long flags;
+	u8 cg_flags;
+};
+
+#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.reg = _reg,					\
+		.bit = _bit,					\
+		.flags = _flags,				\
+		.cg_flags = _cgflags,				\
+	}
+
+#define GATE_AFE(_id, _name, _parent, _reg, _bit)		\
+	GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit,		\
+		       CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE)
+
+#define GATE_AUD0(_id, _name, _parent, _bit)			\
+	GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit)
+
+#define GATE_AUD1(_id, _name, _parent, _bit)			\
+	GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit)
+
+#define GATE_AUD2(_id, _name, _parent, _bit)			\
+	GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON2, _bit)
+
+static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
+	/* AUD0 */
+	GATE_AUD0(CLK_AUD_AFE, "aud_afe_clk", "top_audio", 2),
+	GATE_AUD0(CLK_AUD_22M, "aud_apll22m_clk", "top_aud_engen1", 8),
+	GATE_AUD0(CLK_AUD_24M, "aud_apll24m_clk", "top_aud_engen2", 9),
+	GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner_clk", "top_aud_engen2", 18),
+	GATE_AUD0(CLK_AUD_APLL_TUNER, "aud_apll_tuner_clk", "top_aud_engen1", 19),
+	GATE_AUD0(CLK_AUD_TDM, "aud_tdm_clk", "top_aud_1", 20),
+	GATE_AUD0(CLK_AUD_ADC, "aud_adc_clk", "top_audio", 24),
+	GATE_AUD0(CLK_AUD_DAC, "aud_dac_clk", "top_audio", 25),
+	GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis_clk", "top_audio", 26),
+	GATE_AUD0(CLK_AUD_TML, "aud_tml_clk", "top_audio", 27),
+	GATE_AUD0(CLK_AUD_NLE, "aud_nle_clk", "top_audio", 28),
+
+	/* AUD1 */
+	GATE_AUD1(CLK_AUD_I2S1_BCLK, "aud_i2s1_bclk", "top_audio", 4),
+	GATE_AUD1(CLK_AUD_I2S2_BCLK, "aud_i2s2_bclk", "top_audio", 5),
+	GATE_AUD1(CLK_AUD_I2S3_BCLK, "aud_i2s3_bclk", "top_audio", 6),
+	GATE_AUD1(CLK_AUD_I2S4_BCLK, "aud_i2s4_bclk", "top_audio", 7),
+	GATE_AUD1(CLK_AUD_CONNSYS_I2S_ASRC, "aud_connsys_i2s_asrc", "top_audio", 12),
+	GATE_AUD1(CLK_AUD_GENERAL1_ASRC, "aud_general1_asrc", "top_audio", 13),
+	GATE_AUD1(CLK_AUD_GENERAL2_ASRC, "aud_general2_asrc", "top_audio", 14),
+	GATE_AUD1(CLK_AUD_DAC_HIRES, "aud_dac_hires_clk", "top_audio_h", 15),
+	GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires_clk", "top_audio_h", 16),
+	GATE_AUD1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", "top_audio_h", 17),
+	GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "top_audio", 20),
+	GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "top_audio_h", 21),
+	GATE_AUD1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "top_audio", 28),
+	GATE_AUD1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", "top_audio", 29),
+	GATE_AUD1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", "top_audio", 30),
+	GATE_AUD1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", "top_audio_h", 31),
+
+	/* AUD2 */
+	GATE_AUD2(CLK_AUD_ETDM_IN1_BCLK, "aud_etdm_in1_bclk", "top_audio", 23),
+	GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24),
+};
+
+int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct clk *clk;
+	struct clk_lookup *cl;
+	int i;
+
+	afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK,
+					sizeof(*afe_priv->lookup),
+					GFP_KERNEL);
+
+	if (!afe_priv->lookup)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
+		const struct afe_gate *gate = &aud_clks[i];
+
+		clk = clk_register_gate(afe->dev, gate->name, gate->parent_name,
+					gate->flags, afe->base_addr + gate->reg,
+					gate->bit, gate->cg_flags, NULL);
+
+		if (IS_ERR(clk)) {
+			dev_err(afe->dev, "Failed to register clk %s: %ld\n",
+				gate->name, PTR_ERR(clk));
+			continue;
+		}
+
+		/* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */
+		cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+		if (!cl)
+			return -ENOMEM;
+
+		cl->clk = clk;
+		cl->con_id = gate->name;
+		cl->dev_id = dev_name(afe->dev);
+		clkdev_add(cl);
+
+		afe_priv->lookup[i] = cl;
+	}
+
+	return 0;
+}
+
+void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct clk *clk;
+	struct clk_lookup *cl;
+	int i;
+
+	if (!afe_priv)
+		return;
+
+	for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+		cl = afe_priv->lookup[i];
+		if (!cl)
+			continue;
+
+		clk = cl->clk;
+		clk_unregister_gate(clk);
+
+		clkdev_drop(cl);
+	}
+}
diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
new file mode 100644
index 000000000000..b8d6a06e11e8
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * mt8186-audsys-clk.h  --  Mediatek 8186 audsys clock definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8186_AUDSYS_CLK_H_
+#define _MT8186_AUDSYS_CLK_H_
+
+int mt8186_audsys_clk_register(struct mtk_base_afe *afe);
+void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h
new file mode 100644
index 000000000000..3ce5937c1823
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * mt8186-audsys-clkid.h  --  Mediatek 8186 audsys clock id definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+ */
+
+#ifndef _MT8186_AUDSYS_CLKID_H_
+#define _MT8186_AUDSYS_CLKID_H_
+
+enum{
+	CLK_AUD_AFE,
+	CLK_AUD_22M,
+	CLK_AUD_24M,
+	CLK_AUD_APLL2_TUNER,
+	CLK_AUD_APLL_TUNER,
+	CLK_AUD_TDM,
+	CLK_AUD_ADC,
+	CLK_AUD_DAC,
+	CLK_AUD_DAC_PREDIS,
+	CLK_AUD_TML,
+	CLK_AUD_NLE,
+	CLK_AUD_I2S1_BCLK,
+	CLK_AUD_I2S2_BCLK,
+	CLK_AUD_I2S3_BCLK,
+	CLK_AUD_I2S4_BCLK,
+	CLK_AUD_CONNSYS_I2S_ASRC,
+	CLK_AUD_GENERAL1_ASRC,
+	CLK_AUD_GENERAL2_ASRC,
+	CLK_AUD_DAC_HIRES,
+	CLK_AUD_ADC_HIRES,
+	CLK_AUD_ADC_HIRES_TML,
+	CLK_AUD_ADDA6_ADC,
+	CLK_AUD_ADDA6_ADC_HIRES,
+	CLK_AUD_3RD_DAC,
+	CLK_AUD_3RD_DAC_PREDIS,
+	CLK_AUD_3RD_DAC_TML,
+	CLK_AUD_3RD_DAC_HIRES,
+	CLK_AUD_ETDM_IN1_BCLK,
+	CLK_AUD_ETDM_OUT1_BCLK,
+	CLK_AUD_NR_CLK,
+};
+
+#endif
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
  2022-02-17 13:41 ` [v2 01/17] ASoC: mediatek: mt6366: add codec driver Jiaxin Yu
  2022-02-17 13:41 ` [v2 02/17] ASoC: mediatek: mt8186: support audsys clock control Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 04/17] ASoC: mediatek: mt8186: support hostless " Jiaxin Yu
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 adda dai driver

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 891 ++++++++++++++++++++
 1 file changed, 891 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
new file mode 100644
index 000000000000..6d7dd1533da0
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
@@ -0,0 +1,891 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI ADDA Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-interconnection.h"
+
+enum {
+	UL_IIR_SW = 0,
+	UL_IIR_5HZ,
+	UL_IIR_10HZ,
+	UL_IIR_25HZ,
+	UL_IIR_50HZ,
+	UL_IIR_75HZ,
+};
+
+enum {
+	AUDIO_SDM_LEVEL_MUTE = 0,
+	AUDIO_SDM_LEVEL_NORMAL = 0x1d,
+	/* if you change level normal */
+	/* you need to change formula of hp impedance and dc trim too */
+};
+
+enum {
+	AUDIO_SDM_2ND = 0,
+	AUDIO_SDM_3RD,
+};
+
+enum {
+	DELAY_DATA_MISO1 = 0,
+	DELAY_DATA_MISO2,
+};
+
+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,
+	MTK_AFE_ADDA_DL_RATE_96K = 9,
+	MTK_AFE_ADDA_DL_RATE_192K = 10,
+};
+
+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,
+	MTK_AFE_ADDA_UL_RATE_96K = 4,
+	MTK_AFE_ADDA_UL_RATE_192K = 5,
+	MTK_AFE_ADDA_UL_RATE_48K_HD = 6,
+};
+
+#define SDM_AUTO_RESET_THRESHOLD 0x190000
+
+struct mtk_afe_adda_priv {
+	int dl_rate;
+	int ul_rate;
+};
+
+static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+						       const char *name)
+{
+	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)
+		dai_id = MT8186_DAI_ADDA;
+	else
+		return NULL;
+
+	return afe_priv->dai_priv[dai_id];
+}
+
+static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe,
+					   unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_ADDA_DL_RATE_8K;
+	case 11025:
+		return MTK_AFE_ADDA_DL_RATE_11K;
+	case 12000:
+		return MTK_AFE_ADDA_DL_RATE_12K;
+	case 16000:
+		return MTK_AFE_ADDA_DL_RATE_16K;
+	case 22050:
+		return MTK_AFE_ADDA_DL_RATE_22K;
+	case 24000:
+		return MTK_AFE_ADDA_DL_RATE_24K;
+	case 32000:
+		return MTK_AFE_ADDA_DL_RATE_32K;
+	case 44100:
+		return MTK_AFE_ADDA_DL_RATE_44K;
+	case 48000:
+		return MTK_AFE_ADDA_DL_RATE_48K;
+	case 96000:
+		return MTK_AFE_ADDA_DL_RATE_96K;
+	case 192000:
+		return MTK_AFE_ADDA_DL_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_ADDA_DL_RATE_48K;
+	}
+}
+
+static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe,
+					   unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_ADDA_UL_RATE_8K;
+	case 16000:
+		return MTK_AFE_ADDA_UL_RATE_16K;
+	case 32000:
+		return MTK_AFE_ADDA_UL_RATE_32K;
+	case 48000:
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	case 96000:
+		return MTK_AFE_ADDA_UL_RATE_96K;
+	case 192000:
+		return MTK_AFE_ADDA_UL_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	}
+}
+
+/* dai component */
+static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN3, I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN3, I_DL12_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN3, I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN3, I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN3_1, I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN3_1, I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN3_1, I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN3_1, I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN3,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN3,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN3,
+				    I_GAIN1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN3,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1 Switch", AFE_CONN3,
+				    I_PCM_2_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN3_1,
+				    I_SRC_1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH1 Switch", AFE_CONN3_1,
+				    I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN4, I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN4, I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN4, I_DL12_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN4, I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN4, I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN4, I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN4, I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN4_1, I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN4_1, I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN4_1, I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN4_1, I_DL8_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN4,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN4,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN4,
+				    I_GAIN1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN4,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN4,
+				    I_PCM_1_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN4_1,
+				    I_SRC_1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH2 Switch", AFE_CONN4_1,
+				    I_SRC_2_OUT_CH2, 1, 0),
+};
+
+enum {
+	SUPPLY_SEQ_ADDA_AFE_ON,
+	SUPPLY_SEQ_ADDA_DL_ON,
+	SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
+	SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+	SUPPLY_SEQ_ADDA_FIFO,
+	SUPPLY_SEQ_ADDA_AP_DMIC,
+	SUPPLY_SEQ_ADDA_UL_ON,
+};
+
+static int mtk_adda_ul_src_dmic(struct mtk_base_afe *afe, int id)
+{
+	unsigned int reg;
+
+	switch (id) {
+	case MT8186_DAI_ADDA:
+	case MT8186_DAI_AP_DMIC:
+		reg = AFE_ADDA_UL_SRC_CON0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* dmic mode, 3.25M*/
+	regmap_update_bits(afe->regmap, reg,
+			   DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT,
+			   0x0);
+	regmap_update_bits(afe->regmap, reg,
+			   DMIC_LOW_POWER_MODE_CTL_MASK_SFT,
+			   0x0);
+
+	/* turn on dmic, ch1, ch2 */
+	regmap_update_bits(afe->regmap, reg,
+			   UL_SDM_3_LEVEL_CTL_MASK_SFT,
+			   0x1 << UL_SDM_3_LEVEL_CTL_SFT);
+	regmap_update_bits(afe->regmap, reg,
+			   UL_MODE_3P25M_CH1_CTL_MASK_SFT,
+			   0x1 << UL_MODE_3P25M_CH1_CTL_SFT);
+	regmap_update_bits(afe->regmap, reg,
+			   UL_MODE_3P25M_CH2_CTL_MASK_SFT,
+			   0x1 << UL_MODE_3P25M_CH2_CTL_SFT);
+	return 0;
+}
+
+static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int mtkaif_dmic = afe_priv->mtkaif_dmic;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n",
+		__func__, w->name, event, mtkaif_dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 1);
+
+		/* update setting to dmic */
+		if (mtkaif_dmic) {
+			/* mtkaif_rxif_data_mode = 1, dmic */
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
+					   0x1, 0x1);
+
+			/* dmic mode, 3.25M*/
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
+					   MTKAIF_RXIF_VOICE_MODE_MASK_SFT,
+					   0x0);
+			mtk_adda_ul_src_dmic(afe, MT8186_DAI_ADDA);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(125, 135);
+		mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1);
+
+		/* reset dmic */
+		afe_priv->mtkaif_dmic = 0;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_pad_top_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2)
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x38);
+		else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2)
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x30);
+		else
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x30);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int delay_data;
+	int delay_cycle;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) {
+			/* set protocol 2 */
+			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
+				     0x00010000);
+			/* mtkaif_rxif_clkinv_adc inverse */
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
+					   MTKAIF_RXIF_CLKINV_ADC_MASK_SFT,
+					   0x1 << MTKAIF_RXIF_CLKINV_ADC_SFT);
+
+			if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0) {
+				if (afe_priv->mtkaif_chosen_phase[0] < 0 &&
+				    afe_priv->mtkaif_chosen_phase[1] < 0) {
+					dev_err(afe->dev,
+						"%s(), calib fail mtkaif_chosen_phase[0/1]:%d/%d\n",
+						__func__,
+						afe_priv->mtkaif_chosen_phase[0],
+						afe_priv->mtkaif_chosen_phase[1]);
+					break;
+				}
+
+				if (afe_priv->mtkaif_chosen_phase[0] < 0 ||
+				    afe_priv->mtkaif_chosen_phase[1] < 0) {
+					dev_err(afe->dev,
+						"%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n",
+						__func__,
+						afe_priv->mtkaif_chosen_phase[0],
+						afe_priv->mtkaif_chosen_phase[1]);
+					break;
+				}
+			}
+
+			/* set delay for ch12 */
+			if (afe_priv->mtkaif_phase_cycle[0] >=
+			    afe_priv->mtkaif_phase_cycle[1]) {
+				delay_data = DELAY_DATA_MISO1;
+				delay_cycle = afe_priv->mtkaif_phase_cycle[0] -
+					      afe_priv->mtkaif_phase_cycle[1];
+			} else {
+				delay_data = DELAY_DATA_MISO2;
+				delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
+					      afe_priv->mtkaif_phase_cycle[0];
+			}
+
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_MTKAIF_RX_CFG2,
+					   MTKAIF_RXIF_DELAY_DATA_MASK_SFT,
+					   delay_data <<
+					   MTKAIF_RXIF_DELAY_DATA_SFT);
+
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_MTKAIF_RX_CFG2,
+					   MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,
+					   delay_cycle <<
+					   MTKAIF_RXIF_DELAY_CYCLE_SFT);
+
+		} else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) {
+			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
+				     0x00010000);
+		} else {
+			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(125, 135);
+		mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mt8186_adda_dmic_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->mtkaif_dmic;
+
+	return 0;
+}
+
+static int mt8186_adda_dmic_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;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int dmic_on;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	dmic_on = ucontrol->value.integer.value[0];
+
+	dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
+		 __func__, kcontrol->id.name, dmic_on);
+
+	if (afe_priv->mtkaif_dmic == dmic_on)
+		return 0;
+
+	afe_priv->mtkaif_dmic = dmic_on;
+
+	return 1;
+}
+
+static const struct snd_kcontrol_new mtk_adda_controls[] = {
+	SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1,
+		   DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0),
+	SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC Switch", 0,
+			    mt8186_adda_dmic_get, mt8186_adda_dmic_set),
+};
+
+/* ADDA UL MUX */
+enum {
+	ADDA_UL_MUX_MTKAIF = 0,
+	ADDA_UL_MUX_AP_DMIC,
+	ADDA_UL_MUX_MASK = 0x1,
+};
+
+static const char * const adda_ul_mux_map[] = {
+	"MTKAIF", "AP_DMIC"
+};
+
+static int adda_ul_map_value[] = {
+	ADDA_UL_MUX_MTKAIF,
+	ADDA_UL_MUX_AP_DMIC,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum,
+				  SND_SOC_NOPM,
+				  0,
+				  ADDA_UL_MUX_MASK,
+				  adda_ul_mux_map,
+				  adda_ul_map_value);
+
+static const struct snd_kcontrol_new adda_ul_mux_control =
+	SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch1_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch2_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+			      AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,
+			      NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
+			      AFE_ADDA_DL_SRC2_CON0,
+			      DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,
+			      mtk_adda_dl_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA_UL_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SFT, 0,
+			      mtk_adda_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("AUD_PAD_TOP", SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
+			      AFE_AUD_PAD_TOP,
+			      RG_RX_FIFO_ON_SFT, 0,
+			      mtk_adda_pad_top_event,
+			      SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_adda_mtkaif_cfg_event,
+			      SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
+			      AFE_ADDA_UL_SRC_CON0,
+			      UL_AP_DMIC_ON_SFT, 0,
+			      NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO,
+			      AFE_ADDA_UL_DL_CON0,
+			      AFE_ADDA_FIFO_AUTO_RST_SFT, 1,
+			      NULL, 0),
+
+	SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0,
+			 &adda_ul_mux_control),
+
+	SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"),
+
+	/* clock */
+	SND_SOC_DAPM_CLOCK_SUPPLY("top_mux_audio_h"),
+
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"),
+
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires_clk"),
+};
+
+#define HIRES_THRESHOLD 48000
+static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source,
+				     struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_adda_priv *adda_priv;
+
+	adda_priv = get_adda_priv_by_name(afe, w->name);
+
+	if (!adda_priv) {
+		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
+		return 0;
+	}
+
+	return (adda_priv->dl_rate > HIRES_THRESHOLD) ? 1 : 0;
+}
+
+static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source,
+				     struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_adda_priv *adda_priv;
+
+	adda_priv = get_adda_priv_by_name(afe, w->name);
+
+	if (!adda_priv) {
+		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
+		return 0;
+	}
+
+	return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+	/* playback */
+	{"ADDA_DL_CH1", "DL1_CH1 Switch", "DL1"},
+	{"ADDA_DL_CH2", "DL1_CH1 Switch", "DL1"},
+	{"ADDA_DL_CH2", "DL1_CH2 Switch", "DL1"},
+
+	{"ADDA_DL_CH1", "DL12_CH1 Switch", "DL12"},
+	{"ADDA_DL_CH2", "DL12_CH2 Switch", "DL12"},
+
+	{"ADDA_DL_CH1", "DL6_CH1 Switch", "DL6"},
+	{"ADDA_DL_CH2", "DL6_CH2 Switch", "DL6"},
+
+	{"ADDA_DL_CH1", "DL8_CH1 Switch", "DL8"},
+	{"ADDA_DL_CH2", "DL8_CH2 Switch", "DL8"},
+
+	{"ADDA_DL_CH1", "DL2_CH1 Switch", "DL2"},
+	{"ADDA_DL_CH2", "DL2_CH1 Switch", "DL2"},
+	{"ADDA_DL_CH2", "DL2_CH2 Switch", "DL2"},
+
+	{"ADDA_DL_CH1", "DL3_CH1 Switch", "DL3"},
+	{"ADDA_DL_CH2", "DL3_CH1 Switch", "DL3"},
+	{"ADDA_DL_CH2", "DL3_CH2 Switch", "DL3"},
+
+	{"ADDA_DL_CH1", "DL4_CH1 Switch", "DL4"},
+	{"ADDA_DL_CH2", "DL4_CH2 Switch", "DL4"},
+
+	{"ADDA_DL_CH1", "DL5_CH1 Switch", "DL5"},
+	{"ADDA_DL_CH2", "DL5_CH2 Switch", "DL5"},
+
+	{"ADDA Playback", NULL, "ADDA_DL_CH1"},
+	{"ADDA Playback", NULL, "ADDA_DL_CH2"},
+
+	{"ADDA Playback", NULL, "ADDA Enable"},
+	{"ADDA Playback", NULL, "ADDA Playback Enable"},
+
+	/* capture */
+	{"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"},
+	{"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"},
+
+	{"ADDA Capture", NULL, "ADDA Enable"},
+	{"ADDA Capture", NULL, "ADDA Capture Enable"},
+	{"ADDA Capture", NULL, "AUD_PAD_TOP"},
+	{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
+
+	{"AP DMIC Capture", NULL, "ADDA Enable"},
+	{"AP DMIC Capture", NULL, "ADDA Capture Enable"},
+	{"AP DMIC Capture", NULL, "ADDA_FIFO"},
+	{"AP DMIC Capture", NULL, "AP_DMIC_EN"},
+
+	{"AP DMIC Capture", NULL, "AP_DMIC_INPUT"},
+
+	/* clk */
+	{"ADDA Playback", NULL, "aud_dac_clk"},
+	{"ADDA Playback", NULL, "aud_dac_predis_clk"},
+	{"ADDA Playback", NULL, "aud_dac_hires_clk", mtk_afe_dac_hires_connect},
+
+	{"ADDA Capture Enable", NULL, "aud_adc_clk"},
+	{"ADDA Capture Enable", NULL, "aud_adc_hires_clk",
+	 mtk_afe_adc_hires_connect},
+
+	/* hires source from apll1 */
+	{"top_mux_audio_h", NULL, APLL2_W_NAME},
+
+	{"aud_dac_hires_clk", NULL, "top_mux_audio_h"},
+	{"aud_adc_hires_clk", NULL, "top_mux_audio_h"},
+};
+
+/* dai ops */
+static int mtk_dai_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);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	unsigned int rate = params_rate(params);
+	int id = dai->id;
+	struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id];
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		 __func__,
+		 id,
+		 substream->stream,
+		 rate);
+
+	if (!adda_priv) {
+		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		unsigned int dl_src2_con0 = 0;
+		unsigned int dl_src2_con1 = 0;
+
+		adda_priv->dl_rate = rate;
+
+		/* set sampling rate */
+		dl_src2_con0 = adda_dl_rate_transform(afe, rate) <<
+			       DL_2_INPUT_MODE_CTL_SFT;
+
+		/* set output mode, UP_SAMPLING_RATE_X8 */
+		dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT);
+
+		/* turn off mute function */
+		dl_src2_con0 |= (0x01 << DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);
+		dl_src2_con0 |= (0x01 << DL_2_MUTE_CH1_OFF_CTL_PRE_SFT);
+
+		/* set voice input data if input sample rate is 8k or 16k */
+		if (rate == 8000 || rate == 16000)
+			dl_src2_con0 |= 0x01 << DL_2_VOICE_MODE_CTL_PRE_SFT;
+
+		/* SA suggest apply -0.3db to audio/speech path */
+		dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL <<
+			       DL_2_GAIN_CTL_PRE_SFT;
+
+		/* turn on down-link gain */
+		dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT);
+
+		if (id == MT8186_DAI_ADDA) {
+			/* clean predistortion */
+			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, dl_src2_con0);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);
+
+			/* set sdm gain */
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_DL_SDM_DCCOMP_CON,
+					   ATTGAIN_CTL_MASK_SFT,
+					   AUDIO_SDM_LEVEL_NORMAL <<
+					   ATTGAIN_CTL_SFT);
+
+			/* Use new 2nd sdm */
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_DL_SDM_DITHER_CON,
+					   AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT,
+					   0x1 << AFE_DL_SDM_DITHER_64TAP_EN_SFT);
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_DL_SDM_AUTO_RESET_CON,
+					   AFE_DL_USE_NEW_2ND_SDM_MASK_SFT,
+					   0x1 << AFE_DL_USE_NEW_2ND_SDM_SFT);
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_DL_SDM_DCCOMP_CON,
+					   USE_3RD_SDM_MASK_SFT,
+					   AUDIO_SDM_2ND << USE_3RD_SDM_SFT);
+
+			/* sdm auto reset */
+			regmap_write(afe->regmap,
+				     AFE_ADDA_DL_SDM_AUTO_RESET_CON,
+				     SDM_AUTO_RESET_THRESHOLD);
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_DL_SDM_AUTO_RESET_CON,
+					   SDM_AUTO_RESET_TEST_ON_MASK_SFT,
+					   0x1 << SDM_AUTO_RESET_TEST_ON_SFT);
+		}
+	} else {
+		unsigned int voice_mode = 0;
+		unsigned int ul_src_con0 = 0;	/* default value */
+
+		adda_priv->ul_rate = rate;
+
+		voice_mode = adda_ul_rate_transform(afe, rate);
+
+		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
+
+		/* enable iir */
+		ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
+			       UL_IIR_ON_TMP_CTL_MASK_SFT;
+		ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
+			       UL_IIRMODE_CTL_MASK_SFT;
+		switch (id) {
+		case MT8186_DAI_ADDA:
+		case MT8186_DAI_AP_DMIC:
+			/* 35Hz @ 48k */
+			regmap_write(afe->regmap,
+				     AFE_ADDA_IIR_COEF_02_01, 0x00000000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_IIR_COEF_06_05, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_IIR_COEF_08_07, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_IIR_COEF_10_09, 0x0000C048);
+
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL_SRC_CON0, ul_src_con0);
+
+			/* Using Internal ADC */
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_TOP_CON0,
+					   0x1 << 0,
+					   0x0 << 0);
+
+			/* mtkaif_rxif_data_mode = 0, amic */
+			regmap_update_bits(afe->regmap,
+					   AFE_ADDA_MTKAIF_RX_CFG0,
+					   0x1 << 0,
+					   0x0 << 0);
+			break;
+		default:
+			break;
+		}
+
+		/* ap dmic */
+		switch (id) {
+		case MT8186_DAI_AP_DMIC:
+			mtk_adda_ul_src_dmic(afe, id);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+	.hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+				 SNDRV_PCM_RATE_96000 |\
+				 SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+				SNDRV_PCM_RATE_16000 |\
+				SNDRV_PCM_RATE_32000 |\
+				SNDRV_PCM_RATE_48000 |\
+				SNDRV_PCM_RATE_96000 |\
+				SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			  SNDRV_PCM_FMTBIT_S24_LE |\
+			  SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+	{
+		.name = "ADDA",
+		.id = MT8186_DAI_ADDA,
+		.playback = {
+			.stream_name = "ADDA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_PLAYBACK_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.capture = {
+			.stream_name = "ADDA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "AP_DMIC",
+		.id = MT8186_DAI_AP_DMIC,
+		.capture = {
+			.stream_name = "AP DMIC Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+};
+
+int mt8186_dai_adda_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	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->controls = mtk_adda_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_adda_controls);
+	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);
+
+	/* set dai priv */
+	ret = mt8186_dai_set_priv(afe, MT8186_DAI_ADDA,
+				  sizeof(struct mtk_afe_adda_priv), NULL);
+	if (ret)
+		return ret;
+
+	/* ap dmic priv share with adda */
+	afe_priv->dai_priv[MT8186_DAI_AP_DMIC] =
+		afe_priv->dai_priv[MT8186_DAI_ADDA];
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 04/17] ASoC: mediatek: mt8186: support hostless in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (2 preceding siblings ...)
  2022-02-17 13:41 ` [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 05/17] ASoC: mediatek: mt8186: support hw gain " Jiaxin Yu
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 hostless dai driver.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../soc/mediatek/mt8186/mt8186-dai-hostless.c | 295 ++++++++++++++++++
 1 file changed, 295 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hostless.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
new file mode 100644
index 000000000000..37460a3acc93
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI Hostless Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include "mt8186-afe-common.h"
+
+static const struct snd_pcm_hardware mt8186_hostless_hardware = {
+	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_MMAP_VALID),
+	.period_bytes_min = 256,
+	.period_bytes_max = 4 * 48 * 1024,
+	.periods_min = 2,
+	.periods_max = 256,
+	.buffer_bytes_max = 4 * 48 * 1024,
+	.fifo_size = 0,
+};
+
+/* dai component */
+static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = {
+	/* Hostless ADDA Loopback */
+	{"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
+	{"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
+	{"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
+	{"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
+	{"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
+	{"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
+	{"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
+	{"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
+	{"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
+	{"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
+	{"Hostless LPBK UL", NULL, "ADDA_UL_Mux"},
+
+	/* Hostelss FM */
+	/* connsys_i2s to hw gain 1*/
+	{"Hostless FM UL", NULL, "Connsys I2S"},
+
+	{"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"},
+	{"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"},
+	/* hw gain to adda dl */
+	{"Hostless FM UL", NULL, "HW Gain 1 Out"},
+
+	{"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
+	{"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
+	/* hw gain to i2s3 */
+	{"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
+	{"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
+	/* hw gain to i2s1 */
+	{"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
+	{"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
+
+	/* Hostless_SRC */
+	{"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
+	{"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
+	{"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
+	{"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
+	{"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
+	{"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
+	{"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"},
+
+	/* Hostless_SRC_bargein */
+	{"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"},
+	{"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"},
+	{"Hostless_SRC_Bargein_UL", NULL, "I2S0"},
+
+	/* Hostless AAudio */
+	{"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"},
+	{"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"},
+	{"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"},
+	{"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"},
+};
+
+/* dai ops */
+static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
+
+	snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware);
+
+	ret = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		dev_info(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
+	return ret;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_hostless_ops = {
+	.startup = mtk_dai_hostless_startup,
+};
+
+/* dai driver */
+#define MTK_HOSTLESS_RATES (SNDRV_PCM_RATE_8000_48000 |\
+			   SNDRV_PCM_RATE_88200 |\
+			   SNDRV_PCM_RATE_96000 |\
+			   SNDRV_PCM_RATE_176400 |\
+			   SNDRV_PCM_RATE_192000)
+
+#define MTK_HOSTLESS_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			     SNDRV_PCM_FMTBIT_S24_LE |\
+			     SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_hostless_driver[] = {
+	{
+		.name = "Hostless LPBK DAI",
+		.id = MT8186_DAI_HOSTLESS_LPBK,
+		.playback = {
+			.stream_name = "Hostless LPBK DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Hostless LPBK UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless FM DAI",
+		.id = MT8186_DAI_HOSTLESS_FM,
+		.playback = {
+			.stream_name = "Hostless FM DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Hostless FM UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_SRC_1_DAI",
+		.id = MT8186_DAI_HOSTLESS_SRC_1,
+		.playback = {
+			.stream_name = "Hostless_SRC_1_DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Hostless_SRC_1_UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_SRC_Bargein_DAI",
+		.id = MT8186_DAI_HOSTLESS_SRC_BARGEIN,
+		.playback = {
+			.stream_name = "Hostless_SRC_Bargein_DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Hostless_SRC_Bargein_UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	/* BE dai */
+	{
+		.name = "Hostless_UL1 DAI",
+		.id = MT8186_DAI_HOSTLESS_UL1,
+		.capture = {
+			.stream_name = "Hostless_UL1 UL",
+			.channels_min = 1,
+			.channels_max = 4,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_UL2 DAI",
+		.id = MT8186_DAI_HOSTLESS_UL2,
+		.capture = {
+			.stream_name = "Hostless_UL2 UL",
+			.channels_min = 1,
+			.channels_max = 4,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_UL3 DAI",
+		.id = MT8186_DAI_HOSTLESS_UL3,
+		.capture = {
+			.stream_name = "Hostless_UL3 UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_UL5 DAI",
+		.id = MT8186_DAI_HOSTLESS_UL5,
+		.capture = {
+			.stream_name = "Hostless_UL5 UL",
+			.channels_min = 1,
+			.channels_max = 12,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless_UL6 DAI",
+		.id = MT8186_DAI_HOSTLESS_UL6,
+		.capture = {
+			.stream_name = "Hostless_UL6 UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless HW Gain AAudio DAI",
+		.id = MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO,
+		.capture = {
+			.stream_name = "Hostless HW Gain AAudio In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+	{
+		.name = "Hostless SRC AAudio DAI",
+		.id = MT8186_DAI_HOSTLESS_SRC_AAUDIO,
+		.playback = {
+			.stream_name = "Hostless SRC AAudio DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Hostless SRC AAudio UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HOSTLESS_RATES,
+			.formats = MTK_HOSTLESS_FORMATS,
+		},
+		.ops = &mtk_dai_hostless_ops,
+	},
+};
+
+int mt8186_dai_hostless_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_hostless_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_hostless_driver);
+
+	dai->dapm_routes = mtk_dai_hostless_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hostless_routes);
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 05/17] ASoC: mediatek: mt8186: support hw gain in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (3 preceding siblings ...)
  2022-02-17 13:41 ` [v2 04/17] ASoC: mediatek: mt8186: support hostless " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 06/17] ASoC: mediatek: mt8186: support i2s " Jiaxin Yu
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This path adds mt8186 hw gain dai driver.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../soc/mediatek/mt8186/mt8186-dai-hw-gain.c  | 245 ++++++++++++++++++
 1 file changed, 245 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
new file mode 100644
index 000000000000..796878989727
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI HW Gain Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/regmap.h>
+#include "mt8186-afe-common.h"
+#include "mt8186-interconnection.h"
+
+#define HW_GAIN_1_EN_W_NAME "HW GAIN 1 Enable"
+#define HW_GAIN_2_EN_W_NAME "HW GAIN 2 Enable"
+
+/* dai component */
+static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13_1,
+				    I_CONNSYS_I2S_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14_1,
+				    I_CONNSYS_I2S_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain2_in_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN15,
+				    I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain2_in_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN16,
+				    I_ADDA_UL_CH2, 1, 0),
+};
+
+static int mtk_hw_gain_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int gain_cur;
+	unsigned int gain_con1;
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (strcmp(w->name, HW_GAIN_1_EN_W_NAME) == 0) {
+			gain_cur = AFE_GAIN1_CUR;
+			gain_con1 = AFE_GAIN1_CON1;
+		} else {
+			gain_cur = AFE_GAIN2_CUR;
+			gain_con1 = AFE_GAIN2_CON1;
+		}
+
+		/* let hw gain ramp up, set cur gain to 0 */
+		regmap_update_bits(afe->regmap,
+				   gain_cur,
+				   AFE_GAIN1_CUR_MASK_SFT,
+				   0);
+
+		/* set target gain to 0 */
+		regmap_update_bits(afe->regmap,
+				   gain_con1,
+				   GAIN1_TARGET_MASK_SFT,
+				   0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget mtk_dai_hw_gain_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain1_in_ch1_mix,
+			   ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)),
+	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain1_in_ch2_mix,
+			   ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)),
+	SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain2_in_ch1_mix,
+			   ARRAY_SIZE(mtk_hw_gain2_in_ch1_mix)),
+	SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain2_in_ch2_mix,
+			   ARRAY_SIZE(mtk_hw_gain2_in_ch2_mix)),
+
+	SND_SOC_DAPM_SUPPLY(HW_GAIN_1_EN_W_NAME,
+			    AFE_GAIN1_CON0, GAIN1_ON_SFT, 0,
+			    mtk_hw_gain_event,
+			    SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_SUPPLY(HW_GAIN_2_EN_W_NAME,
+			    AFE_GAIN2_CON0, GAIN2_ON_SFT, 0,
+			    mtk_hw_gain_event,
+			    SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"),
+	SND_SOC_DAPM_INPUT("HW Gain 2 Out Endpoint"),
+	SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_hw_gain_routes[] = {
+	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"},
+	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"},
+	{"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH1"},
+	{"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH2"},
+
+	{"HW Gain 1 In", NULL, HW_GAIN_1_EN_W_NAME},
+	{"HW Gain 1 Out", NULL, HW_GAIN_1_EN_W_NAME},
+	{"HW Gain 2 In", NULL, HW_GAIN_2_EN_W_NAME},
+	{"HW Gain 2 Out", NULL, HW_GAIN_2_EN_W_NAME},
+
+	{"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"},
+	{"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"},
+	{"HW Gain 2 Out", NULL, "HW Gain 2 Out Endpoint"},
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain_controls[] = {
+	SOC_SINGLE("HW Gain 1 Volume", AFE_GAIN1_CON1,
+		   GAIN1_TARGET_SFT, GAIN1_TARGET_MASK, 0),
+	SOC_SINGLE("HW Gain 2 Volume", AFE_GAIN2_CON1,
+		   GAIN2_TARGET_SFT, GAIN2_TARGET_MASK, 0),
+};
+
+/* dai ops */
+static int mtk_dai_gain_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 rate = params_rate(params);
+	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id);
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		 __func__,
+		 dai->id,
+		 substream->stream,
+		 rate);
+
+	/* rate */
+	regmap_update_bits(afe->regmap,
+			   dai->id == MT8186_DAI_HW_GAIN_1 ?
+			   AFE_GAIN1_CON0 : AFE_GAIN2_CON0,
+			   GAIN1_MODE_MASK_SFT,
+			   rate_reg << GAIN1_MODE_SFT);
+
+	/* sample per step */
+	regmap_update_bits(afe->regmap,
+			   dai->id == MT8186_DAI_HW_GAIN_1 ?
+			   AFE_GAIN1_CON0 : AFE_GAIN2_CON0,
+			   GAIN1_SAMPLE_PER_STEP_MASK_SFT,
+			   (dai->id == MT8186_DAI_HW_GAIN_1 ? 0x40 : 0x0) <<
+			   GAIN1_SAMPLE_PER_STEP_SFT);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_gain_ops = {
+	.hw_params = mtk_dai_gain_hw_params,
+};
+
+/* dai driver */
+#define MTK_HW_GAIN_RATES (SNDRV_PCM_RATE_8000_48000 |\
+			   SNDRV_PCM_RATE_88200 |\
+			   SNDRV_PCM_RATE_96000 |\
+			   SNDRV_PCM_RATE_176400 |\
+			   SNDRV_PCM_RATE_192000)
+
+#define MTK_HW_GAIN_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			     SNDRV_PCM_FMTBIT_S24_LE |\
+			     SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_gain_driver[] = {
+	{
+		.name = "HW Gain 1",
+		.id = MT8186_DAI_HW_GAIN_1,
+		.playback = {
+			.stream_name = "HW Gain 1 In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HW_GAIN_RATES,
+			.formats = MTK_HW_GAIN_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HW Gain 1 Out",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HW_GAIN_RATES,
+			.formats = MTK_HW_GAIN_FORMATS,
+		},
+		.ops = &mtk_dai_gain_ops,
+		.symmetric_rate = 1,
+		.symmetric_channels = 1,
+		.symmetric_sample_bits = 1,
+	},
+	{
+		.name = "HW Gain 2",
+		.id = MT8186_DAI_HW_GAIN_2,
+		.playback = {
+			.stream_name = "HW Gain 2 In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HW_GAIN_RATES,
+			.formats = MTK_HW_GAIN_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HW Gain 2 Out",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_HW_GAIN_RATES,
+			.formats = MTK_HW_GAIN_FORMATS,
+		},
+		.ops = &mtk_dai_gain_ops,
+		.symmetric_rate = 1,
+		.symmetric_channels = 1,
+		.symmetric_sample_bits = 1,
+	},
+};
+
+int mt8186_dai_hw_gain_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_gain_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_gain_driver);
+
+	dai->controls = mtk_hw_gain_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_hw_gain_controls);
+	dai->dapm_widgets = mtk_dai_hw_gain_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_hw_gain_widgets);
+	dai->dapm_routes = mtk_dai_hw_gain_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hw_gain_routes);
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 06/17] ASoC: mediatek: mt8186: support i2s in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (4 preceding siblings ...)
  2022-02-17 13:41 ` [v2 05/17] ASoC: mediatek: mt8186: support hw gain " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 07/17] ASoC: mediatek: mt8186: support pcm " Jiaxin Yu
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 i2s dai driver

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c | 1371 ++++++++++++++++++++
 1 file changed, 1371 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
new file mode 100644
index 000000000000..d6db5f6a7315
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
@@ -0,0 +1,1371 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI I2S Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-interconnection.h"
+
+enum {
+	I2S_FMT_EIAJ = 0,
+	I2S_FMT_I2S = 1,
+};
+
+enum {
+	I2S_WLEN_16_BIT = 0,
+	I2S_WLEN_32_BIT = 1,
+};
+
+enum {
+	I2S_HD_NORMAL = 0,
+	I2S_HD_LOW_JITTER = 1,
+};
+
+enum {
+	I2S1_SEL_O28_O29 = 0,
+	I2S1_SEL_O03_O04 = 1,
+};
+
+enum {
+	I2S_IN_PAD_CONNSYS = 0,
+	I2S_IN_PAD_IO_MUX = 1,
+};
+
+struct mtk_afe_i2s_priv {
+	int id;
+	int rate; /* for determine which apll to use */
+	int low_jitter_en;
+	int master; /* only i2s0 has slave mode*/
+
+	const char *share_property_name;
+	int share_i2s_id;
+
+	int mclk_id;
+	int mclk_rate;
+	int mclk_apll;
+};
+
+static unsigned int get_i2s_wlen(snd_pcm_format_t format)
+{
+	return snd_pcm_format_physical_width(format) <= 16 ?
+	       I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;
+}
+
+#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"
+#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"
+#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"
+#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"
+#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux"
+
+#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"
+#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"
+#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"
+#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"
+
+#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"
+#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"
+#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"
+#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"
+
+static int get_i2s_id_by_name(struct mtk_base_afe *afe,
+			      const char *name)
+{
+	if (strncmp(name, "I2S0", 4) == 0)
+		return MT8186_DAI_I2S_0;
+	else if (strncmp(name, "I2S1", 4) == 0)
+		return MT8186_DAI_I2S_1;
+	else if (strncmp(name, "I2S2", 4) == 0)
+		return MT8186_DAI_I2S_2;
+	else if (strncmp(name, "I2S3", 4) == 0)
+		return MT8186_DAI_I2S_3;
+	else
+		return -EINVAL;
+}
+
+static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,
+						     const char *name)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_i2s_id_by_name(afe, name);
+
+	if (dai_id < 0)
+		return NULL;
+
+	return afe_priv->dai_priv[dai_id];
+}
+
+/* low jitter control */
+static const char * const mt8186_i2s_hd_str[] = {
+	"Normal", "Low_Jitter"
+};
+
+static const struct soc_enum mt8186_i2s_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str),
+			    mt8186_i2s_hd_str),
+};
+
+/* clock source control */
+static const char * const mt8186_i2s_src_str[] = {
+	"Master", "Slave"
+};
+
+static const struct soc_enum mt8186_i2s_src_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_src_str),
+			    mt8186_i2s_src_str),
+};
+
+static int mt8186_i2s_hd_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 mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
+
+	return 0;
+}
+
+static int mt8186_i2s_hd_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 mtk_afe_i2s_priv *i2s_priv;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int hd_en;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	hd_en = ucontrol->value.integer.value[0];
+
+	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
+		 __func__, kcontrol->id.name, hd_en);
+
+	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	i2s_priv->low_jitter_en = hd_en;
+
+	return 0;
+}
+
+static int mt8186_i2s_src_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 mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = i2s_priv->master;
+
+	return 0;
+}
+
+static int mt8186_i2s_src_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 mtk_afe_i2s_priv *i2s_priv;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int clk_src;
+	int dai_id;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	clk_src = ucontrol->value.integer.value[0];
+
+	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
+		 __func__, kcontrol->id.name, clk_src);
+
+	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
+	dai_id = get_i2s_id_by_name(afe, kcontrol->id.name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	switch (dai_id) {
+	case MT8186_DAI_I2S_0:
+		regmap_update_bits(afe->regmap, AFE_I2S_CON,
+				   I2S_SRC_MASK_SFT,
+				   clk_src << I2S_SRC_SFT);
+		break;
+	default:
+		break;
+	}
+
+	i2s_priv->master = clk_src;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {
+	SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8186_i2s_enum[0],
+		     mt8186_i2s_hd_get, mt8186_i2s_hd_set),
+	SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8186_i2s_enum[0],
+		     mt8186_i2s_hd_get, mt8186_i2s_hd_set),
+	SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8186_i2s_enum[0],
+		     mt8186_i2s_hd_get, mt8186_i2s_hd_set),
+	SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8186_i2s_enum[0],
+		     mt8186_i2s_hd_get, mt8186_i2s_hd_set),
+	SOC_ENUM_EXT(MTK_AFE_I2S0_SRC_KCONTROL_NAME, mt8186_i2s_src_enum[0],
+		     mt8186_i2s_src_get, mt8186_i2s_src_set),
+};
+
+/* dai component */
+/* i2s virtual mux to output widget */
+static const char * const i2s_mux_map[] = {
+	"Normal", "Dummy_Widget",
+};
+
+static int i2s_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum,
+					      SND_SOC_NOPM,
+					      0,
+					      1,
+					      i2s_mux_map,
+					      i2s_mux_map_value);
+
+static const struct snd_kcontrol_new i2s0_in_mux_control =
+	SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum);
+
+static const struct snd_kcontrol_new i2s1_out_mux_control =
+	SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum);
+
+static const struct snd_kcontrol_new i2s2_in_mux_control =
+	SOC_DAPM_ENUM("I2S2 In Select", i2s_mux_map_enum);
+
+static const struct snd_kcontrol_new i2s3_out_mux_control =
+	SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum);
+
+/* i2s in lpbk */
+static const char * const i2s_lpbk_mux_map[] = {
+	"Normal", "Lpbk",
+};
+
+static int i2s_lpbk_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum,
+					      AFE_I2S_CON,
+					      I2S_LOOPBACK_SFT,
+					      1,
+					      i2s_lpbk_mux_map,
+					      i2s_lpbk_mux_map_value);
+
+static const struct snd_kcontrol_new i2s0_lpbk_mux_control =
+	SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum,
+					      AFE_I2S_CON2,
+					      I2S3_LOOPBACK_SFT,
+					      1,
+					      i2s_lpbk_mux_map,
+					      i2s_lpbk_mux_map_value);
+
+static const struct snd_kcontrol_new i2s2_lpbk_mux_control =
+	SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum);
+
+/* interconnection */
+static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN0,
+				    I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN0,
+				    I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN0,
+				    I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN0,
+				    I_DL12_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN0,
+				    I_DL12_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN0_1,
+				    I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN0_1,
+				    I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN0_1,
+				    I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN0_1,
+				    I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN0,
+				    I_GAIN1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN0,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN0,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN0,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN0,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN0_1,
+				    I_SRC_1_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN1,
+				    I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN1,
+				    I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN1,
+				    I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN1,
+				    I_DL12_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN1,
+				    I_DL12_CH4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN1_1,
+				    I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN1_1,
+				    I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN1_1,
+				    I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN1_1,
+				    I_DL8_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN1,
+				    I_GAIN1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN1,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN1,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN1,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN1,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN1,
+				    I_PCM_1_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN1_1,
+				    I_SRC_1_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN28,
+				    I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN28,
+				    I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN28,
+				    I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN28,
+				    I_DL12_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN28,
+				    I_DL12_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN28_1,
+				    I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN28_1,
+				    I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN28_1,
+				    I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN28_1,
+				    I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN28,
+				    I_GAIN1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN28,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN28,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN28_1,
+				    I_SRC_1_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN29,
+				    I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN29,
+				    I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN29,
+				    I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN29,
+				    I_DL12_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN29,
+				    I_DL12_CH4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN29_1,
+				    I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN29_1,
+				    I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN29_1,
+				    I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN29_1,
+				    I_DL8_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN29,
+				    I_GAIN1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN29,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN29,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN29,
+				    I_PCM_1_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN29_1,
+				    I_SRC_1_OUT_CH2, 1, 0),
+};
+
+enum {
+	SUPPLY_SEQ_APLL,
+	SUPPLY_SEQ_I2S_MCLK_EN,
+	SUPPLY_SEQ_I2S_HD_EN,
+	SUPPLY_SEQ_I2S_EN,
+};
+
+static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol,
+			    int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, w->name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_apll_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol,
+			  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (strcmp(w->name, APLL1_W_NAME) == 0)
+			mt8186_apll1_enable(afe);
+		else
+			mt8186_apll2_enable(afe);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (strcmp(w->name, APLL1_W_NAME) == 0)
+			mt8186_apll1_disable(afe);
+		else
+			mt8186_apll2_disable(afe);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	i2s_priv = get_i2s_priv_by_name(afe, w->name);
+
+	if (!i2s_priv) {
+		dev_info(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);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		i2s_priv->mclk_rate = 0;
+		mt8186_mck_disable(afe, i2s_priv->mclk_id);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
+	SND_SOC_DAPM_INPUT("CONNSYS"),
+
+	SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_i2s1_ch1_mix,
+			   ARRAY_SIZE(mtk_i2s1_ch1_mix)),
+	SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_i2s1_ch2_mix,
+			   ARRAY_SIZE(mtk_i2s1_ch2_mix)),
+
+	SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_i2s3_ch1_mix,
+			   ARRAY_SIZE(mtk_i2s3_ch1_mix)),
+	SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_i2s3_ch2_mix,
+			   ARRAY_SIZE(mtk_i2s3_ch2_mix)),
+
+	/* i2s en*/
+	SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN,
+			      AFE_I2S_CON, I2S_EN_SFT, 0,
+			      mtk_i2s_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN,
+			      AFE_I2S_CON1, I2S_EN_SFT, 0,
+			      mtk_i2s_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN,
+			      AFE_I2S_CON2, I2S_EN_SFT, 0,
+			      mtk_i2s_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN,
+			      AFE_I2S_CON3, I2S_EN_SFT, 0,
+			      mtk_i2s_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	/* i2s hd en */
+	SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
+			      AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
+			      AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
+			      AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
+			      AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* i2s mclk en */
+	SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_mclk_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_mclk_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_mclk_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_mclk_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* apll */
+	SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_apll_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_apll_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* allow i2s on without codec on */
+	SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"),
+	SND_SOC_DAPM_MUX("I2S1_Out_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control),
+	SND_SOC_DAPM_MUX("I2S3_Out_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control),
+	SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"),
+	SND_SOC_DAPM_MUX("I2S0_In_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control),
+	SND_SOC_DAPM_MUX("I2S2_In_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s2_in_mux_control),
+
+	/* i2s in lpbk */
+	SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control),
+	SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux",
+			 SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control),
+};
+
+static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
+				     struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return 0;
+	}
+
+	if (i2s_priv->share_i2s_id < 0)
+		return 0;
+
+	return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);
+}
+
+static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
+				  struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+
+	if (!i2s_priv) {
+		dev_info(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;
+
+	/* check if share i2s need hd en */
+	if (i2s_priv->share_i2s_id < 0)
+		return 0;
+
+	if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
+		return i2s_priv->low_jitter_en;
+
+	return 0;
+}
+
+static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
+				    struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+	int cur_apll;
+	int i2s_need_apll;
+
+	i2s_priv = get_i2s_priv_by_name(afe, w->name);
+
+	if (!i2s_priv) {
+		dev_info(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);
+
+	return (i2s_need_apll == cur_apll) ? 1 : 0;
+}
+
+static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
+				    struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+
+	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+
+	if (!i2s_priv) {
+		dev_info(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;
+
+	/* check if share i2s need mclk */
+	if (i2s_priv->share_i2s_id < 0)
+		return 0;
+
+	if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
+		return (i2s_priv->mclk_rate > 0) ? 1 : 0;
+
+	return 0;
+}
+
+static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
+				     struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_i2s_priv *i2s_priv;
+	int cur_apll;
+
+	i2s_priv = get_i2s_priv_by_name(afe, w->name);
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return 0;
+	}
+
+	/* which apll */
+	cur_apll = mt8186_get_apll_by_name(afe, source->name);
+
+	return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
+	{"Connsys I2S", NULL, "CONNSYS"},
+
+	/* i2s0 */
+	{"I2S0", NULL, "I2S0_EN"},
+	{"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
+	{"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
+	{"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
+
+	{"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+	{I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+	{"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+	{I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+	/* i2s1 */
+	{"I2S1_CH1", "DL1_CH1 Switch", "DL1"},
+	{"I2S1_CH2", "DL1_CH2 Switch", "DL1"},
+
+	{"I2S1_CH1", "DL2_CH1 Switch", "DL2"},
+	{"I2S1_CH2", "DL2_CH2 Switch", "DL2"},
+
+	{"I2S1_CH1", "DL3_CH1 Switch", "DL3"},
+	{"I2S1_CH2", "DL3_CH2 Switch", "DL3"},
+
+	{"I2S1_CH1", "DL12_CH1 Switch", "DL12"},
+	{"I2S1_CH2", "DL12_CH2 Switch", "DL12"},
+
+	{"I2S1_CH1", "DL12_CH3 Switch", "DL12"},
+	{"I2S1_CH2", "DL12_CH4 Switch", "DL12"},
+
+	{"I2S1_CH1", "DL6_CH1 Switch", "DL6"},
+	{"I2S1_CH2", "DL6_CH2 Switch", "DL6"},
+
+	{"I2S1_CH1", "DL4_CH1 Switch", "DL4"},
+	{"I2S1_CH2", "DL4_CH2 Switch", "DL4"},
+
+	{"I2S1_CH1", "DL5_CH1 Switch", "DL5"},
+	{"I2S1_CH2", "DL5_CH2 Switch", "DL5"},
+
+	{"I2S1_CH1", "DL8_CH1 Switch", "DL8"},
+	{"I2S1_CH2", "DL8_CH2 Switch", "DL8"},
+
+	{"I2S1", NULL, "I2S1_CH1"},
+	{"I2S1", NULL, "I2S1_CH2"},
+
+	{"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
+	{"I2S1", NULL, "I2S1_EN"},
+	{"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
+	{"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
+
+	{"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+	{I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+	{"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+	{I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+	/* i2s2 */
+	{"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
+	{"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
+	{"I2S2", NULL, "I2S2_EN"},
+	{"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
+
+	{"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+	{I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+	{"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+	{I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+	/* i2s3 */
+	{"I2S3_CH1", "DL1_CH1 Switch", "DL1"},
+	{"I2S3_CH2", "DL1_CH2 Switch", "DL1"},
+
+	{"I2S3_CH1", "DL2_CH1 Switch", "DL2"},
+	{"I2S3_CH2", "DL2_CH2 Switch", "DL2"},
+
+	{"I2S3_CH1", "DL3_CH1 Switch", "DL3"},
+	{"I2S3_CH2", "DL3_CH2 Switch", "DL3"},
+
+	{"I2S3_CH1", "DL12_CH1 Switch", "DL12"},
+	{"I2S3_CH2", "DL12_CH2 Switch", "DL12"},
+
+	{"I2S3_CH1", "DL12_CH3 Switch", "DL12"},
+	{"I2S3_CH2", "DL12_CH4 Switch", "DL12"},
+
+	{"I2S3_CH1", "DL6_CH1 Switch", "DL6"},
+	{"I2S3_CH2", "DL6_CH2 Switch", "DL6"},
+
+	{"I2S3_CH1", "DL4_CH1 Switch", "DL4"},
+	{"I2S3_CH2", "DL4_CH2 Switch", "DL4"},
+
+	{"I2S3_CH1", "DL5_CH1 Switch", "DL5"},
+	{"I2S3_CH2", "DL5_CH2 Switch", "DL5"},
+
+	{"I2S3_CH1", "DL8_CH1 Switch", "DL8"},
+	{"I2S3_CH2", "DL8_CH2 Switch", "DL8"},
+
+	{"I2S3", NULL, "I2S3_CH1"},
+	{"I2S3", NULL, "I2S3_CH2"},
+
+	{"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
+	{"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
+	{"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
+	{"I2S3", NULL, "I2S3_EN"},
+
+	{"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
+	{I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+	{I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+	{"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+	{I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+	{I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+	/* allow i2s on without codec on */
+	{"I2S0", NULL, "I2S0_In_Mux"},
+	{"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},
+
+	{"I2S1_Out_Mux", "Dummy_Widget", "I2S1"},
+	{"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"},
+
+	{"I2S2", NULL, "I2S2_In_Mux"},
+	{"I2S2_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},
+
+	{"I2S3_Out_Mux", "Dummy_Widget", "I2S3"},
+	{"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"},
+
+	/* i2s in lpbk */
+	{"I2S0_Lpbk_Mux", "Lpbk", "I2S3"},
+	{"I2S2_Lpbk_Mux", "Lpbk", "I2S1"},
+	{"I2S0", NULL, "I2S0_Lpbk_Mux"},
+	{"I2S2", NULL, "I2S2_Lpbk_Mux"},
+};
+
+/* dai ops */
+static int mtk_dai_connsys_i2s_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 rate = params_rate(params);
+	unsigned int rate_reg = mt8186_rate_transform(afe->dev,
+						      rate, dai->id);
+	unsigned int i2s_con = 0;
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		 __func__,
+		 dai->id,
+		 substream->stream,
+		 rate);
+
+	/* non-inverse, i2s mode, slave, 16bits, from connsys */
+	i2s_con |= 0 << INV_PAD_CTRL_SFT;
+	i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
+	i2s_con |= 1 << I2S_SRC_SFT;
+	i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT;
+	i2s_con |= 0 << I2SIN_PAD_SEL_SFT;
+	regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);
+
+	/* use asrc */
+	regmap_update_bits(afe->regmap,
+			   AFE_CONNSYS_I2S_CON,
+			   I2S_BYPSRC_MASK_SFT,
+			   0x0 << I2S_BYPSRC_SFT);
+
+	/* slave mode, set i2s for asrc */
+	regmap_update_bits(afe->regmap,
+			   AFE_CONNSYS_I2S_CON,
+			   I2S_MODE_MASK_SFT,
+			   rate_reg << I2S_MODE_SFT);
+
+	if (rate == 44100)
+		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001B9000);
+	else if (rate == 32000)
+		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);
+	else
+		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001E0000);
+
+	/* Calibration setting */
+	regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x00140000);
+	regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x00036000);
+	regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x0002FC00);
+	regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x00007EF4);
+	regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0x00FF5986);
+
+	/* 0:Stereo 1:Mono */
+	regmap_update_bits(afe->regmap,
+			   AFE_ASRC_2CH_CON2,
+			   CHSET_IS_MONO_MASK_SFT,
+			   0x0 << CHSET_IS_MONO_SFT);
+
+	return 0;
+}
+
+static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream,
+				       int cmd, struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+	dev_info(afe->dev, "%s(), cmd %d, stream %d\n",
+		 __func__,
+		 cmd,
+		 substream->stream);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* i2s enable */
+		regmap_update_bits(afe->regmap,
+				   AFE_CONNSYS_I2S_CON,
+				   I2S_EN_MASK_SFT,
+				   0x1 << I2S_EN_SFT);
+
+		/* calibrator enable */
+		regmap_update_bits(afe->regmap,
+				   AFE_ASRC_2CH_CON5,
+				   CALI_EN_MASK_SFT,
+				   0x1 << CALI_EN_SFT);
+
+		/* asrc enable */
+		regmap_update_bits(afe->regmap,
+				   AFE_ASRC_2CH_CON0,
+				   CON0_CHSET_STR_CLR_MASK_SFT,
+				   0x1 << CON0_CHSET_STR_CLR_SFT);
+		regmap_update_bits(afe->regmap,
+				   AFE_ASRC_2CH_CON0,
+				   CON0_ASM_ON_MASK_SFT,
+				   0x1 << CON0_ASM_ON_SFT);
+
+		afe_priv->dai_on[dai->id] = true;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		regmap_update_bits(afe->regmap,
+				   AFE_ASRC_2CH_CON0,
+				   CON0_ASM_ON_MASK_SFT,
+				   0 << CON0_ASM_ON_SFT);
+		regmap_update_bits(afe->regmap,
+				   AFE_ASRC_2CH_CON5,
+				   CALI_EN_MASK_SFT,
+				   0 << CALI_EN_SFT);
+
+		/* i2s disable */
+		regmap_update_bits(afe->regmap,
+				   AFE_CONNSYS_I2S_CON,
+				   I2S_EN_MASK_SFT,
+				   0x0 << I2S_EN_SFT);
+
+		/* bypass asrc */
+		regmap_update_bits(afe->regmap,
+				   AFE_CONNSYS_I2S_CON,
+				   I2S_BYPSRC_MASK_SFT,
+				   0x1 << I2S_BYPSRC_SFT);
+
+		afe_priv->dai_on[dai->id] = false;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = {
+	.hw_params = mtk_dai_connsys_i2s_hw_params,
+	.trigger = mtk_dai_connsys_i2s_trigger,
+};
+
+/* i2s */
+static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
+			      struct snd_pcm_hw_params *params,
+			      int i2s_id)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];
+
+	unsigned int rate = params_rate(params);
+	unsigned int rate_reg = mt8186_rate_transform(afe->dev,
+						      rate, i2s_id);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int i2s_con = 0;
+	int ret = 0;
+
+	dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n",
+		 __func__,
+		 i2s_id,
+		 rate, format);
+
+	if (i2s_priv)
+		i2s_priv->rate = rate;
+	else
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+
+	switch (i2s_id) {
+	case MT8186_DAI_I2S_0:
+		i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
+		i2s_con |= rate_reg << I2S_OUT_MODE_SFT;
+		i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
+		i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
+		regmap_update_bits(afe->regmap, AFE_I2S_CON,
+				   0xffffeffa, i2s_con);
+		break;
+	case MT8186_DAI_I2S_1:
+		i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;
+		i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;
+		i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;
+		i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;
+		regmap_update_bits(afe->regmap, AFE_I2S_CON1,
+				   0xffffeffa, i2s_con);
+		break;
+	case MT8186_DAI_I2S_2:
+		i2s_con = 8 << I2S3_UPDATE_WORD_SFT;
+		i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;
+		i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;
+		i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;
+		regmap_update_bits(afe->regmap, AFE_I2S_CON2,
+				   0xffffeffa, i2s_con);
+		break;
+	case MT8186_DAI_I2S_3:
+		i2s_con = rate_reg << I2S4_OUT_MODE_SFT;
+		i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;
+		i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;
+		regmap_update_bits(afe->regmap, AFE_I2S_CON3,
+				   0xffffeffa, i2s_con);
+		break;
+	default:
+		dev_info(afe->dev, "%s(), id %d not support\n",
+			 __func__, i2s_id);
+		return -EINVAL;
+	}
+
+	/* set share i2s */
+	if (i2s_priv && i2s_priv->share_i2s_id >= 0)
+		ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);
+
+	return ret;
+}
+
+static int mtk_dai_i2s_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);
+
+	return mtk_dai_i2s_config(afe, params, dai->id);
+}
+
+static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];
+	int apll;
+	int apll_rate;
+
+	if (!i2s_priv) {
+		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	if (dir != SND_SOC_CLOCK_OUT) {
+		dev_info(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
+		return -EINVAL;
+	}
+
+	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
+
+	apll = mt8186_get_apll_by_rate(afe, freq);
+	apll_rate = mt8186_get_apll_rate(afe, apll);
+
+	if (freq > apll_rate) {
+		dev_info(afe->dev, "%s(), freq > apll rate", __func__);
+		return -EINVAL;
+	}
+
+	if (apll_rate % freq != 0) {
+		dev_info(afe->dev, "%s(), APLL cannot generate freq Hz", __func__);
+		return -EINVAL;
+	}
+
+	i2s_priv->mclk_rate = freq;
+	i2s_priv->mclk_apll = apll;
+
+	if (i2s_priv->share_i2s_id > 0) {
+		struct mtk_afe_i2s_priv *share_i2s_priv;
+
+		share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
+		if (!share_i2s_priv) {
+			dev_info(afe->dev, "%s(), share_i2s_priv == NULL", __func__);
+			return -EINVAL;
+		}
+
+		share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
+		share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {
+	.hw_params = mtk_dai_i2s_hw_params,
+	.set_sysclk = mtk_dai_i2s_set_sysclk,
+};
+
+/* dai driver */
+#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\
+		       SNDRV_PCM_RATE_88200 |\
+		       SNDRV_PCM_RATE_96000 |\
+		       SNDRV_PCM_RATE_176400 |\
+		       SNDRV_PCM_RATE_192000)
+
+#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE |\
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
+	{
+		.name = "CONNSYS_I2S",
+		.id = MT8186_DAI_CONNSYS_I2S,
+		.capture = {
+			.stream_name = "Connsys I2S",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_CONNSYS_I2S_RATES,
+			.formats = MTK_I2S_FORMATS,
+		},
+		.ops = &mtk_dai_connsys_i2s_ops,
+	},
+	{
+		.name = "I2S0",
+		.id = MT8186_DAI_I2S_0,
+		.capture = {
+			.stream_name = "I2S0",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_I2S_RATES,
+			.formats = MTK_I2S_FORMATS,
+		},
+		.ops = &mtk_dai_i2s_ops,
+	},
+	{
+		.name = "I2S1",
+		.id = MT8186_DAI_I2S_1,
+		.playback = {
+			.stream_name = "I2S1",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_I2S_RATES,
+			.formats = MTK_I2S_FORMATS,
+		},
+		.ops = &mtk_dai_i2s_ops,
+	},
+	{
+		.name = "I2S2",
+		.id = MT8186_DAI_I2S_2,
+		.capture = {
+			.stream_name = "I2S2",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_I2S_RATES,
+			.formats = MTK_I2S_FORMATS,
+		},
+		.ops = &mtk_dai_i2s_ops,
+	},
+	{
+		.name = "I2S3",
+		.id = MT8186_DAI_I2S_3,
+		.playback = {
+			.stream_name = "I2S3",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_I2S_RATES,
+			.formats = MTK_I2S_FORMATS,
+		},
+		.ops = &mtk_dai_i2s_ops,
+	}
+};
+
+/* this enum is merely for mtk_afe_i2s_priv declare */
+enum {
+	DAI_I2S0 = 0,
+	DAI_I2S1,
+	DAI_I2S2,
+	DAI_I2S3,
+	DAI_I2S_NUM,
+};
+
+static const struct mtk_afe_i2s_priv mt8186_i2s_priv[DAI_I2S_NUM] = {
+	[DAI_I2S0] = {
+		.id = MT8186_DAI_I2S_0,
+		.mclk_id = MT8186_I2S0_MCK,
+		.share_property_name = "i2s0-share",
+		.share_i2s_id = -1,
+	},
+	[DAI_I2S1] = {
+		.id = MT8186_DAI_I2S_1,
+		.mclk_id = MT8186_I2S1_MCK,
+		.share_property_name = "i2s1-share",
+		.share_i2s_id = -1,
+	},
+	[DAI_I2S2] = {
+		.id = MT8186_DAI_I2S_2,
+		.mclk_id = MT8186_I2S2_MCK,
+		.share_property_name = "i2s2-share",
+		.share_i2s_id = -1,
+	},
+	[DAI_I2S3] = {
+		.id = MT8186_DAI_I2S_3,
+		/*  clock gate naming is hf_faud_i2s4_m_ck*/
+		.mclk_id = MT8186_I2S4_MCK,
+		.share_property_name = "i2s3-share",
+		.share_i2s_id = -1,
+	}
+};
+
+static int mt8186_dai_i2s_get_share(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	const struct device_node *of_node = afe->dev->of_node;
+	const char *of_str;
+	const char *property_name;
+	struct mtk_afe_i2s_priv *i2s_priv;
+	int i;
+
+	for (i = 0; i < DAI_I2S_NUM; i++) {
+		i2s_priv = afe_priv->dai_priv[mt8186_i2s_priv[i].id];
+		property_name = mt8186_i2s_priv[i].share_property_name;
+		if (of_property_read_string(of_node, property_name, &of_str))
+			continue;
+		i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str);
+	}
+
+	return 0;
+}
+
+static int mt8186_dai_i2s_set_priv(struct mtk_base_afe *afe)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < DAI_I2S_NUM; i++) {
+		ret = mt8186_dai_set_priv(afe, mt8186_i2s_priv[i].id,
+					  sizeof(struct mtk_afe_i2s_priv),
+					  &mt8186_i2s_priv[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int mt8186_dai_i2s_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+	int ret;
+
+	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_i2s_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
+
+	dai->controls = mtk_dai_i2s_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);
+	dai->dapm_widgets = mtk_dai_i2s_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
+	dai->dapm_routes = mtk_dai_i2s_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
+
+	/* set all dai i2s private data */
+	ret = mt8186_dai_i2s_set_priv(afe);
+	if (ret)
+		return ret;
+
+	/* parse share i2s */
+	ret = mt8186_dai_i2s_get_share(afe);
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 07/17] ASoC: mediatek: mt8186: support pcm in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (5 preceding siblings ...)
  2022-02-17 13:41 ` [v2 06/17] ASoC: mediatek: mt8186: support i2s " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 08/17] ASoC: mediatek: mt8186: support src " Jiaxin Yu
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 pcm dai driver.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c | 432 +++++++++++++++++++++
 1 file changed, 432 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
new file mode 100644
index 000000000000..73b3f720ed35
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI I2S Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-interconnection.h"
+
+struct mtk_afe_pcm_priv {
+	unsigned int id;
+	unsigned int fmt;
+	unsigned int bck_invert;
+	unsigned int lck_invert;
+};
+
+enum AUD_TX_LCH_RPT {
+	AUD_TX_LCH_RPT_NO_REPEAT = 0,
+	AUD_TX_LCH_RPT_REPEAT = 1
+};
+
+enum AUD_VBT_16K_MODE {
+	AUD_VBT_16K_MODE_DISABLE = 0,
+	AUD_VBT_16K_MODE_ENABLE = 1
+};
+
+enum AUD_EXT_MODEM {
+	AUD_EXT_MODEM_SELECT_INTERNAL = 0,
+	AUD_EXT_MODEM_SELECT_EXTERNAL = 1
+};
+
+enum AUD_PCM_SYNC_TYPE {
+	/* bck sync length = 1 */
+	AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
+	/* bck sync length = PCM_INTF_CON1[9:13] */
+	AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
+};
+
+enum AUD_BT_MODE {
+	AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
+	AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
+};
+
+enum AUD_PCM_AFIFO_SRC {
+	/* slave mode & external modem uses different crystal */
+	AUD_PCM_AFIFO_ASRC = 0,
+	/* slave mode & external modem uses the same crystal */
+	AUD_PCM_AFIFO_AFIFO = 1
+};
+
+enum AUD_PCM_CLOCK_SOURCE {
+	AUD_PCM_CLOCK_MASTER_MODE = 0,
+	AUD_PCM_CLOCK_SLAVE_MODE = 1
+};
+
+enum AUD_PCM_WLEN {
+	AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
+	AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
+};
+
+enum AUD_PCM_24BIT {
+	AUD_PCM_24BIT_PCM_16_BITS = 0,
+	AUD_PCM_24BIT_PCM_24_BITS = 1
+};
+
+enum AUD_PCM_MODE {
+	AUD_PCM_MODE_PCM_MODE_8K = 0,
+	AUD_PCM_MODE_PCM_MODE_16K = 1,
+	AUD_PCM_MODE_PCM_MODE_32K = 2,
+	AUD_PCM_MODE_PCM_MODE_48K = 3,
+};
+
+enum AUD_PCM_FMT {
+	AUD_PCM_FMT_I2S = 0,
+	AUD_PCM_FMT_EIAJ = 1,
+	AUD_PCM_FMT_PCM_MODE_A = 2,
+	AUD_PCM_FMT_PCM_MODE_B = 3
+};
+
+enum AUD_BCLK_OUT_INV {
+	AUD_BCLK_OUT_INV_NO_INVERSE = 0,
+	AUD_BCLK_OUT_INV_INVERSE = 1
+};
+
+enum AUD_LRCLK_OUT_INV {
+	AUD_LRCLK_OUT_INV_NO_INVERSE = 0,
+	AUD_LRCLK_OUT_INV_INVERSE = 1
+};
+
+enum AUD_PCM_EN {
+	AUD_PCM_EN_DISABLE = 0,
+	AUD_PCM_EN_ENABLE = 1
+};
+
+/* dai component */
+static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN7,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN7,
+				    I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN7_1,
+				    I_DL4_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN8,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN8,
+				    I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN8_1,
+				    I_DL4_CH2, 1, 0),
+};
+
+static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol,
+			    int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_PCM, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_PCM, 0);
+		break;
+	}
+
+	return 0;
+}
+
+/* pcm in/out lpbk */
+static const char * const pcm_lpbk_mux_map[] = {
+	"Normal", "Lpbk",
+};
+
+static int pcm_lpbk_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_in_lpbk_mux_map_enum,
+					      PCM_INTF_CON1,
+					      PCM_I2S_PCM_LOOPBACK_SFT,
+					      1,
+					      pcm_lpbk_mux_map,
+					      pcm_lpbk_mux_map_value);
+
+static const struct snd_kcontrol_new pcm_in_lpbk_mux_control =
+	SOC_DAPM_ENUM("PCM In Lpbk Select", pcm_in_lpbk_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_out_lpbk_mux_map_enum,
+					      PCM_INTF_CON1,
+					      PCM_I2S_PCM_LOOPBACK_SFT,
+					      1,
+					      pcm_lpbk_mux_map,
+					      pcm_lpbk_mux_map_value);
+
+static const struct snd_kcontrol_new pcm_out_lpbk_mux_control =
+	SOC_DAPM_ENUM("PCM Out Lpbk Select", pcm_out_lpbk_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_pcm_1_playback_ch1_mix,
+			   ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)),
+	SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_pcm_1_playback_ch2_mix,
+			   ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)),
+
+	SND_SOC_DAPM_SUPPLY("PCM_1_EN",
+			    PCM_INTF_CON1, PCM_EN_SFT, 0,
+			    mtk_pcm_en_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* pcm in lpbk */
+	SND_SOC_DAPM_MUX("PCM_In_Lpbk_Mux",
+			 SND_SOC_NOPM, 0, 0, &pcm_in_lpbk_mux_control),
+
+	/* pcm out lpbk */
+	SND_SOC_DAPM_MUX("PCM_Out_Lpbk_Mux",
+			 SND_SOC_NOPM, 0, 0, &pcm_out_lpbk_mux_control),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
+	{"PCM 1 Playback", NULL, "PCM_1_PB_CH1"},
+	{"PCM 1 Playback", NULL, "PCM_1_PB_CH2"},
+
+	{"PCM 1 Playback", NULL, "PCM_1_EN"},
+	{"PCM 1 Capture", NULL, "PCM_1_EN"},
+
+	{"PCM_1_PB_CH1", "DL2_CH1 Switch", "DL2"},
+	{"PCM_1_PB_CH2", "DL2_CH2 Switch", "DL2"},
+
+	{"PCM_1_PB_CH1", "DL4_CH1 Switch", "DL4"},
+	{"PCM_1_PB_CH2", "DL4_CH2 Switch", "DL4"},
+
+	/* pcm out lpbk */
+	{"PCM_Out_Lpbk_Mux", "Lpbk", "PCM 1 Playback"},
+	{"I2S0", NULL, "PCM_Out_Lpbk_Mux"},
+
+	/* pcm in lpbk */
+	{"PCM_In_Lpbk_Mux", "Lpbk", "PCM 1 Capture"},
+	{"I2S3", NULL, "PCM_In_Lpbk_Mux"},
+};
+
+/* dai ops */
+static int mtk_dai_pcm_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);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int pcm_id = dai->id;
+	struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id];
+	unsigned int rate = params_rate(params);
+	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int data_width =
+		snd_pcm_format_width(format);
+	unsigned int wlen_width =
+		snd_pcm_format_physical_width(format);
+	unsigned int pcm_con = 0;
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n",
+		 __func__,
+		 dai->id,
+		 substream->stream,
+		 dai->playback_widget->active,
+		 dai->capture_widget->active);
+	dev_info(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n",
+		 __func__,
+		 rate,
+		 rate_reg,
+		 data_width,
+		 wlen_width);
+
+	if (dai->playback_widget->active || dai->capture_widget->active)
+		return 0;
+
+	switch (dai->id) {
+	case MT8186_DAI_PCM:
+		pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
+		pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
+		pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT;
+		pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
+		pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
+		pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
+		pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT;
+		pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
+
+		/* sampling rate */
+		pcm_con |= rate_reg << PCM_MODE_SFT;
+
+		/* format */
+		pcm_con |= pcm_priv->fmt << PCM_FMT_SFT;
+
+		/* 24bit data width */
+		if (data_width > 16)
+			pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT;
+		else
+			pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT;
+
+		/* wlen width*/
+		if (wlen_width > 16)
+			pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT;
+		else
+			pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT;
+
+		/* clock invert */
+		pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT;
+		pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT;
+
+		regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+				   0xfffffffe, pcm_con);
+		break;
+	default:
+		dev_info(afe->dev, "%s(), id %d not support\n",
+			 __func__, dai->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	/* DAI mode*/
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		pcm_priv->fmt = AUD_PCM_FMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		pcm_priv->fmt = AUD_PCM_FMT_EIAJ;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_B;
+		break;
+	default:
+		pcm_priv->fmt = AUD_PCM_FMT_I2S;
+	}
+
+	/* DAI clock inversion*/
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
+		pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
+		pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE;
+		pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE;
+		pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE;
+		break;
+	default:
+		pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
+		pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
+	.hw_params = mtk_dai_pcm_hw_params,
+	.set_fmt = mtk_dai_pcm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_PCM_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 mtk_dai_pcm_driver[] = {
+	{
+		.name = "PCM 1",
+		.id = MT8186_DAI_PCM,
+		.playback = {
+			.stream_name = "PCM 1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_PCM_RATES,
+			.formats = MTK_PCM_FORMATS,
+		},
+		.capture = {
+			.stream_name = "PCM 1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_PCM_RATES,
+			.formats = MTK_PCM_FORMATS,
+		},
+		.ops = &mtk_dai_pcm_ops,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
+	},
+};
+
+static struct mtk_afe_pcm_priv *init_pcm_priv_data(struct mtk_base_afe *afe)
+{
+	struct mtk_afe_pcm_priv *pcm_priv;
+
+	pcm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_pcm_priv),
+				GFP_KERNEL);
+	if (!pcm_priv)
+		return NULL;
+
+	pcm_priv->id = MT8186_DAI_PCM;
+	pcm_priv->fmt = AUD_PCM_FMT_I2S;
+	pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
+	pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
+
+	return pcm_priv;
+}
+
+int mt8186_dai_pcm_register(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_pcm_priv *pcm_priv;
+	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_pcm_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
+
+	dai->dapm_widgets = mtk_dai_pcm_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
+	dai->dapm_routes = mtk_dai_pcm_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
+
+	pcm_priv = init_pcm_priv_data(afe);
+	if (!pcm_priv)
+		return -ENOMEM;
+
+	afe_priv->dai_priv[MT8186_DAI_PCM] = pcm_priv;
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 08/17] ASoC: mediatek: mt8186: support src in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (6 preceding siblings ...)
  2022-02-17 13:41 ` [v2 07/17] ASoC: mediatek: mt8186: support pcm " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 09/17] ASoC: mediatek: mt8186: support tdm " Jiaxin Yu
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 src dai driver

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-dai-src.c | 758 +++++++++++++++++++++
 1 file changed, 758 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-src.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-src.c b/sound/soc/mediatek/mt8186/mt8186-dai-src.c
new file mode 100644
index 000000000000..7ff1623b591a
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-src.c
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+//  MediaTek ALSA SoC Audio DAI SRC Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/regmap.h>
+#include "mt8186-afe-common.h"
+#include "mt8186-interconnection.h"
+
+struct mtk_afe_src_priv {
+	int dl_rate;
+	int ul_rate;
+};
+
+static const unsigned int src_iir_coeff_32_to_16[] = {
+	0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002,
+	0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002,
+	0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002,
+	0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002,
+	0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002,
+	0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002,
+	0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002,
+	0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001
+};
+
+static const unsigned int src_iir_coeff_44_to_16[] = {
+	0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002,
+	0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002,
+	0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002,
+	0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002,
+	0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002,
+	0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002,
+	0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001
+};
+
+static const unsigned int src_iir_coeff_44_to_32[] = {
+	0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003,
+	0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002,
+	0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002,
+	0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002,
+	0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002,
+	0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002,
+	0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001
+};
+
+static const unsigned int src_iir_coeff_48_to_16[] = {
+	0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002,
+	0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002,
+	0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002,
+	0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002,
+	0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002,
+	0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002,
+	0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001,
+	0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004
+};
+
+static const unsigned int src_iir_coeff_48_to_32[] = {
+	0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002,
+	0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002,
+	0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002,
+	0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002,
+	0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002,
+	0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002,
+	0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001
+};
+
+static const unsigned int src_iir_coeff_48_to_44[] = {
+	0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003,
+	0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003,
+	0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003,
+	0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003,
+	0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001
+};
+
+static const unsigned int src_iir_coeff_96_to_16[] = {
+	0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
+	0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
+	0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
+	0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
+	0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
+	0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
+	0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
+	0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
+};
+
+static const unsigned int src_iir_coeff_96_to_44[] = {
+	0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
+	0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
+	0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
+	0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
+	0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
+	0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
+	0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
+	0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
+};
+
+static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate)
+{
+	switch (rate) {
+	case 8000:
+		return 0x00050000;
+	case 11025:
+		return 0x0006E400;
+	case 12000:
+		return 0x00078000;
+	case 16000:
+		return 0x000A0000;
+	case 22050:
+		return 0x000DC800;
+	case 24000:
+		return 0x000F0000;
+	case 32000:
+		return 0x00140000;
+	case 44100:
+		return 0x001B9000;
+	case 48000:
+		return 0x001E0000;
+	case 88200:
+		return 0x00372000;
+	case 96000:
+		return 0x003C0000;
+	case 176400:
+		return 0x006E4000;
+	case 192000:
+		return 0x00780000;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid!!!\n",
+			 __func__, rate);
+		return 0;
+	}
+}
+
+static const unsigned int *get_iir_coeff(unsigned int rate_in,
+					 unsigned int rate_out,
+					 unsigned int *param_num)
+{
+	if (rate_in == 32000 && rate_out == 16000) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_32_to_16);
+		return src_iir_coeff_32_to_16;
+	} else if (rate_in == 44100 && rate_out == 16000) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_16);
+		return src_iir_coeff_44_to_16;
+	} else if (rate_in == 44100 && rate_out == 32000) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_32);
+		return src_iir_coeff_44_to_32;
+	} else if ((rate_in == 48000 && rate_out == 16000) ||
+		   (rate_in == 96000 && rate_out == 32000)) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_16);
+		return src_iir_coeff_48_to_16;
+	} else if (rate_in == 48000 && rate_out == 32000) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_32);
+		return src_iir_coeff_48_to_32;
+	} else if (rate_in == 48000 && rate_out == 44100) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_44);
+		return src_iir_coeff_48_to_44;
+	} else if (rate_in == 96000 && rate_out == 16000) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_16);
+		return src_iir_coeff_96_to_16;
+	} else if ((rate_in == 96000 && rate_out == 44100) ||
+		   (rate_in == 48000 && rate_out == 22050)) {
+		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_44);
+		return src_iir_coeff_96_to_44;
+	}
+
+	*param_num = 0;
+	return NULL;
+}
+
+#define DEBUG_COEFF
+static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
+	unsigned int iir_coeff_num;
+	unsigned int iir_stage;
+	int rate_in = src_priv->dl_rate;
+	int rate_out = src_priv->ul_rate;
+	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe,
+							   rate_out);
+	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe,
+							  rate_in);
+
+	/* set out freq mode */
+	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3,
+			   G_SRC_ASM_FREQ_4_MASK_SFT,
+			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
+
+	/* set in freq mode */
+	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4,
+			   G_SRC_ASM_FREQ_5_MASK_SFT,
+			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
+
+	regmap_write(afe->regmap,
+		     AFE_GENERAL1_ASRC_2CH_CON5, 0x003f5986);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL1_ASRC_2CH_CON5, 0x003f5987);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL1_ASRC_2CH_CON6, 0x00001fbd);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL1_ASRC_2CH_CON2, 0x00000000);
+
+	/* set iir if in_rate > out_rate */
+	if (rate_in > rate_out) {
+		int i;
+#ifdef DEBUG_COEFF
+		int reg_val;
+#endif
+		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
+							      &iir_coeff_num);
+
+		if (iir_coeff_num == 0 || !iir_coeff) {
+			dev_info(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
+				 __func__, iir_coeff_num, iir_coeff);
+			return -EINVAL;
+		}
+
+		/* COEFF_SRAM_CTRL */
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
+				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
+				   0x1 << G_SRC_COEFF_SRAM_CTRL_SFT);
+		/* Clear coeff history to r/w coeff from the first position */
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
+				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
+				   0x0);
+		/* Write SRC coeff, should not read the reg during write */
+		for (i = 0; i < iir_coeff_num; i++)
+			regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
+				     iir_coeff[i]);
+
+#ifdef DEBUG_COEFF
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
+				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
+				   0x0);
+
+		for (i = 0; i < iir_coeff_num; i++) {
+			regmap_read(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
+				    &reg_val);
+			dev_info(afe->dev, "%s(), i = %d, coeff = 0x%x\n",
+				 __func__, i, reg_val);
+		}
+#endif
+		/* disable sram access */
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
+				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
+				   0x0);
+		/* CHSET_IIR_STAGE */
+		iir_stage = (iir_coeff_num / 6) - 1;
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
+				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
+		/* CHSET_IIR_EN */
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_EN_MASK_SFT,
+				   0x1 << G_SRC_CHSET_IIR_EN_SFT);
+	} else {
+		/* CHSET_IIR_EN off */
+		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_EN_MASK_SFT,
+				   0x0);
+	}
+
+	return 0;
+}
+
+static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
+	unsigned int iir_coeff_num;
+	unsigned int iir_stage;
+	int rate_in = src_priv->dl_rate;
+	int rate_out = src_priv->ul_rate;
+	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe,
+							   rate_out);
+	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe,
+							  rate_in);
+
+	/* set out freq mode */
+	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3,
+			   G_SRC_ASM_FREQ_4_MASK_SFT,
+			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
+
+	/* set in freq mode */
+	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4,
+			   G_SRC_ASM_FREQ_5_MASK_SFT,
+			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
+
+	regmap_write(afe->regmap,
+		     AFE_GENERAL2_ASRC_2CH_CON5, 0x003f5986);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL2_ASRC_2CH_CON5, 0x003f5987);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL2_ASRC_2CH_CON6, 0x00001fbd);
+	regmap_write(afe->regmap,
+		     AFE_GENERAL2_ASRC_2CH_CON2, 0x00000000);
+
+	/* set iir if in_rate > out_rate */
+	if (rate_in > rate_out) {
+		int i;
+#ifdef DEBUG_COEFF
+		int reg_val;
+#endif
+		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
+							      &iir_coeff_num);
+
+		if (iir_coeff_num == 0 || !iir_coeff) {
+			dev_info(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
+				 __func__, iir_coeff_num, iir_coeff);
+			return -EINVAL;
+		}
+
+		/* COEFF_SRAM_CTRL */
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
+				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
+				   0x1 << G_SRC_COEFF_SRAM_CTRL_SFT);
+		/* Clear coeff history to r/w coeff from the first position */
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
+				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
+				   0x0);
+		/* Write SRC coeff, should not read the reg during write */
+		for (i = 0; i < iir_coeff_num; i++)
+			regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
+				     iir_coeff[i]);
+
+#ifdef DEBUG_COEFF
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
+				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
+				   0x0);
+
+		for (i = 0; i < iir_coeff_num; i++) {
+			regmap_read(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
+				    &reg_val);
+			dev_info(afe->dev, "%s(), i = %d, coeff = 0x%x\n",
+				 __func__, i, reg_val);
+		}
+#endif
+		/* disable sram access */
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
+				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
+				   0x0);
+		/* CHSET_IIR_STAGE */
+		iir_stage = (iir_coeff_num / 6) - 1;
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
+				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
+		/* CHSET_IIR_EN */
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_EN_MASK_SFT,
+				   0x1 << G_SRC_CHSET_IIR_EN_SFT);
+	} else {
+		/* CHSET_IIR_EN off */
+		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
+				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0x0);
+	}
+
+	return 0;
+}
+
+#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable"
+#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable"
+
+static int mtk_hw_src_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol,
+			    int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int id;
+	struct mtk_afe_src_priv *src_priv;
+	unsigned int reg;
+
+	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
+		id = MT8186_DAI_SRC_1;
+	else
+		id = MT8186_DAI_SRC_2;
+
+	src_priv = afe_priv->dai_priv[id];
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",
+		__func__,
+		w->name, event,
+		id, src_priv,
+		src_priv->dl_rate,
+		src_priv->ul_rate);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (id == MT8186_DAI_SRC_1)
+			mtk_set_src_1_param(afe, id);
+		else
+			mtk_set_src_2_param(afe, id);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		reg = (id == MT8186_DAI_SRC_1) ?
+		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
+		/* ASM_ON */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_ASM_ON_MASK_SFT,
+				   0x1 << G_SRC_ASM_ON_SFT);
+		/* CHSET_ON */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_CHSET_ON_MASK_SFT,
+				   0x1 << G_SRC_CHSET_ON_SFT);
+		/* CHSET_STR_CLR */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_CHSET_STR_CLR_MASK_SFT,
+				   0x1 << G_SRC_CHSET_STR_CLR_SFT);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		reg = (id == MT8186_DAI_SRC_1) ?
+		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
+		/* ASM_OFF */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_ASM_ON_MASK_SFT, 0x0);
+		/* CHSET_OFF */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_CHSET_ON_MASK_SFT, 0x0);
+		/* CHSET_STR_CLR */
+		regmap_update_bits(afe->regmap, reg,
+				   G_SRC_CHSET_STR_CLR_MASK_SFT, 0x0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* dai component */
+static const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40,
+				    I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40,
+				    I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40,
+				    I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1,
+				    I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1,
+				    I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40,
+				    I_I2S0_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1,
+				    I_DL5_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41,
+				    I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41,
+				    I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41,
+				    I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1,
+				    I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1,
+				    I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41,
+				    I_I2S0_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1,
+				    I_DL5_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42,
+				    I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42,
+				    I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42,
+				    I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42,
+				    I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1,
+				    I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1,
+				    I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42,
+				    I_GAIN2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43,
+				    I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43,
+				    I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43,
+				    I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43,
+				    I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1,
+				    I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1,
+				    I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43,
+				    I_GAIN2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_src_1_in_ch1_mix,
+			   ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)),
+	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_src_1_in_ch2_mix,
+			   ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)),
+	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_src_2_in_ch1_mix,
+			   ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)),
+	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_src_2_in_ch2_mix,
+			   ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)),
+
+	SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME,
+			    GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0,
+			    mtk_hw_src_event,
+			    SND_SOC_DAPM_PRE_PMU |
+			    SND_SOC_DAPM_POST_PMU |
+			    SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME,
+			    GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0,
+			    mtk_hw_src_event,
+			    SND_SOC_DAPM_PRE_PMU |
+			    SND_SOC_DAPM_POST_PMU |
+			    SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"),
+	SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"),
+	SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"),
+	SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"),
+};
+
+static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source,
+				  struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_src_priv *src_priv;
+
+	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
+		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1];
+	else
+		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2];
+
+	dev_info(afe->dev,
+		 "%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n",
+		 __func__, source->name, sink->name,
+		 src_priv->dl_rate, src_priv->ul_rate);
+
+	return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_src_routes[] = {
+	{"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"},
+	{"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"},
+	{"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"},
+	{"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"},
+	{"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"},
+	{"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"},
+	{"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"},
+	{"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"},
+	{"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"},
+	{"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"},
+	{"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"},
+	{"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"},
+	{"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"},
+	{"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"},
+	{"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"},
+	{"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"},
+	{"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"},
+	{"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"},
+	{"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"},
+	{"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"},
+	{"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"},
+	{"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"},
+	{"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"},
+	{"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"},
+
+	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"},
+	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"},
+
+	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"},
+	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"},
+
+	{"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
+	{"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
+	{"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
+	{"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
+
+	{"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"},
+	{"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"},
+	{"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"},
+	{"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"},
+};
+
+/* dai ops */
+static int mtk_dai_src_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);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int id = dai->id;
+	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
+	unsigned int sft, mask;
+	unsigned int rate = params_rate(params);
+	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id);
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		 __func__,
+		 id,
+		 substream->stream,
+		 rate);
+
+	/* rate */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		src_priv->dl_rate = rate;
+		if (id == MT8186_DAI_SRC_1) {
+			sft = GENERAL1_ASRCIN_MODE_SFT;
+			mask = GENERAL1_ASRCIN_MODE_MASK;
+		} else {
+			sft = GENERAL2_ASRCIN_MODE_SFT;
+			mask = GENERAL2_ASRCIN_MODE_MASK;
+		}
+	} else {
+		src_priv->ul_rate = rate;
+		if (id == MT8186_DAI_SRC_1) {
+			sft = GENERAL1_ASRCOUT_MODE_SFT;
+			mask = GENERAL1_ASRCOUT_MODE_MASK;
+		} else {
+			sft = GENERAL2_ASRCOUT_MODE_SFT;
+			mask = GENERAL2_ASRCOUT_MODE_MASK;
+		}
+	}
+
+	regmap_update_bits(afe->regmap,
+			   GENERAL_ASRC_MODE,
+			   mask << sft,
+			   rate_reg << sft);
+
+	return 0;
+}
+
+static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int id = dai->id;
+	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
+
+	dev_info(afe->dev, "%s(), id %d, stream %d\n",
+		 __func__,
+		 id,
+		 substream->stream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		src_priv->dl_rate = 0;
+	else
+		src_priv->ul_rate = 0;
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_src_ops = {
+	.hw_params = mtk_dai_src_hw_params,
+	.hw_free = mtk_dai_src_hw_free,
+};
+
+/* dai driver */
+#define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\
+		       SNDRV_PCM_RATE_88200 |\
+		       SNDRV_PCM_RATE_96000 |\
+		       SNDRV_PCM_RATE_176400 |\
+		       SNDRV_PCM_RATE_192000)
+
+#define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE |\
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_src_driver[] = {
+	{
+		.name = "HW_SRC_1",
+		.id = MT8186_DAI_SRC_1,
+		.playback = {
+			.stream_name = "HW_SRC_1_In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_SRC_RATES,
+			.formats = MTK_SRC_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HW_SRC_1_Out",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_SRC_RATES,
+			.formats = MTK_SRC_FORMATS,
+		},
+		.ops = &mtk_dai_src_ops,
+	},
+	{
+		.name = "HW_SRC_2",
+		.id = MT8186_DAI_SRC_2,
+		.playback = {
+			.stream_name = "HW_SRC_2_In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_SRC_RATES,
+			.formats = MTK_SRC_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HW_SRC_2_Out",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_SRC_RATES,
+			.formats = MTK_SRC_FORMATS,
+		},
+		.ops = &mtk_dai_src_ops,
+	},
+};
+
+int mt8186_dai_src_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+	int ret;
+
+	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_src_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver);
+
+	dai->dapm_widgets = mtk_dai_src_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets);
+	dai->dapm_routes = mtk_dai_src_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes);
+
+	/* set dai priv */
+	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1,
+				  sizeof(struct mtk_afe_src_priv), NULL);
+	if (ret)
+		return ret;
+
+	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2,
+				  sizeof(struct mtk_afe_src_priv), NULL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 09/17] ASoC: mediatek: mt8186: support tdm in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (7 preceding siblings ...)
  2022-02-17 13:41 ` [v2 08/17] ASoC: mediatek: mt8186: support src " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 10/17] ASoC: mediatek: mt8186: support audio clock control " Jiaxin Yu
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 tdm dai driver.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 713 +++++++++++++++++++++
 1 file changed, 713 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c

diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
new file mode 100644
index 000000000000..28dd3661f0e0
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
@@ -0,0 +1,713 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MediaTek ALSA SoC Audio DAI TDM Control
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+
+#include "mt8186-afe-clk.h"
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-gpio.h"
+#include "mt8186-interconnection.h"
+
+#define TDM_HD_EN_W_NAME "TDM_HD_EN"
+#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"
+#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"
+
+struct mtk_afe_tdm_priv {
+	unsigned int id;
+	unsigned int rate; /* for determine which apll to use */
+	unsigned int bck_invert;
+	unsigned int lck_invert;
+	unsigned int lrck_width;
+	unsigned int mclk_id;
+	unsigned int mclk_multiple; /* according to sample rate */
+	unsigned int mclk_rate;
+	unsigned int mclk_apll;
+	unsigned int tdm_mode;
+	unsigned int data_mode;
+	unsigned int slave_mode;
+	unsigned int low_jitter_en;
+};
+
+enum {
+	TDM_IN_I2S = 0,
+	TDM_IN_LJ = 1,
+	TDM_IN_RJ = 2,
+	TDM_IN_DSP_A = 4,
+	TDM_IN_DSP_B = 5,
+};
+
+enum {
+	TDM_DATA_ONE_PIN = 0,
+	TDM_DATA_MULTI_PIN,
+};
+
+enum {
+	TDM_BCK_NON_INV = 0,
+	TDM_BCK_INV = 1,
+};
+
+enum {
+	TDM_LCK_NON_INV = 0,
+	TDM_LCK_INV = 1,
+};
+
+static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,
+				       unsigned int mode)
+{
+	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
+		return 0;
+	else
+		return snd_pcm_format_physical_width(format) - 1;
+}
+
+static unsigned int get_tdm_ch_fixup(unsigned int channels)
+{
+	if (channels > 4)
+		return 8;
+	else if (channels > 2)
+		return 4;
+	else
+		return 2;
+}
+
+static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
+					 unsigned int channels)
+{
+	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
+		return get_tdm_ch_fixup(channels);
+	else
+		return 2;
+}
+
+enum {
+	SUPPLY_SEQ_APLL,
+	SUPPLY_SEQ_TDM_MCK_EN,
+	SUPPLY_SEQ_TDM_HD_EN,
+	SUPPLY_SEQ_TDM_EN,
+};
+
+static int get_tdm_id_by_name(const char *name)
+{
+	return MT8186_DAI_TDM_IN;
+}
+
+static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol,
+			    int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	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_info(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);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		tdm_priv->mclk_rate = 0;
+		mt8186_mck_disable(afe, tdm_priv->mclk_id);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* dai component */
+/* tdm virtual mux to output widget */
+static const char * const tdm_mux_map[] = {
+	"Normal", "Dummy_Widget",
+};
+
+static int tdm_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum,
+					      SND_SOC_NOPM,
+					      0,
+					      1,
+					      tdm_mux_map,
+					      tdm_mux_map_value);
+
+static const struct snd_kcontrol_new tdm_in_mux_control =
+	SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
+
+	SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
+			      ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT,
+			      0, mtk_tdm_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	/* tdm hd en */
+	SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN,
+			      ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT,
+			      0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_tdm_mck_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"),
+
+	SND_SOC_DAPM_MUX("TDM_In_Mux",
+			 SND_SOC_NOPM, 0, 0, &tdm_in_mux_control),
+};
+
+static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,
+				    struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return 0;
+	}
+
+	return (tdm_priv->mclk_rate > 0) ? 1 : 0;
+}
+
+static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source,
+					 struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_tdm_id_by_name(w->name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+	int cur_apll;
+
+	/* which apll */
+	cur_apll = mt8186_get_apll_by_name(afe, source->name);
+
+	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
+}
+
+static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,
+				  struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return 0;
+	}
+
+	return tdm_priv->low_jitter_en;
+}
+
+static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
+				    struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_tdm_id_by_name(w->name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+	int cur_apll;
+	int tdm_need_apll;
+
+	if (!tdm_priv) {
+		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return 0;
+	}
+
+	/* which apll */
+	cur_apll = mt8186_get_apll_by_name(afe, source->name);
+
+	/* choose APLL from tdm rate */
+	tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate);
+
+	return (tdm_need_apll == cur_apll) ? 1 : 0;
+}
+
+/* low jitter control */
+static const char * const mt8186_tdm_hd_str[] = {
+	"Normal", "Low_Jitter"
+};
+
+static const struct soc_enum mt8186_tdm_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str),
+			    mt8186_tdm_hd_str),
+};
+
+static int mt8186_tdm_hd_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 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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;
+
+	return 0;
+}
+
+static int mt8186_tdm_hd_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 dai_id = get_tdm_id_by_name(kcontrol->id.name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int hd_en;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	hd_en = ucontrol->value.integer.value[0];
+
+	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
+		 __func__, kcontrol->id.name, hd_en);
+
+	if (!tdm_priv) {
+		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	tdm_priv->low_jitter_en = hd_en;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
+	SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],
+		     mt8186_tdm_hd_get, mt8186_tdm_hd_set),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
+	{"TDM IN", NULL, "aud_tdm_clk"},
+	{"TDM IN", NULL, "TDM_EN"},
+	{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},
+	{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
+	{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
+
+	{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},
+	{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect},
+	{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect},
+
+	/* allow tdm on without codec on */
+	{"TDM IN", NULL, "TDM_In_Mux"},
+	{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},
+};
+
+/* dai ops */
+static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
+				struct mtk_afe_tdm_priv *tdm_priv,
+				int freq)
+{
+	int apll;
+	int apll_rate;
+
+	apll = mt8186_get_apll_by_rate(afe, freq);
+	apll_rate = mt8186_get_apll_rate(afe, apll);
+
+	if (!freq || freq > apll_rate) {
+		dev_info(afe->dev,
+			 "%s(), freq(%d Hz) invalid\n", __func__, freq);
+		return -EINVAL;
+	}
+
+	if (apll_rate % freq != 0) {
+		dev_info(afe->dev,
+			 "%s(), APLL cannot generate %d Hz", __func__, freq);
+		return -EINVAL;
+	}
+
+	tdm_priv->mclk_rate = freq;
+	tdm_priv->mclk_apll = apll;
+
+	return 0;
+}
+
+static int mtk_dai_tdm_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);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int tdm_id = dai->id;
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
+	unsigned int tdm_mode = tdm_priv->tdm_mode;
+	unsigned int data_mode = tdm_priv->data_mode;
+	unsigned int rate = params_rate(params);
+	unsigned int channels = params_channels(params);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int bit_width =
+		snd_pcm_format_physical_width(format);
+	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?
+		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
+	unsigned int lrck_width =
+		get_tdm_lrck_width(format, tdm_mode);
+	unsigned int tdm_con = 0;
+	bool slave_mode = tdm_priv->slave_mode;
+	bool lrck_inv = tdm_priv->lck_invert;
+	bool bck_inv = tdm_priv->bck_invert;
+	unsigned int ctrl_reg;
+	unsigned int ctrl_mask;
+	unsigned int tran_rate;
+	unsigned int tran_relatch_rate;
+
+	if (tdm_priv)
+		tdm_priv->rate = rate;
+	else
+		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+
+	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);
+	}
+
+	/* ETDM_IN1_CON0 */
+	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
+	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
+	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
+	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
+	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;
+	/* default disable sync mode */
+	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;
+	/* relatch fix to h26m */
+	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
+
+	ctrl_reg = ETDM_IN1_CON0;
+	ctrl_mask = ETDM_IN_CON0_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	/* ETDM_IN1_CON1 */
+	tdm_con = 0;
+	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
+	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
+	tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
+
+	ctrl_reg = ETDM_IN1_CON1;
+	ctrl_mask = ETDM_IN_CON1_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	/* ETDM_IN1_CON3 */
+	tdm_con = 0;
+	tdm_con = ETDM_IN_CON3_FS(tran_rate);
+
+	ctrl_reg = ETDM_IN1_CON3;
+	ctrl_mask = ETDM_IN_CON3_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	/* ETDM_IN1_CON4 */
+	tdm_con = 0;
+	tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);
+	if (slave_mode) {
+		if (lrck_inv)
+			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;
+		if (bck_inv)
+			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;
+	} else {
+		if (lrck_inv)
+			tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;
+		if (bck_inv)
+			tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;
+	}
+
+	ctrl_reg = ETDM_IN1_CON4;
+	ctrl_mask = ETDM_IN_CON4_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	/* ETDM_IN1_CON2 */
+	tdm_con = 0;
+	if (data_mode == TDM_DATA_MULTI_PIN) {
+		tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;
+		tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);
+	}
+
+	ctrl_reg = ETDM_IN1_CON2;
+	ctrl_mask = ETDM_IN_CON2_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	/* ETDM_IN1_CON8 */
+	tdm_con = 0;
+	if (slave_mode) {
+		tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
+		tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;
+		tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);
+	} else {
+		tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
+	}
+
+	ctrl_reg = ETDM_IN1_CON8;
+	ctrl_mask = ETDM_IN_CON8_CTRL_MASK;
+	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
+
+	return 0;
+}
+
+static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	if (dir != SND_SOC_CLOCK_IN) {
+		dev_info(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
+		return -EINVAL;
+	}
+
+	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
+
+	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
+}
+
+static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
+		return -EINVAL;
+	}
+
+	/* DAI mode*/
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		tdm_priv->tdm_mode = TDM_IN_I2S;
+		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		tdm_priv->tdm_mode = TDM_IN_LJ;
+		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		tdm_priv->tdm_mode = TDM_IN_RJ;
+		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		tdm_priv->tdm_mode = TDM_IN_DSP_A;
+		tdm_priv->data_mode = TDM_DATA_ONE_PIN;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		tdm_priv->tdm_mode = TDM_IN_DSP_B;
+		tdm_priv->data_mode = TDM_DATA_ONE_PIN;
+		break;
+	default:
+		dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__);
+		return -EINVAL;
+	}
+
+	/* DAI clock inversion*/
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		tdm_priv->bck_invert = TDM_BCK_NON_INV;
+		tdm_priv->lck_invert = TDM_LCK_NON_INV;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		tdm_priv->bck_invert = TDM_BCK_NON_INV;
+		tdm_priv->lck_invert = TDM_LCK_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		tdm_priv->bck_invert = TDM_BCK_INV;
+		tdm_priv->lck_invert = TDM_LCK_NON_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		tdm_priv->bck_invert = TDM_BCK_INV;
+		tdm_priv->lck_invert = TDM_LCK_INV;
+		break;
+	default:
+		dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+	case SND_SOC_DAIFMT_CBP_CFP:
+		tdm_priv->slave_mode = false;
+		break;
+	case SND_SOC_DAIFMT_CBC_CFC:
+		tdm_priv->slave_mode = true;
+		break;
+	default:
+		dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK",
+			__func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai,
+				    unsigned int tx_mask,
+				    unsigned int rx_mask,
+				    int slots,
+				    int slot_width)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
+
+	dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width);
+
+	tdm_priv->lrck_width = slot_width;
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
+	.hw_params = mtk_dai_tdm_hw_params,
+	.set_sysclk = mtk_dai_tdm_set_sysclk,
+	.set_fmt = mtk_dai_tdm_set_fmt,
+	.set_tdm_slot = mtk_dai_tdm_set_tdm_slot,
+};
+
+/* dai driver */
+#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+		       SNDRV_PCM_RATE_88200 |\
+		       SNDRV_PCM_RATE_96000 |\
+		       SNDRV_PCM_RATE_176400 |\
+		       SNDRV_PCM_RATE_192000)
+
+#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE |\
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
+	{
+		.name = "TDM IN",
+		.id = MT8186_DAI_TDM_IN,
+		.capture = {
+			.stream_name = "TDM IN",
+			.channels_min = 2,
+			.channels_max = 8,
+			.rates = MTK_TDM_RATES,
+			.formats = MTK_TDM_FORMATS,
+		},
+		.ops = &mtk_dai_tdm_ops,
+	},
+};
+
+static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
+{
+	struct mtk_afe_tdm_priv *tdm_priv;
+
+	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
+				GFP_KERNEL);
+	if (!tdm_priv)
+		return NULL;
+
+	tdm_priv->mclk_multiple = 512;
+	tdm_priv->mclk_id = MT8186_TDM_MCK;
+	tdm_priv->id = MT8186_DAI_TDM_IN;
+
+	return tdm_priv;
+}
+
+int mt8186_dai_tdm_register(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_tdm_priv *tdm_priv;
+	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_tdm_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
+
+	dai->controls = mtk_dai_tdm_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);
+	dai->dapm_widgets = mtk_dai_tdm_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
+	dai->dapm_routes = mtk_dai_tdm_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
+
+	tdm_priv = init_tdm_priv_data(afe);
+	if (!tdm_priv)
+		return -ENOMEM;
+
+	afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv;
+
+	return 0;
+}
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 10/17] ASoC: mediatek: mt8186: support audio clock control in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (8 preceding siblings ...)
  2022-02-17 13:41 ` [v2 09/17] ASoC: mediatek: mt8186: support tdm " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:41 ` [v2 11/17] ASoC: mediatek: mt8186: support gpio " Jiaxin Yu
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch add audio clock control with CCF interface.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 719 +++++++++++++++++++++
 sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 210 ++++++
 2 files changed, 929 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h

diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
new file mode 100644
index 000000000000..14f64b935619
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
@@ -0,0 +1,719 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-afe-clk.c  --  Mediatek 8186 afe clock ctrl
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-clk.h"
+#include "mt8186-audsys-clk.h"
+
+static DEFINE_MUTEX(mutex_request_dram);
+
+static const char *aud_clks[CLK_NUM] = {
+	[CLK_AFE] = "aud_afe_clk",
+	[CLK_DAC] = "aud_dac_clk",
+	[CLK_DAC_PREDIS] = "aud_dac_predis_clk",
+	[CLK_ADC] = "aud_adc_clk",
+	[CLK_TML] = "aud_tml_clk",
+	[CLK_APLL22M] = "aud_apll22m_clk",
+	[CLK_APLL24M] = "aud_apll24m_clk",
+	[CLK_APLL1_TUNER] = "aud_apll_tuner_clk",
+	[CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
+	[CLK_TDM] = "aud_tdm_clk",
+	[CLK_NLE] = "aud_nle_clk",
+	[CLK_DAC_HIRES] = "aud_dac_hires_clk",
+	[CLK_ADC_HIRES] = "aud_adc_hires_clk",
+	[CLK_I2S1_BCLK] = "aud_i2s1_bclk",
+	[CLK_I2S2_BCLK] = "aud_i2s2_bclk",
+	[CLK_I2S3_BCLK] = "aud_i2s3_bclk",
+	[CLK_I2S4_BCLK] = "aud_i2s4_bclk",
+	[CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc",
+	[CLK_GENERAL1_ASRC] = "aud_general1_asrc",
+	[CLK_GENERAL2_ASRC] = "aud_general2_asrc",
+	[CLK_ADC_HIRES_TML] = "aud_adc_hires_tml",
+	[CLK_ADDA6_ADC] = "aud_adda6_adc",
+	[CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
+	[CLK_3RD_DAC] = "aud_3rd_dac",
+	[CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis",
+	[CLK_3RD_DAC_TML] = "aud_3rd_dac_tml",
+	[CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires",
+	[CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk",
+	[CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk",
+	[CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
+	[CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk",
+	[CLK_MUX_AUDIO] = "top_mux_audio",
+	[CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int",
+	[CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4",
+	[CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
+	[CLK_TOP_APLL1_CK] = "top_apll1_ck",
+	[CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
+	[CLK_TOP_APLL2_CK] = "top_apll2_ck",
+	[CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
+	[CLK_TOP_APLL1_D8] = "top_apll1_d8",
+	[CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
+	[CLK_TOP_APLL2_D8] = "top_apll2_d8",
+	[CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h",
+	[CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
+	[CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
+	[CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
+	[CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
+	[CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel",
+	[CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
+	[CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
+	[CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
+	[CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
+	[CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm",
+	[CLK_CLK26M] = "top_clk26m_clk",
+};
+
+int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe,
+				    int clk_id)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
+			     afe_priv->clk[clk_id]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS],
+			 aud_clks[clk_id], ret);
+	}
+
+	return ret;
+}
+
+static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	if (enable) {
+		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_1], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
+				     afe_priv->clk[CLK_TOP_APLL1_CK]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
+				 aud_clks[CLK_TOP_APLL1_CK], ret);
+			goto EXIT;
+		}
+
+		/* 180.6336 / 8 = 22.5792MHz */
+		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
+				     afe_priv->clk[CLK_TOP_APLL1_D8]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
+				 aud_clks[CLK_TOP_APLL1_D8], ret);
+			goto EXIT;
+		}
+	} else {
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
+				 aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
+
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
+				 aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
+	}
+EXIT:
+	return 0;
+}
+
+static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	if (enable) {
+		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_2], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
+				     afe_priv->clk[CLK_TOP_APLL2_CK]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
+				 aud_clks[CLK_TOP_APLL2_CK], ret);
+			goto EXIT;
+		}
+
+		/* 196.608 / 8 = 24.576MHz */
+		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
+				     afe_priv->clk[CLK_TOP_APLL2_D8]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
+				 aud_clks[CLK_TOP_APLL2_D8], ret);
+			goto EXIT;
+		}
+	} else {
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
+				 aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
+
+		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
+				 aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
+	}
+
+EXIT:
+	return 0;
+}
+
+int mt8186_afe_enable_cgs(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+	int i;
+
+	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) {
+		ret = clk_prepare_enable(afe_priv->clk[i]);
+		if (ret) {
+			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[i], ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+void mt8186_afe_disable_cgs(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int i;
+
+	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++)
+		clk_disable_unprepare(afe_priv->clk[i]);
+}
+
+int mt8186_afe_enable_clock(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);
+		goto CLK_INFRA_SYS_AUDIO_ERR;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret);
+		goto CLK_INFRA_AUDIO_26M_ERR;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIO], ret);
+		goto CLK_MUX_AUDIO_ERR;
+	}
+	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
+			     afe_priv->clk[CLK_CLK26M]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIO],
+			 aud_clks[CLK_CLK26M], ret);
+		goto CLK_MUX_AUDIO_ERR;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
+		goto CLK_MUX_AUDIO_INTBUS_ERR;
+	}
+	ret = mt8186_set_audio_int_bus_parent(afe,
+					      CLK_TOP_MAINPLL_D2_D4);
+	if (ret)
+		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
+
+	ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H],
+			     afe_priv->clk[CLK_TOP_APLL2_CK]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+			 __func__, aud_clks[CLK_TOP_MUX_AUDIO_H],
+			 aud_clks[CLK_TOP_APLL2_CK], ret);
+		goto CLK_MUX_AUDIO_H_PARENT_ERR;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_AFE], ret);
+		goto CLK_AFE_ERR;
+	}
+
+	return 0;
+
+CLK_AFE_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
+CLK_MUX_AUDIO_H_PARENT_ERR:
+CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
+	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
+CLK_MUX_AUDIO_INTBUS_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+CLK_MUX_AUDIO_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
+CLK_INFRA_SYS_AUDIO_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
+CLK_INFRA_AUDIO_26M_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
+
+	return ret;
+}
+
+void mt8186_afe_disable_clock(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
+	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
+	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
+	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
+}
+
+int mt8186_afe_suspend_clock(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* set audio int bus to 26M */
+	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
+		goto CLK_MUX_AUDIO_INTBUS_ERR;
+	}
+	ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
+	if (ret)
+		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
+
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+
+	return 0;
+
+CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
+	mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4);
+CLK_MUX_AUDIO_INTBUS_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	return ret;
+}
+
+int mt8186_afe_resume_clock(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* set audio int bus to normal working clock */
+	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
+		goto CLK_MUX_AUDIO_INTBUS_ERR;
+	}
+	ret = mt8186_set_audio_int_bus_parent(afe,
+					      CLK_TOP_MAINPLL_D2_D4);
+	if (ret)
+		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
+
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+
+	return 0;
+
+CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
+	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
+CLK_MUX_AUDIO_INTBUS_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
+	return ret;
+}
+
+int mt8186_apll1_enable(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* setting for APLL */
+	apll1_mux_setting(afe, true);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_APLL22M], ret);
+		goto ERR_CLK_APLL22M;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_APLL1_TUNER], ret);
+		goto ERR_CLK_APLL1_TUNER;
+	}
+
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+			   0x0000FFF7, 0x00000832);
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
+
+	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+			   AFE_22M_ON_MASK_SFT,
+			   0x1 << AFE_22M_ON_SFT);
+
+	return 0;
+
+ERR_CLK_APLL1_TUNER:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
+ERR_CLK_APLL22M:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
+
+	return ret;
+}
+
+void mt8186_apll1_disable(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+			   AFE_22M_ON_MASK_SFT,
+			   0x0 << AFE_22M_ON_SFT);
+
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
+
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
+
+	apll1_mux_setting(afe, false);
+}
+
+int mt8186_apll2_enable(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* setting for APLL */
+	apll2_mux_setting(afe, true);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_APLL24M], ret);
+		goto ERR_CLK_APLL24M;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
+	if (ret) {
+		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[CLK_APLL2_TUNER], ret);
+		goto ERR_CLK_APLL2_TUNER;
+	}
+
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+			   0x0000FFF7, 0x00000634);
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
+
+	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+			   AFE_24M_ON_MASK_SFT,
+			   0x1 << AFE_24M_ON_SFT);
+
+	return 0;
+
+ERR_CLK_APLL2_TUNER:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
+ERR_CLK_APLL24M:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
+
+	return ret;
+}
+
+void mt8186_apll2_disable(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+
+	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+			   AFE_24M_ON_MASK_SFT,
+			   0x0 << AFE_24M_ON_SFT);
+
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
+
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
+
+	apll2_mux_setting(afe, false);
+}
+
+int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll)
+{
+	return (apll == MT8186_APLL1) ? 180633600 : 196608000;
+}
+
+int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
+{
+	return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1;
+}
+
+int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
+{
+	if (strcmp(name, APLL1_W_NAME) == 0)
+		return MT8186_APLL1;
+	else
+		return MT8186_APLL2;
+}
+
+/* mck */
+struct mt8186_mck_div {
+	int m_sel_id;
+	int div_clk_id;
+	/* below will be deprecated */
+	int div_pdn_reg;
+	int div_pdn_mask_sft;
+	int div_reg;
+	int div_mask_sft;
+	int div_mask;
+	int div_sft;
+	int div_msb_reg;
+	int div_msb_mask_sft;
+	int div_msb_mask;
+	int div_msb_sft;
+	int div_apll_sel_reg;
+	int div_apll_sel_mask_sft;
+	int div_apll_sel_sft;
+	int div_inv_reg;
+	int div_inv_mask_sft;
+};
+
+static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = {
+	[MT8186_I2S0_MCK] = {
+		.m_sel_id = CLK_TOP_I2S0_M_SEL,
+		.div_clk_id = CLK_TOP_APLL12_DIV0,
+		.div_pdn_reg = CLK_AUDDIV_0,
+		.div_pdn_mask_sft = APLL12_DIV0_PDN_MASK_SFT,
+		.div_reg = CLK_AUDDIV_2,
+		.div_mask_sft = APLL12_CK_DIV0_MASK_SFT,
+		.div_mask = APLL12_CK_DIV0_MASK,
+		.div_sft = APLL12_CK_DIV0_SFT,
+		.div_apll_sel_reg = CLK_AUDDIV_0,
+		.div_apll_sel_mask_sft = APLL_I2S0_MCK_SEL_MASK_SFT,
+		.div_apll_sel_sft = APLL_I2S0_MCK_SEL_SFT,
+	},
+	[MT8186_I2S1_MCK] = {
+		.m_sel_id = CLK_TOP_I2S1_M_SEL,
+		.div_clk_id = CLK_TOP_APLL12_DIV1,
+		.div_pdn_reg = CLK_AUDDIV_0,
+		.div_pdn_mask_sft = APLL12_DIV1_PDN_MASK_SFT,
+		.div_reg = CLK_AUDDIV_2,
+		.div_mask_sft = APLL12_CK_DIV1_MASK_SFT,
+		.div_mask = APLL12_CK_DIV1_MASK,
+		.div_sft = APLL12_CK_DIV1_SFT,
+		.div_apll_sel_reg = CLK_AUDDIV_0,
+		.div_apll_sel_mask_sft = APLL_I2S1_MCK_SEL_MASK_SFT,
+		.div_apll_sel_sft = APLL_I2S1_MCK_SEL_SFT,
+	},
+	[MT8186_I2S2_MCK] = {
+		.m_sel_id = CLK_TOP_I2S2_M_SEL,
+		.div_clk_id = CLK_TOP_APLL12_DIV2,
+		.div_pdn_reg = CLK_AUDDIV_0,
+		.div_pdn_mask_sft = APLL12_DIV2_PDN_MASK_SFT,
+		.div_reg = CLK_AUDDIV_2,
+		.div_mask_sft = APLL12_CK_DIV2_MASK_SFT,
+		.div_mask = APLL12_CK_DIV2_MASK,
+		.div_sft = APLL12_CK_DIV2_SFT,
+		.div_apll_sel_reg = CLK_AUDDIV_0,
+		.div_apll_sel_mask_sft = APLL_I2S2_MCK_SEL_MASK_SFT,
+		.div_apll_sel_sft = APLL_I2S2_MCK_SEL_SFT,
+	},
+	[MT8186_I2S4_MCK] = {
+		.m_sel_id = CLK_TOP_I2S4_M_SEL,
+		.div_clk_id = CLK_TOP_APLL12_DIV4,
+		.div_pdn_reg = CLK_AUDDIV_0,
+		.div_pdn_mask_sft = APLL12_DIV4_PDN_MASK_SFT,
+		.div_reg = CLK_AUDDIV_2,
+		.div_mask_sft = APLL12_CK_DIV4_MASK_SFT,
+		.div_mask = APLL12_CK_DIV4_MASK,
+		.div_sft = APLL12_CK_DIV4_SFT,
+		.div_apll_sel_reg = CLK_AUDDIV_0,
+		.div_apll_sel_mask_sft = APLL_I2S4_MCK_SEL_MASK_SFT,
+		.div_apll_sel_sft = APLL_I2S4_MCK_SEL_SFT,
+	},
+	[MT8186_TDM_MCK] = {
+		.m_sel_id = CLK_TOP_TDM_M_SEL,
+		.div_clk_id = CLK_TOP_APLL12_DIV_TDM,
+		.div_pdn_reg = CLK_AUDDIV_0,
+		.div_pdn_mask_sft = APLL12_DIV_TDM_PDN_MASK_SFT,
+		.div_reg = CLK_AUDDIV_3,
+		.div_mask_sft = APLL12_CK_DIV_TDM_MASK_SFT,
+		.div_mask = APLL12_CK_DIV_TDM_MASK,
+		.div_sft = APLL12_CK_DIV_TDM_SFT,
+		.div_apll_sel_reg = CLK_AUDDIV_0,
+		.div_apll_sel_mask_sft = APLL_TDM_MCK_SEL_MASK_SFT,
+		.div_apll_sel_sft = APLL_TDM_MCK_SEL_SFT,
+	},
+};
+
+int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int apll = mt8186_get_apll_by_rate(afe, rate);
+	int apll_clk_id = apll == MT8186_APLL1 ?
+			  CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
+	int m_sel_id = mck_div[mck_id].m_sel_id;
+	int div_clk_id = mck_div[mck_id].div_clk_id;
+	int ret;
+
+	/* select apll */
+	if (m_sel_id >= 0) {
+		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
+		if (ret) {
+			dev_info(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
+				 __func__, aud_clks[m_sel_id], ret);
+			return ret;
+		}
+		ret = clk_set_parent(afe_priv->clk[m_sel_id],
+				     afe_priv->clk[apll_clk_id]);
+		if (ret) {
+			dev_info(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
+				 __func__, aud_clks[m_sel_id],
+				aud_clks[apll_clk_id], ret);
+			return ret;
+		}
+	}
+
+	/* enable div, set rate */
+	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
+	if (ret) {
+		dev_info(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
+			 __func__, aud_clks[div_clk_id], ret);
+		return ret;
+	}
+	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
+	if (ret) {
+		dev_info(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
+			 __func__, aud_clks[div_clk_id],
+			 rate, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	int m_sel_id = mck_div[mck_id].m_sel_id;
+	int div_clk_id = mck_div[mck_id].div_clk_id;
+
+	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
+	if (m_sel_id >= 0)
+		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
+}
+
+int mt8186_init_clock(struct mtk_base_afe *afe)
+{
+	struct mt8186_afe_private *afe_priv = afe->platform_priv;
+	struct device_node *of_node = afe->dev->of_node;
+	int i = 0;
+
+	 mt8186_audsys_clk_register(afe);
+
+	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
+				     GFP_KERNEL);
+	if (!afe_priv->clk)
+		return -ENOMEM;
+
+	for (i = 0; i < CLK_NUM; i++) {
+		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
+		if (IS_ERR(afe_priv->clk[i])) {
+			dev_info(afe->dev, "%s devm_clk_get %s fail, ret %ld\n",
+				 __func__,
+				 aud_clks[i], PTR_ERR(afe_priv->clk[i]));
+			afe_priv->clk[i] = NULL;
+		}
+	}
+
+	afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node,
+							       "mediatek,apmixedsys");
+	if (IS_ERR(afe_priv->apmixedsys)) {
+		dev_err(afe->dev, "%s() Cannot find apmixedsys controller: %ld\n",
+			__func__, PTR_ERR(afe_priv->apmixedsys));
+		return PTR_ERR(afe_priv->apmixedsys);
+	}
+
+	afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node,
+							     "mediatek,topckgen");
+	if (IS_ERR(afe_priv->topckgen)) {
+		dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
+			__func__, PTR_ERR(afe_priv->topckgen));
+		return PTR_ERR(afe_priv->topckgen);
+	}
+
+	afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node,
+							     "mediatek,infracfg");
+	if (IS_ERR(afe_priv->infracfg)) {
+		dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n",
+			__func__, PTR_ERR(afe_priv->infracfg));
+		return PTR_ERR(afe_priv->infracfg);
+	}
+
+	return 0;
+}
+
+void mt8186_deinit_clock(struct mtk_base_afe *afe)
+{
+	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
new file mode 100644
index 000000000000..3ce7a9a24d4a
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * mt8186-afe-clk.h  --  Mediatek 8186 afe clock ctrl definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+ */
+
+#ifndef _MT8186_AFE_CLOCK_CTRL_H_
+#define _MT8186_AFE_CLOCK_CTRL_H_
+
+#define PERI_BUS_DCM_CTRL 0x0074
+#define MODULE_SW_CG_1_STA 0x0094
+#define MODULE_SW_CG_2_STA 0x00ac
+#define CLK_CFG_7 0x0080
+#define CLK_CFG_8 0x0090
+#define CLK_CFG_11 0x00c0
+#define CLK_CFG_12 0x00d0
+#define CLK_CFG_13 0x00e0
+#define CLK_CFG_15 0x0100
+#define AP_PLL_CON3 0x0014
+#define APLL1_CON4 0x0328
+#define APLL1_TUNER_CON0 0x0040
+#define APLL2_CON4 0x033c
+#define APLL2_TUNER_CON0 0x0044
+
+#define AP_PLL_CON5 0x0014
+#define APLL1_CON0 0x02c0
+#define APLL1_CON1 0x02c4
+#define APLL1_CON2 0x02c8
+#define APLL1_CON3 0x02cc
+#define APLL1_PWR_CON0 0x02d0
+
+#define APLL2_CON0 0x02d4
+#define APLL2_CON1 0x02d8
+#define APLL2_CON2 0x02dc
+#define APLL2_CON3 0x02e0
+#define APLL2_PWR_CON0 0x02e4
+
+#define APMIXEDSYS_MAX_LENGTH APLL2_PWR_CON0
+
+#define CLK_CFG_6 0x0080
+#define CLK_AUDDIV_0 0x0320
+#define CLK_AUDDIV_1 0x0324
+#define CLK_AUDDIV_2 0x0328
+#define CKSYS_AUD_TOP_CFG 0x032c
+#define CKSYS_AUD_TOP_MON 0x0330
+#define CLK_AUDDIV_3 0x0334
+
+#define CLK_MAX_LENGTH CLK_AUDDIV_3
+
+/* CLK_CFG_6 */
+#define CLK_AUD_INTBUS_SEL_SFT              16
+#define CLK_AUD_INTBUS_SEL_MASK             0x3
+#define CLK_AUD_INTBUS_SEL_MASK_SFT         (0x3 << 16)
+
+/* CLK_AUDDIV_0 */
+#define APLL12_DIV0_PDN_SFT                0
+#define APLL12_DIV0_PDN_MASK               0x1
+#define APLL12_DIV0_PDN_MASK_SFT           (0x1 << 0)
+#define APLL12_DIV1_PDN_SFT                1
+#define APLL12_DIV1_PDN_MASK               0x1
+#define APLL12_DIV1_PDN_MASK_SFT           (0x1 << 1)
+#define APLL12_DIV2_PDN_SFT                2
+#define APLL12_DIV2_PDN_MASK               0x1
+#define APLL12_DIV2_PDN_MASK_SFT           (0x1 << 2)
+#define APLL12_DIV4_PDN_SFT                3
+#define APLL12_DIV4_PDN_MASK               0x1
+#define APLL12_DIV4_PDN_MASK_SFT           (0x1 << 3)
+#define APLL12_DIV_TDM_PDN_SFT             4
+#define APLL12_DIV_TDM_PDN_MASK            0x1
+#define APLL12_DIV_TDM_PDN_MASK_SFT        (0x1 << 4)
+#define APLL_I2S0_MCK_SEL_SFT              16
+#define APLL_I2S0_MCK_SEL_MASK             0x1
+#define APLL_I2S0_MCK_SEL_MASK_SFT         (0x1 << 16)
+#define APLL_I2S1_MCK_SEL_SFT              17
+#define APLL_I2S1_MCK_SEL_MASK             0x1
+#define APLL_I2S1_MCK_SEL_MASK_SFT         (0x1 << 17)
+#define APLL_I2S2_MCK_SEL_SFT              18
+#define APLL_I2S2_MCK_SEL_MASK             0x1
+#define APLL_I2S2_MCK_SEL_MASK_SFT         (0x1 << 17)
+#define APLL_I2S4_MCK_SEL_SFT              19
+#define APLL_I2S4_MCK_SEL_MASK             0x1
+#define APLL_I2S4_MCK_SEL_MASK_SFT         (0x1 << 19)
+#define APLL_TDM_MCK_SEL_SFT               20
+#define APLL_TDM_MCK_SEL_MASK              0x1
+#define APLL_TDM_MCK_SEL_MASK_SFT          (0x1 << 20)
+
+/* CLK_AUDDIV_2 */
+#define APLL12_CK_DIV0_SFT                 0
+#define APLL12_CK_DIV0_MASK                0xff
+#define APLL12_CK_DIV0_MASK_SFT            (0xff << 0)
+#define APLL12_CK_DIV1_SFT                 8
+#define APLL12_CK_DIV1_MASK                0xff
+#define APLL12_CK_DIV1_MASK_SFT            (0xff << 8)
+#define APLL12_CK_DIV2_SFT                 16
+#define APLL12_CK_DIV2_MASK                0xff
+#define APLL12_CK_DIV2_MASK_SFT            (0xff << 16)
+#define APLL12_CK_DIV4_SFT                 24
+#define APLL12_CK_DIV4_MASK                0xff
+#define APLL12_CK_DIV4_MASK_SFT            (0xff << 24)
+
+/* CLK_AUDDIV_3 */
+#define APLL12_CK_DIV_TDM_SFT              0
+#define APLL12_CK_DIV_TDM_MASK             0xff
+#define APLL12_CK_DIV_TDM_MASK_SFT         (0xff << 0)
+
+/* AUD_TOP_CFG */
+#define AUD_TOP_CFG_SFT                    0
+#define AUD_TOP_CFG_MASK                   0xffffffff
+#define AUD_TOP_CFG_MASK_SFT               (0xffffffff << 0)
+
+/* AUD_TOP_MON */
+#define AUD_TOP_MON_SFT                    0
+#define AUD_TOP_MON_MASK                   0xffffffff
+#define AUD_TOP_MON_MASK_SFT               (0xffffffff << 0)
+
+/* APLL */
+#define APLL1_W_NAME "APLL1"
+#define APLL2_W_NAME "APLL2"
+enum {
+	MT8186_APLL1 = 0,
+	MT8186_APLL2,
+};
+
+enum {
+	CLK_AFE = 0,
+	CLK_DAC,
+	CLK_DAC_PREDIS,
+	CLK_ADC,
+	CLK_TML,
+	CLK_APLL22M,
+	CLK_APLL24M,
+	CLK_APLL1_TUNER,
+	CLK_APLL2_TUNER,
+	CLK_TDM,
+	CLK_NLE,
+	CLK_DAC_HIRES,
+	CLK_ADC_HIRES,
+	CLK_I2S1_BCLK,
+	CLK_I2S2_BCLK,
+	CLK_I2S3_BCLK,
+	CLK_I2S4_BCLK,
+	CLK_CONNSYS_I2S_ASRC,
+	CLK_GENERAL1_ASRC,
+	CLK_GENERAL2_ASRC,
+	CLK_ADC_HIRES_TML,
+	CLK_ADDA6_ADC,
+	CLK_ADDA6_ADC_HIRES,
+	CLK_3RD_DAC,
+	CLK_3RD_DAC_PREDIS,
+	CLK_3RD_DAC_TML,
+	CLK_3RD_DAC_HIRES,
+	CLK_ETDM_IN1_BCLK,
+	CLK_ETDM_OUT1_BCLK,
+	CLK_INFRA_SYS_AUDIO,
+	CLK_INFRA_AUDIO_26M,
+	CLK_MUX_AUDIO,
+	CLK_MUX_AUDIOINTBUS,
+	CLK_TOP_MAINPLL_D2_D4,
+	/* apll related mux */
+	CLK_TOP_MUX_AUD_1,
+	CLK_TOP_APLL1_CK,
+	CLK_TOP_MUX_AUD_2,
+	CLK_TOP_APLL2_CK,
+	CLK_TOP_MUX_AUD_ENG1,
+	CLK_TOP_APLL1_D8,
+	CLK_TOP_MUX_AUD_ENG2,
+	CLK_TOP_APLL2_D8,
+	CLK_TOP_MUX_AUDIO_H,
+	CLK_TOP_I2S0_M_SEL,
+	CLK_TOP_I2S1_M_SEL,
+	CLK_TOP_I2S2_M_SEL,
+	CLK_TOP_I2S4_M_SEL,
+	CLK_TOP_TDM_M_SEL,
+	CLK_TOP_APLL12_DIV0,
+	CLK_TOP_APLL12_DIV1,
+	CLK_TOP_APLL12_DIV2,
+	CLK_TOP_APLL12_DIV4,
+	CLK_TOP_APLL12_DIV_TDM,
+	CLK_CLK26M,
+	CLK_NUM
+};
+
+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);
+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);
+void mt8186_afe_disable_clock(struct mtk_base_afe *afe);
+int mt8186_afe_suspend_clock(struct mtk_base_afe *afe);
+int mt8186_afe_resume_clock(struct mtk_base_afe *afe);
+
+int mt8186_apll1_enable(struct mtk_base_afe *afe);
+void mt8186_apll1_disable(struct mtk_base_afe *afe);
+
+int mt8186_apll2_enable(struct mtk_base_afe *afe);
+void mt8186_apll2_disable(struct mtk_base_afe *afe);
+
+int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll);
+int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
+int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
+
+/* these will be replaced by using CCF */
+int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
+void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id);
+
+#endif
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 11/17] ASoC: mediatek: mt8186: support gpio control in platform driver
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (9 preceding siblings ...)
  2022-02-17 13:41 ` [v2 10/17] ASoC: mediatek: mt8186: support audio clock control " Jiaxin Yu
@ 2022-02-17 13:41 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:42 ` [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document Jiaxin Yu
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:41 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch add gpio control for all audio interface separately.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 210 ++++++++++++++++++++
 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h |  19 ++
 2 files changed, 229 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h

diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
new file mode 100644
index 000000000000..6faec5c95bf3
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8186-afe-gpio.c  --  Mediatek 8186 afe gpio ctrl
+//
+// Copyright (c) 2022 MediaTek Inc.
+// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "mt8186-afe-common.h"
+#include "mt8186-afe-gpio.h"
+
+struct pinctrl *aud_pinctrl;
+
+enum mt8186_afe_gpio {
+	MT8186_AFE_GPIO_CLK_MOSI_OFF,
+	MT8186_AFE_GPIO_CLK_MOSI_ON,
+	MT8186_AFE_GPIO_CLK_MISO_OFF,
+	MT8186_AFE_GPIO_CLK_MISO_ON,
+	MT8186_AFE_GPIO_DAT_MISO_OFF,
+	MT8186_AFE_GPIO_DAT_MISO_ON,
+	MT8186_AFE_GPIO_DAT_MOSI_OFF,
+	MT8186_AFE_GPIO_DAT_MOSI_ON,
+	MT8186_AFE_GPIO_I2S0_OFF,
+	MT8186_AFE_GPIO_I2S0_ON,
+	MT8186_AFE_GPIO_I2S1_OFF,
+	MT8186_AFE_GPIO_I2S1_ON,
+	MT8186_AFE_GPIO_I2S2_OFF,
+	MT8186_AFE_GPIO_I2S2_ON,
+	MT8186_AFE_GPIO_I2S3_OFF,
+	MT8186_AFE_GPIO_I2S3_ON,
+	MT8186_AFE_GPIO_TDM_OFF,
+	MT8186_AFE_GPIO_TDM_ON,
+	MT8186_AFE_GPIO_PCM_OFF,
+	MT8186_AFE_GPIO_PCM_ON,
+	MT8186_AFE_GPIO_GPIO_NUM
+};
+
+struct audio_gpio_attr {
+	const char *name;
+	bool gpio_prepare;
+	struct pinctrl_state *gpioctrl;
+};
+
+static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM] = {
+	[MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL},
+	[MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL},
+	[MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false, NULL},
+	[MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false, NULL},
+	[MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL},
+	[MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL},
+	[MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL},
+	[MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL},
+	[MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL},
+	[MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL},
+	[MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL},
+	[MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL},
+	[MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL},
+	[MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL},
+	[MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL},
+	[MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL},
+	[MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL},
+	[MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL},
+	[MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL},
+	[MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL},
+};
+
+static DEFINE_MUTEX(gpio_request_mutex);
+
+int mt8186_afe_gpio_init(struct device *dev)
+{
+	int ret;
+	int i = 0;
+
+	aud_pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(aud_pinctrl)) {
+		ret = PTR_ERR(aud_pinctrl);
+		dev_info(dev, "%s(), ret %d, cannot get aud_pinctrl!\n",
+			 __func__, ret);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
+		aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl,
+							     aud_gpios[i].name);
+		if (IS_ERR(aud_gpios[i].gpioctrl)) {
+			ret = PTR_ERR(aud_gpios[i].gpioctrl);
+			dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n",
+				 __func__, aud_gpios[i].name, ret);
+		} else {
+			aud_gpios[i].gpio_prepare = true;
+		}
+	}
+
+	/* gpio status init */
+	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 0);
+	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init);
+
+static int mt8186_afe_gpio_select(struct device *dev,
+				  enum mt8186_afe_gpio type)
+{
+	int ret = 0;
+
+	if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) {
+		dev_info(dev, "%s(), error, invalid gpio type %d\n",
+			 __func__, type);
+		return -EINVAL;
+	}
+
+	if (!aud_gpios[type].gpio_prepare) {
+		dev_info(dev, "%s(), error, gpio type %d not prepared\n",
+			 __func__, type);
+		return -EIO;
+	}
+
+	ret = pinctrl_select_state(aud_pinctrl,
+				   aud_gpios[type].gpioctrl);
+	if (ret)
+		dev_info(dev, "%s(), error, can not set gpio type %d\n",
+			 __func__, type);
+
+	return ret;
+}
+
+static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable)
+{
+	if (enable) {
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON);
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON);
+	} else {
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF);
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF);
+	}
+
+	return 0;
+}
+
+static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable)
+{
+	if (enable) {
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON);
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON);
+	} else {
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF);
+		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF);
+	}
+
+	return 0;
+}
+
+int mt8186_afe_gpio_request(struct device *dev, bool enable,
+			    int dai, int uplink)
+{
+	mutex_lock(&gpio_request_mutex);
+	switch (dai) {
+	case MT8186_DAI_ADDA:
+		if (uplink)
+			mt8186_afe_gpio_adda_ul(dev, enable);
+		else
+			mt8186_afe_gpio_adda_dl(dev, enable);
+		break;
+	case MT8186_DAI_I2S_0:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S0_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S0_OFF);
+		break;
+	case MT8186_DAI_I2S_1:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S1_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S1_OFF);
+		break;
+	case MT8186_DAI_I2S_2:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S2_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S2_OFF);
+		break;
+	case MT8186_DAI_I2S_3:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S3_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S3_OFF);
+		break;
+	case MT8186_DAI_TDM_IN:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_TDM_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_TDM_OFF);
+		break;
+	case MT8186_DAI_PCM:
+		if (enable)
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_PCM_ON);
+		else
+			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_PCM_OFF);
+		break;
+	default:
+		mutex_unlock(&gpio_request_mutex);
+		dev_info(dev, "%s(), invalid dai %d\n", __func__, dai);
+		return -EINVAL;
+	}
+	mutex_unlock(&gpio_request_mutex);
+	return 0;
+}
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
new file mode 100644
index 000000000000..1ddc27838eb1
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * mt6833-afe-gpio.h  --  Mediatek 6833 afe gpio ctrl definition
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
+ */
+
+#ifndef _MT8186_AFE_GPIO_H_
+#define _MT8186_AFE_GPIO_H_
+
+struct mtk_base_afe;
+
+int mt8186_afe_gpio_init(struct device *dev);
+
+int mt8186_afe_gpio_request(struct device *dev, bool enable,
+			    int dai, int uplink);
+
+#endif
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (10 preceding siblings ...)
  2022-02-17 13:41 ` [v2 11/17] ASoC: mediatek: mt8186: support gpio " Jiaxin Yu
@ 2022-02-17 13:42 ` Jiaxin Yu
  2022-02-25 16:43   ` Rob Herring
  2022-02-17 13:42 ` [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357 Jiaxin Yu
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:42 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds mt8186 audio afe document.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../bindings/sound/mt8186-afe-pcm.yaml        | 175 ++++++++++++++++++
 1 file changed, 175 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml

diff --git a/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
new file mode 100644
index 000000000000..88f82d096443
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8186-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek AFE PCM controller for mt8186
+
+maintainers:
+  - Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8186-sound
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    const: audiosys
+
+  mediatek,apmixedsys:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of the mediatek apmixedsys controller
+
+  mediatek,infracfg:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of the mediatek infracfg controller
+
+  mediatek,topckgen:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of the mediatek topckgen controller
+
+  clocks:
+    items:
+      - description: audio infra sys clock
+      - description: audio infra 26M clock
+      - description: audio top mux
+      - description: audio intbus mux
+      - description: mainpll 136.5M clock
+      - description: faud1 mux
+      - description: apll1 clock
+      - description: faud2 mux
+      - description: apll2 clock
+      - description: audio engen1 mux
+      - description: apll1_d8 22.5792M clock
+      - description: audio engen2 mux
+      - description: apll2_d8 24.576M clock
+      - description: i2s0 mclk mux
+      - description: i2s1 mclk mux
+      - description: i2s2 mclk mux
+      - description: i2s4 mclk mux
+      - description: tdm mclk mux
+      - description: i2s0_mck divider
+      - description: i2s1_mck divider
+      - description: i2s2_mck divider
+      - description: i2s4_mck divider
+      - description: tdm_mck divider
+      - description: audio hires mux
+      - description: 26M clock
+
+  clock-names:
+    items:
+      - const: aud_infra_clk
+      - const: mtkaif_26m_clk
+      - const: top_mux_audio
+      - const: top_mux_audio_int
+      - const: top_mainpll_d2_d4
+      - const: top_mux_aud_1
+      - const: top_apll1_ck
+      - const: top_mux_aud_2
+      - const: top_apll2_ck
+      - const: top_mux_aud_eng1
+      - const: top_apll1_d8
+      - const: top_mux_aud_eng2
+      - const: top_apll2_d8
+      - const: top_i2s0_m_sel
+      - const: top_i2s1_m_sel
+      - const: top_i2s2_m_sel
+      - const: top_i2s4_m_sel
+      - const: top_tdm_m_sel
+      - const: top_apll12_div0
+      - const: top_apll12_div1
+      - const: top_apll12_div2
+      - const: top_apll12_div4
+      - const: top_apll12_div_tdm
+      - const: top_mux_audio_h
+      - const: top_clk26m_clk
+
+required:
+  - compatible
+  - interrupts
+  - resets
+  - reset-names
+  - mediatek,apmixedsys
+  - mediatek,infracfg
+  - mediatek,topckgen
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    afe: mt8186-afe-pcm@11210000 {
+        compatible = "mediatek,mt8186-sound";
+        reg = <0x11210000 0x2000>;
+        interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+        resets = <&watchdog 17>; //MT8186_TOPRGU_AUDIO_SW_RST
+        reset-names = "audiosys";
+        mediatek,apmixedsys = <&apmixedsys>;
+        mediatek,infracfg = <&infracfg>;
+        mediatek,topckgen = <&topckgen>;
+        clocks = <&infracfg_ao 44>, //CLK_INFRA_AO_AUDIO
+                 <&infracfg_ao 54>, //CLK_INFRA_AO_AUDIO_26M_BCLK
+                 <&topckgen 15>, //CLK_TOP_AUDIO
+                 <&topckgen 16>, //CLK_TOP_AUD_INTBUS
+                 <&topckgen 70>, //CLK_TOP_MAINPLL_D2_D4
+                 <&topckgen 17>, //CLK_TOP_AUD_1
+                 <&apmixedsys 12>, //CLK_APMIXED_APLL1
+                 <&topckgen 18>, //CLK_TOP_AUD_2
+                 <&apmixedsys 13>, //CLK_APMIXED_APLL2
+                 <&topckgen 19>, //CLK_TOP_AUD_ENGEN1
+                 <&topckgen 101>, //CLK_TOP_APLL1_D8
+                 <&topckgen 20>, //CLK_TOP_AUD_ENGEN2
+                 <&topckgen 104>, //CLK_TOP_APLL2_D8
+                 <&topckgen 63>, //CLK_TOP_APLL_I2S0_MCK_SEL
+                 <&topckgen 64>, //CLK_TOP_APLL_I2S1_MCK_SEL
+                 <&topckgen 65>, //CLK_TOP_APLL_I2S2_MCK_SEL
+                 <&topckgen 66>, //CLK_TOP_APLL_I2S4_MCK_SEL
+                 <&topckgen 67>, //CLK_TOP_APLL_TDMOUT_MCK_SEL
+                 <&topckgen 131>, //CLK_TOP_APLL12_CK_DIV0
+                 <&topckgen 132>, //CLK_TOP_APLL12_CK_DIV1
+                 <&topckgen 133>, //CLK_TOP_APLL12_CK_DIV2
+                 <&topckgen 134>, //CLK_TOP_APLL12_CK_DIV4
+                 <&topckgen 135>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_M
+                 <&topckgen 44>, //CLK_TOP_AUDIO_H
+                 <&clk26m>;
+        clock-names = "aud_infra_clk",
+                      "mtkaif_26m_clk",
+                      "top_mux_audio",
+                      "top_mux_audio_int",
+                      "top_mainpll_d2_d4",
+                      "top_mux_aud_1",
+                      "top_apll1_ck",
+                      "top_mux_aud_2",
+                      "top_apll2_ck",
+                      "top_mux_aud_eng1",
+                      "top_apll1_d8",
+                      "top_mux_aud_eng2",
+                      "top_apll2_d8",
+                      "top_i2s0_m_sel",
+                      "top_i2s1_m_sel",
+                      "top_i2s2_m_sel",
+                      "top_i2s4_m_sel",
+                      "top_tdm_m_sel",
+                      "top_apll12_div0",
+                      "top_apll12_div1",
+                      "top_apll12_div2",
+                      "top_apll12_div4",
+                      "top_apll12_div_tdm",
+                      "top_mux_audio_h",
+                      "top_clk26m_clk";
+    };
+
+...
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (11 preceding siblings ...)
  2022-02-17 13:42 ` [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document Jiaxin Yu
@ 2022-02-17 13:42 ` Jiaxin Yu
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-02-17 13:42 ` [v2 15/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357 document Jiaxin Yu
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:42 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds support for mt8186 board with mt6366, da7219 and max98357.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../mt8186/mt8186-mt6366-da7219-max98357.c    | 910 ++++++++++++++++++
 1 file changed, 910 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c

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..6ba53b8d1e46
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
@@ -0,0 +1,910 @@
+// 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/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"
+
+#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 mt6366_codec_conf[] = {
+	{
+		.dlc = COMP_CODEC_CONF("mt6358-sound"),
+		.name_prefix = "Mt6366",
+	},
+};
+
+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, NULL, 0);
+	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 = 0, 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\n");
+
+	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\n");
+
+			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;
+}
+
+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);
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+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_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, NULL, 0);
+	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_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_info(rtd->dev, "failed to snd_soc_dapm_sync\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				      struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *channels = hw_param_interval(params,
+		SNDRV_PCM_HW_PARAM_CHANNELS);
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s channel to 2 channel */
+	channels->min = 2;
+	channels->max = 2;
+
+	/* fix BE i2s format to S32_LE, 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, SNDRV_PCM_FORMAT_S32_LE);
+
+	return 0;
+}
+
+static int mt8186_hdmi_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					   struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *channels = hw_param_interval(params,
+		SNDRV_PCM_HW_PARAM_CHANNELS);
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s channel to 2 channel */
+	channels->min = 2;
+	channels->max = 2;
+
+	/* fix BE i2s format to S24_LE, 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, SNDRV_PCM_FORMAT_S24_LE);
+
+	return 0;
+}
+
+/* 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_CODEC(DA7219_DEV_NAME,
+						   DA7219_CODEC_DAI)),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME,
+						   DA7219_CODEC_DAI)),
+		     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_CODEC(NULL, "i2s-hifi"),
+					COMP_CODEC("max98357a", "HiFi")),
+		     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()));
+#if IS_ENABLED(CONFIG_SND_SOC_MTK_BTCVSD)
+SND_SOC_DAILINK_DEFS(btcvsd,
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_PLATFORM("18050000.mtk-btcvsd-snd")));
+#endif
+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,
+		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,
+		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,
+		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,
+		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),
+	},
+	/* BTCVSD */
+#if IS_ENABLED(CONFIG_SND_SOC_MTK_BTCVSD)
+	{
+		.name = "BTCVSD",
+		.stream_name = "BTCVSD",
+		SND_SOC_DAILINK_REG(btcvsd),
+	},
+#endif
+	/* 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_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.dpcm_playback = 1,
+		.ignore_suspend = 1,
+		.init = mt8186_mt6366_hdmi_init,
+		.be_hw_params_fixup = mt8186_hdmi_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("SPK Out", NULL),
+	SND_SOC_DAPM_OUTPUT("HDMI Out"),
+};
+
+static const struct snd_soc_dapm_route
+mt8186_mt6366_da7219_max98357_routes[] = {
+	/* SPK */
+	{ "SPK Out", NULL, "Speaker" },
+	/* HDMI */
+	{ "HDMI Out", NULL, "TX" },
+};
+
+static const struct snd_kcontrol_new
+mt8186_mt6366_da7219_max98357_controls[] = {
+	SOC_DAPM_PIN_SWITCH("SPK Out"),
+	SOC_DAPM_PIN_SWITCH("HDMI Out"),
+};
+
+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 = mt6366_codec_conf,
+	.num_configs = ARRAY_SIZE(mt6366_codec_conf),
+};
+
+static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &mt8186_mt6366_da7219_max98357_soc_card;
+	struct snd_soc_dai_link *dai_link;
+	struct mt8186_mt6366_da7219_max98357_priv *priv;
+	struct device_node *platform_node, *hdmi_codec;
+	int ret, i;
+
+	dev_info(&pdev->dev, "%s(), ++\n", __func__);
+
+	card->dev = &pdev->dev;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_node = of_parse_phandle(pdev->dev.of_node,
+					 "mediatek,platform", 0);
+	if (!platform_node) {
+		dev_info(&pdev->dev,
+			 "Property 'platform' missing or invalid\n");
+		return -EINVAL;
+	}
+
+	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+				      "mediatek,hdmi-codec", 0);
+	if (!hdmi_codec) {
+		dev_info(&pdev->dev,
+			 "Property 'hdmi' missing or invalid\n");
+		return -EINVAL;
+	}
+
+	for_each_card_prelinks(card, i, dai_link) {
+		if (dai_link->platforms->name)
+			continue;
+
+		if (hdmi_codec && strcmp(dai_link->name, "I2S3") == 0) {
+			dai_link->codecs->of_node = hdmi_codec;
+			dai_link->ignore = 0;
+		}
+
+		dai_link->platforms->of_node = platform_node;
+	}
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	/* init gpio */
+	ret = mt8186_afe_gpio_init(&pdev->dev);
+	if (ret)
+		dev_info(&pdev->dev, "init gpio error\n");
+
+	dev_info(&pdev->dev, "%s(), devm_snd_soc_register_card\n", __func__);
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_info(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			 __func__, ret);
+	of_node_put(platform_node);
+	of_node_put(hdmi_codec);
+
+	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",},
+	{}
+};
+#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");
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 15/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357 document
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (12 preceding siblings ...)
  2022-02-17 13:42 ` [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357 Jiaxin Yu
@ 2022-02-17 13:42 ` Jiaxin Yu
  2022-02-17 13:42 ` [v2 16/17] ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and rt5682s Jiaxin Yu
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:42 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds document for mt8186 board with mt6366, da7219 and max98357.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../sound/mt8186-mt6366-da7219-max98357.yaml  | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml

diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml
new file mode 100644
index 000000000000..adef16a4630c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8186-mt6366-da7219-max98357.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8186 with MT6366, DA7219 and MAX98357 ASoC sound card driver
+
+maintainers:
+  - Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+description:
+  This binding describes the MT8186 sound card.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8186_mt6366_da7219_max98357_sound
+
+  mediatek,platform:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8186 ASoC platform.
+
+  mediatek,hdmi-codec:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of HDMI codec.
+
+additionalProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+
+examples:
+  - |
+
+    sound: mt8192-sound {
+        compatible = "mediatek,mt8186_mt6366_da7219_max98357_sound";
+        mediatek,platform = <&afe>;
+        mediatek,hdmi-codec = <&anx_bridge_dp>;
+        pinctrl-names = "aud_clk_mosi_off",
+                        "aud_clk_mosi_on";
+        pinctrl-0 = <&aud_clk_mosi_off>;
+        pinctrl-1 = <&aud_clk_mosi_on>;
+    };
+
+...
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 16/17] ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and rt5682s
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (13 preceding siblings ...)
  2022-02-17 13:42 ` [v2 15/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357 document Jiaxin Yu
@ 2022-02-17 13:42 ` Jiaxin Yu
  2022-02-17 13:42 ` [v2 17/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-rt1019-rt5682s document Jiaxin Yu
       [not found] ` <20220217134205.15400-13-jiaxin.yu@mediatek.com>
  16 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:42 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds support for mt8186 board with mt6366, rt1019 and rt5682s.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../mt8186/mt8186-mt6366-rt1019-rt5682s.c     | 894 ++++++++++++++++++
 1 file changed, 894 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c

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..82d8ed95f653
--- /dev/null
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
@@ -0,0 +1,894 @@
+// 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/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"
+
+#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 mt6366_codec_conf[] = {
+	{
+		.dlc = COMP_CODEC_CONF("mt6358-sound"),
+		.name_prefix = "Mt6366",
+	},
+};
+
+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, NULL, 0);
+	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_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, NULL, 0);
+	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_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_info(rtd->dev, "failed to snd_soc_dapm_sync\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				      struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *channels = hw_param_interval(params,
+		SNDRV_PCM_HW_PARAM_CHANNELS);
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s channel to 2 channel */
+	channels->min = 2;
+	channels->max = 2;
+
+	/* fix BE i2s format to S24_LE, 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, SNDRV_PCM_FORMAT_S24_LE);
+
+	return 0;
+}
+
+static int mt8186_hdmi_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					   struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *channels = hw_param_interval(params,
+		SNDRV_PCM_HW_PARAM_CHANNELS);
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s channel to 2 channel */
+	channels->min = 2;
+	channels->max = 2;
+
+	/* fix BE i2s format to S32_LE, 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, SNDRV_PCM_FORMAT_S32_LE);
+
+	return 0;
+}
+
+/* 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_CODEC(RT5682S_DEV0_NAME,
+						   RT5682S_CODEC_DAI)),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2s1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(RT5682S_DEV0_NAME,
+						   RT5682S_CODEC_DAI)),
+		     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_CODEC(NULL, "i2s-hifi"),
+					COMP_CODEC(RT1019_DEV0_NAME,
+						   RT1019_CODEC_DAI)),
+		     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()));
+#if IS_ENABLED(CONFIG_SND_SOC_MTK_BTCVSD)
+SND_SOC_DAILINK_DEFS(btcvsd,
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_PLATFORM("18050000.mtk-btcvsd-snd")));
+#endif
+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,
+		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,
+		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,
+		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,
+		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),
+	},
+	/* BTCVSD */
+#if IS_ENABLED(CONFIG_SND_SOC_MTK_BTCVSD)
+	{
+		.name = "BTCVSD",
+		.stream_name = "BTCVSD",
+		SND_SOC_DAILINK_REG(btcvsd),
+	},
+#endif
+	/* 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_hdmi_init,
+		.be_hw_params_fixup = mt8186_hdmi_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("SPK Out", NULL),
+	SND_SOC_DAPM_OUTPUT("HDMI Out"),
+};
+
+static const struct snd_soc_dapm_route
+mt8186_mt6366_rt1019_rt5682s_routes[] = {
+	/* SPK */
+	{ "SPK Out", NULL, "Speaker" },
+	/* HDMI */
+	{ "HDMI Out", NULL, "TX" },
+};
+
+static const struct snd_kcontrol_new
+mt8186_mt6366_rt1019_rt5682s_controls[] = {
+	SOC_DAPM_PIN_SWITCH("SPK Out"),
+	SOC_DAPM_PIN_SWITCH("HDMI Out"),
+};
+
+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 = mt6366_codec_conf,
+	.num_configs = ARRAY_SIZE(mt6366_codec_conf),
+};
+
+static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &mt8186_mt6366_rt1019_rt5682s_soc_card;
+	struct snd_soc_dai_link *dai_link;
+	struct mt8186_mt6366_rt1019_rt5682s_priv *priv;
+	struct device_node *platform_node, *hdmi_codec;
+	int ret, i;
+
+	dev_info(&pdev->dev, "%s(), ++\n", __func__);
+
+	card->dev = &pdev->dev;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_node = of_parse_phandle(pdev->dev.of_node,
+					 "mediatek,platform", 0);
+	if (!platform_node) {
+		dev_info(&pdev->dev,
+			 "Property 'platform' missing or invalid\n");
+		return -EINVAL;
+	}
+
+	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+				      "mediatek,hdmi-codec", 0);
+	if (!hdmi_codec) {
+		dev_info(&pdev->dev,
+			 "Property 'hdmi' missing or invalid\n");
+		return -EINVAL;
+	}
+
+	for_each_card_prelinks(card, i, dai_link) {
+		if (dai_link->platforms->name)
+			continue;
+
+		if (hdmi_codec && strcmp(dai_link->name, "I2S3") == 0) {
+			dai_link->codecs->of_node = hdmi_codec;
+			dai_link->ignore = 0;
+		}
+
+		dai_link->platforms->of_node = platform_node;
+	}
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	/* init gpio */
+	ret = mt8186_afe_gpio_init(&pdev->dev);
+	if (ret)
+		dev_info(&pdev->dev, "init gpio error\n");
+
+	dev_info(&pdev->dev, "%s(), devm_snd_soc_register_card\n", __func__);
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_info(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			 __func__, ret);
+	of_node_put(platform_node);
+	of_node_put(hdmi_codec);
+
+	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",},
+	{}
+};
+#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");
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* [v2 17/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-rt1019-rt5682s document
  2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
                   ` (14 preceding siblings ...)
  2022-02-17 13:42 ` [v2 16/17] ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and rt5682s Jiaxin Yu
@ 2022-02-17 13:42 ` Jiaxin Yu
       [not found] ` <20220217134205.15400-13-jiaxin.yu@mediatek.com>
  16 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-02-17 13:42 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, Jiaxin Yu

This patch adds document for mt8186 board with mt6366, rt1019 and rt5682s.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
---
 .../sound/mt8186-mt6366-rt1019-rt5682s.yaml   | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml

diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
new file mode 100644
index 000000000000..9280a26038f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8186-mt6366-rt1019-rt5682s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8186 with MT6366, RT1019 and RT5682S ASoC sound card driver
+
+maintainers:
+  - Jiaxin Yu <jiaxin.yu@mediatek.com>
+
+description:
+  This binding describes the MT8186 sound card.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8186_mt6366_rt1019_rt5682s_sound
+
+  mediatek,platform:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8186 ASoC platform.
+
+  mediatek,hdmi-codec:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of HDMI codec.
+
+additionalProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+
+examples:
+  - |
+
+    sound: mt8186-sound {
+        compatible = "mediatek,mt8186_mt6366_rt1019_rt5682s_sound";
+        mediatek,platform = <&afe>;
+        mediatek,hdmi-codec = <&it6505dptx>;
+        pinctrl-names = "aud_clk_mosi_off",
+                        "aud_clk_mosi_on";
+        pinctrl-0 = <&aud_clk_mosi_off>;
+        pinctrl-1 = <&aud_clk_mosi_on>;
+    };
+
+...
-- 
2.18.0


_______________________________________________
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] 44+ messages in thread

* Re: [v2 01/17] ASoC: mediatek: mt6366: add codec driver
  2022-02-17 13:41 ` [v2 01/17] ASoC: mediatek: mt6366: add codec driver Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-05  4:24     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> Mt6366 is a new version of mt6358, and they are same about audio part.
> So we can reuse the driver of mt6358.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>

Hello Jiaxin,
I'm sorry but this commit makes very little sense.

If you want to advertise MT6366 support, please write a note and/or
a new compatible string inside of the mt6358 driver (and dt-bindings),
then, please drop this commit.


> ---
>   sound/soc/codecs/Kconfig  | 8 ++++++++
>   sound/soc/codecs/Makefile | 1 +
>   2 files changed, 9 insertions(+)
> 
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 8fa24783ce01..6631094678f5 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS
>   	imply SND_SOC_MT6351
>   	imply SND_SOC_MT6358
>   	imply SND_SOC_MT6359
> +	imply SND_SOC_MT6366
>   	imply SND_SOC_MT6660
>   	imply SND_SOC_NAU8315
>   	imply SND_SOC_NAU8540
> @@ -1888,6 +1889,13 @@ config SND_SOC_MT6359_ACCDET
>   	  for ASoC codec soc-jack detection mechanism.
>   	  Select N if you don't have jack on board.
>   
> +config SND_SOC_MT6366
> +	tristate "MediaTek MT6366 Codec"
> +	depends on MTK_PMIC_WRAP
> +	help
> +	  Enable support for the platform which uses MT6366 as
> +	  external codec device.
> +
>   config SND_SOC_MT6660
>   	tristate "Mediatek MT6660 Speaker Amplifier"
>   	depends on I2C
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 42d00aa4ee46..1279684feaf0 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -465,6 +465,7 @@ obj-$(CONFIG_SND_SOC_MT6351)	+= snd-soc-mt6351.o
>   obj-$(CONFIG_SND_SOC_MT6358)	+= snd-soc-mt6358.o
>   obj-$(CONFIG_SND_SOC_MT6359)	+= snd-soc-mt6359.o
>   obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o
> +obj-$(CONFIG_SND_SOC_MT6366)	+= snd-soc-mt6358.o
>   obj-$(CONFIG_SND_SOC_MT6660)	+= snd-soc-mt6660.o
>   obj-$(CONFIG_SND_SOC_NAU8315)   += snd-soc-nau8315.o
>   obj-$(CONFIG_SND_SOC_NAU8540)   += snd-soc-nau8540.o



_______________________________________________
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] 44+ messages in thread

* Re: [v2 04/17] ASoC: mediatek: mt8186: support hostless in platform driver
  2022-02-17 13:41 ` [v2 04/17] ASoC: mediatek: mt8186: support hostless " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 hostless dai driver.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   .../soc/mediatek/mt8186/mt8186-dai-hostless.c | 295 ++++++++++++++++++
>   1 file changed, 295 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
> new file mode 100644
> index 000000000000..37460a3acc93
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c
> @@ -0,0 +1,295 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI Hostless Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include "mt8186-afe-common.h"
> +
> +static const struct snd_pcm_hardware mt8186_hostless_hardware = {
> +	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
> +		 SNDRV_PCM_INFO_MMAP_VALID),
> +	.period_bytes_min = 256,
> +	.period_bytes_max = 4 * 48 * 1024,
> +	.periods_min = 2,
> +	.periods_max = 256,
> +	.buffer_bytes_max = 4 * 48 * 1024,
> +	.fifo_size = 0,
> +};
> +
> +/* dai component */
> +static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = {
> +	/* Hostless ADDA Loopback */
> +	{"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
> +	{"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
> +	{"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
> +	{"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
> +	{"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
> +	{"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
> +	{"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
> +	{"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
> +	{"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
> +	{"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
> +	{"Hostless LPBK UL", NULL, "ADDA_UL_Mux"},
> +
> +	/* Hostelss FM */
> +	/* connsys_i2s to hw gain 1*/
> +	{"Hostless FM UL", NULL, "Connsys I2S"},
> +
> +	{"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"},
> +	{"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"},
> +	/* hw gain to adda dl */
> +	{"Hostless FM UL", NULL, "HW Gain 1 Out"},
> +
> +	{"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
> +	{"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
> +	/* hw gain to i2s3 */
> +	{"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
> +	{"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
> +	/* hw gain to i2s1 */
> +	{"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
> +	{"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
> +
> +	/* Hostless_SRC */
> +	{"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
> +	{"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
> +	{"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
> +	{"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
> +	{"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
> +	{"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
> +	{"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"},
> +
> +	/* Hostless_SRC_bargein */
> +	{"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"},
> +	{"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"},
> +	{"Hostless_SRC_Bargein_UL", NULL, "I2S0"},
> +
> +	/* Hostless AAudio */
> +	{"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"},
> +	{"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"},
> +	{"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"},
> +	{"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"},
> +};
> +
> +/* dai ops */
> +static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream,
> +				    struct snd_soc_dai *dai)
> +{
> +	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	int ret;
> +
> +	snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware);
> +
> +	ret = snd_pcm_hw_constraint_integer(runtime,
> +					    SNDRV_PCM_HW_PARAM_PERIODS);
> +	if (ret < 0)
> +		dev_info(afe->dev, "snd_pcm_hw_constraint_integer failed\n");

	if (ret < 0) {
		dev_err(afe->dev, "setting constraints failed: %d\n", ret);
		return ret;
	}

	return 0;


Thanks,
Angelo



_______________________________________________
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] 44+ messages in thread

* Re: [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver
  2022-02-17 13:41 ` [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-05 10:49     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 adda dai driver
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 891 ++++++++++++++++++++
>   1 file changed, 891 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> new file mode 100644
> index 000000000000..6d7dd1533da0
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> @@ -0,0 +1,891 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI ADDA Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/regmap.h>
> +#include <linux/delay.h>
> +#include "mt8186-afe-clk.h"
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-gpio.h"
> +#include "mt8186-interconnection.h"
> +

..snip..


> +
> +static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
> +				     struct snd_kcontrol *kcontrol,
> +				     int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int delay_data;
> +	int delay_cycle;
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) {
> +			/* set protocol 2 */
> +			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
> +				     0x00010000);

No leading zeros, please (also, it fits in one line):
			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000);

> +			/* mtkaif_rxif_clkinv_adc inverse */
> +			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
> +					   MTKAIF_RXIF_CLKINV_ADC_MASK_SFT,
> +					   0x1 << MTKAIF_RXIF_CLKINV_ADC_SFT);

Please use the BIT() macro:
					   BIT(MTKAIF_RXIF_CLKINV_ADC_SFT)

> +
> +			if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0) {
> +				if (afe_priv->mtkaif_chosen_phase[0] < 0 &&
> +				    afe_priv->mtkaif_chosen_phase[1] < 0) {
> +					dev_err(afe->dev,
> +						"%s(), calib fail mtkaif_chosen_phase[0/1]:%d/%d\n",
> +						__func__,
> +						afe_priv->mtkaif_chosen_phase[0],
> +						afe_priv->mtkaif_chosen_phase[1]);
> +					break;
> +				}
> +
> +				if (afe_priv->mtkaif_chosen_phase[0] < 0 ||
> +				    afe_priv->mtkaif_chosen_phase[1] < 0) {
> +					dev_err(afe->dev,
> +						"%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n",
> +						__func__,
> +						afe_priv->mtkaif_chosen_phase[0],
> +						afe_priv->mtkaif_chosen_phase[1]);
> +					break;
> +				}
> +			}
> +
> +			/* set delay for ch12 */
> +			if (afe_priv->mtkaif_phase_cycle[0] >=
> +			    afe_priv->mtkaif_phase_cycle[1]) {
> +				delay_data = DELAY_DATA_MISO1;
> +				delay_cycle = afe_priv->mtkaif_phase_cycle[0] -
> +					      afe_priv->mtkaif_phase_cycle[1];
> +			} else {
> +				delay_data = DELAY_DATA_MISO2;
> +				delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
> +					      afe_priv->mtkaif_phase_cycle[0];
> +			}
> +
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_MTKAIF_RX_CFG2,
> +					   MTKAIF_RXIF_DELAY_DATA_MASK_SFT,
> +					   delay_data <<
> +					   MTKAIF_RXIF_DELAY_DATA_SFT);
> +
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_MTKAIF_RX_CFG2,
> +					   MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,
> +					   delay_cycle <<
> +					   MTKAIF_RXIF_DELAY_CYCLE_SFT);
> +
> +		} else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) {
> +			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
> +				     0x00010000);

No leading zeroes, please.

> +		} else {
> +			regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);

0x0 -> 0

> +		}
> +
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
> +			     struct snd_kcontrol *kcontrol,
> +			     int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +
> +	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 0);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
> +		usleep_range(125, 135);
> +		mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 0);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt8186_adda_dmic_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->mtkaif_dmic;
> +
> +	return 0;
> +}
> +
> +static int mt8186_adda_dmic_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;
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	int dmic_on;
> +
> +	if (ucontrol->value.enumerated.item[0] >= e->items)
> +		return -EINVAL;
> +
> +	dmic_on = ucontrol->value.integer.value[0];
> +
> +	dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
> +		 __func__, kcontrol->id.name, dmic_on);

Shouldn't this be a dev_dbg() instead?

> +
> +	if (afe_priv->mtkaif_dmic == dmic_on)
> +		return 0;
> +
> +	afe_priv->mtkaif_dmic = dmic_on;
> +
> +	return 1;
> +}
> +

...snip...

> +
> +#define HIRES_THRESHOLD 48000
> +static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source,
> +				     struct snd_soc_dapm_widget *sink)
> +{
> +	struct snd_soc_dapm_widget *w = source;
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_adda_priv *adda_priv;
> +
> +	adda_priv = get_adda_priv_by_name(afe, w->name);
> +
> +	if (!adda_priv) {
> +		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);

dev_err()

> +		return 0;
> +	}
> +
> +	return (adda_priv->dl_rate > HIRES_THRESHOLD) ? 1 : 0;
> +}
> +
> +static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source,
> +				     struct snd_soc_dapm_widget *sink)
> +{
> +	struct snd_soc_dapm_widget *w = source;
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_adda_priv *adda_priv;
> +
> +	adda_priv = get_adda_priv_by_name(afe, w->name);
> +
> +	if (!adda_priv) {
> +		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);

dev_err()

> +		return 0;
> +	}
> +
> +	return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0;
> +}
> +

..snip..

> +};
> +
> +/* dai ops */
> +static int mtk_dai_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);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	unsigned int rate = params_rate(params);
> +	int id = dai->id;
> +	struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id];
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> +		 __func__,
> +		 id,
> +		 substream->stream,
> +		 rate);
> +
> +	if (!adda_priv) {
> +		dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		unsigned int dl_src2_con0 = 0;
> +		unsigned int dl_src2_con1 = 0;

This initialization is redundant: you're never using these variables
before initializing them later, so initializing them to zero is not
needed here.

> +
> +		adda_priv->dl_rate = rate;
> +
> +		/* set sampling rate */
> +		dl_src2_con0 = adda_dl_rate_transform(afe, rate) <<
> +			       DL_2_INPUT_MODE_CTL_SFT;
> +
> +		/* set output mode, UP_SAMPLING_RATE_X8 */
> +		dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT);
> +
> +		/* turn off mute function */
> +		dl_src2_con0 |= (0x01 << DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);

BIT() macro, please

> +		dl_src2_con0 |= (0x01 << DL_2_MUTE_CH1_OFF_CTL_PRE_SFT);
> +
> +		/* set voice input data if input sample rate is 8k or 16k */
> +		if (rate == 8000 || rate == 16000)
> +			dl_src2_con0 |= 0x01 << DL_2_VOICE_MODE_CTL_PRE_SFT;
> +
> +		/* SA suggest apply -0.3db to audio/speech path */
> +		dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL <<
> +			       DL_2_GAIN_CTL_PRE_SFT;
> +
> +		/* turn on down-link gain */
> +		dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT);
> +
> +		if (id == MT8186_DAI_ADDA) {
> +			/* clean predistortion */
> +			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, dl_src2_con0);
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);
> +
> +			/* set sdm gain */
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
> +					   ATTGAIN_CTL_MASK_SFT,
> +					   AUDIO_SDM_LEVEL_NORMAL <<
> +					   ATTGAIN_CTL_SFT);
> +
> +			/* Use new 2nd sdm */
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_DL_SDM_DITHER_CON,
> +					   AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT,
> +					   0x1 << AFE_DL_SDM_DITHER_64TAP_EN_SFT);

BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)

> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_DL_SDM_AUTO_RESET_CON,
> +					   AFE_DL_USE_NEW_2ND_SDM_MASK_SFT,
> +					   0x1 << AFE_DL_USE_NEW_2ND_SDM_SFT);

BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)

> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
> +					   USE_3RD_SDM_MASK_SFT,
> +					   AUDIO_SDM_2ND << USE_3RD_SDM_SFT);
> +
> +			/* sdm auto reset */
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_DL_SDM_AUTO_RESET_CON,
> +				     SDM_AUTO_RESET_THRESHOLD);
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_DL_SDM_AUTO_RESET_CON,
> +					   SDM_AUTO_RESET_TEST_ON_MASK_SFT,
> +					   0x1 << SDM_AUTO_RESET_TEST_ON_SFT);

BIT(SDM_AUTO_RESET_TEST_ON_SFT)

> +		}
> +	} else {
> +		unsigned int voice_mode = 0;

what about...
		unsigned int ul_src_con0 = 0; /* default value */
		unsigned int voice_mode =  adda_ul_rate_transform(afe, rate);

> +		unsigned int ul_src_con0 = 0;	/* default value */
> +
> +		adda_priv->ul_rate = rate;
> +
> +		voice_mode = adda_ul_rate_transform(afe, rate);
> +
> +		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
> +
> +		/* enable iir */
> +		ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
> +			       UL_IIR_ON_TMP_CTL_MASK_SFT;
> +		ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
> +			       UL_IIRMODE_CTL_MASK_SFT;
> +		switch (id) {
> +		case MT8186_DAI_ADDA:
> +		case MT8186_DAI_AP_DMIC:
> +			/* 35Hz @ 48k */
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_IIR_COEF_02_01, 0x00000000);

Please drop leading zeroes:

regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0);

> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);

... and also please write hex in lower-case:

regmap_write(afe->regmap,
	     AFE_ADDA_IIR_COEF_04_03, 0x03fb8);

> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_IIR_COEF_06_05, 0x3FB80000);
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_IIR_COEF_08_07, 0x3FB80000);
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_IIR_COEF_10_09, 0x0000C048);
> +
> +			regmap_write(afe->regmap,
> +				     AFE_ADDA_UL_SRC_CON0, ul_src_con0);
> +
> +			/* Using Internal ADC */
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_TOP_CON0,
> +					   0x1 << 0,
> +					   0x0 << 0);

Please use the BIT() macro:

regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0);

P.S.: 87 columns is ok

> +
> +			/* mtkaif_rxif_data_mode = 0, amic */
> +			regmap_update_bits(afe->regmap,
> +					   AFE_ADDA_MTKAIF_RX_CFG0,
> +					   0x1 << 0,
> +					   0x0 << 0);

same here.

> +			break;
> +		default:
> +			break;
> +		}
> +
> +		/* ap dmic */
> +		switch (id) {
> +		case MT8186_DAI_AP_DMIC:
> +			mtk_adda_ul_src_dmic(afe, id);
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +}
> +

Regards,
Angelo


_______________________________________________
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] 44+ messages in thread

* Re: [v2 05/17] ASoC: mediatek: mt8186: support hw gain in platform driver
  2022-02-17 13:41 ` [v2 05/17] ASoC: mediatek: mt8186: support hw gain " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This path adds mt8186 hw gain dai driver.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   .../soc/mediatek/mt8186/mt8186-dai-hw-gain.c  | 245 ++++++++++++++++++
>   1 file changed, 245 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
> new file mode 100644
> index 000000000000..796878989727
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c
> @@ -0,0 +1,245 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI HW Gain Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/regmap.h>
> +#include "mt8186-afe-common.h"
> +#include "mt8186-interconnection.h"
> +
> +#define HW_GAIN_1_EN_W_NAME "HW GAIN 1 Enable"
> +#define HW_GAIN_2_EN_W_NAME "HW GAIN 2 Enable"
> +
> +/* dai component */
> +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = {
> +	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13_1,
> +				    I_CONNSYS_I2S_CH1, 1, 0),
> +};
> +
> +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = {
> +	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14_1,
> +				    I_CONNSYS_I2S_CH2, 1, 0),
> +};
> +
> +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch1_mix[] = {
> +	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN15,
> +				    I_ADDA_UL_CH1, 1, 0),
> +};
> +
> +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch2_mix[] = {
> +	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN16,
> +				    I_ADDA_UL_CH2, 1, 0),
> +};
> +
> +static int mtk_hw_gain_event(struct snd_soc_dapm_widget *w,
> +			     struct snd_kcontrol *kcontrol,
> +			     int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	unsigned int gain_cur;
> +	unsigned int gain_con1;
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		if (strcmp(w->name, HW_GAIN_1_EN_W_NAME) == 0) {
> +			gain_cur = AFE_GAIN1_CUR;
> +			gain_con1 = AFE_GAIN1_CON1;
> +		} else {
> +			gain_cur = AFE_GAIN2_CUR;
> +			gain_con1 = AFE_GAIN2_CON1;
> +		}
> +
> +		/* let hw gain ramp up, set cur gain to 0 */
> +		regmap_update_bits(afe->regmap,
> +				   gain_cur,
> +				   AFE_GAIN1_CUR_MASK_SFT,
> +				   0);

This fits in one line (86 columns is ok)

> +
> +		/* set target gain to 0 */
> +		regmap_update_bits(afe->regmap,
> +				   gain_con1,
> +				   GAIN1_TARGET_MASK_SFT,
> +				   0);

Same here.

> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct snd_soc_dapm_widget mtk_dai_hw_gain_widgets[] = {
> +	/* inter-connections */
> +	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0,
> +			   mtk_hw_gain1_in_ch1_mix,
> +			   ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)),
> +	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0,
> +			   mtk_hw_gain1_in_ch2_mix,
> +			   ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)),
> +	SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH1", SND_SOC_NOPM, 0, 0,
> +			   mtk_hw_gain2_in_ch1_mix,
> +			   ARRAY_SIZE(mtk_hw_gain2_in_ch1_mix)),
> +	SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH2", SND_SOC_NOPM, 0, 0,
> +			   mtk_hw_gain2_in_ch2_mix,
> +			   ARRAY_SIZE(mtk_hw_gain2_in_ch2_mix)),
> +
> +	SND_SOC_DAPM_SUPPLY(HW_GAIN_1_EN_W_NAME,
> +			    AFE_GAIN1_CON0, GAIN1_ON_SFT, 0,
> +			    mtk_hw_gain_event,
> +			    SND_SOC_DAPM_PRE_PMU),
> +
> +	SND_SOC_DAPM_SUPPLY(HW_GAIN_2_EN_W_NAME,
> +			    AFE_GAIN2_CON0, GAIN2_ON_SFT, 0,
> +			    mtk_hw_gain_event,
> +			    SND_SOC_DAPM_PRE_PMU),
> +
> +	SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"),
> +	SND_SOC_DAPM_INPUT("HW Gain 2 Out Endpoint"),
> +	SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"),
> +};
> +
> +static const struct snd_soc_dapm_route mtk_dai_hw_gain_routes[] = {
> +	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"},
> +	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"},
> +	{"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH1"},
> +	{"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH2"},
> +
> +	{"HW Gain 1 In", NULL, HW_GAIN_1_EN_W_NAME},
> +	{"HW Gain 1 Out", NULL, HW_GAIN_1_EN_W_NAME},
> +	{"HW Gain 2 In", NULL, HW_GAIN_2_EN_W_NAME},
> +	{"HW Gain 2 Out", NULL, HW_GAIN_2_EN_W_NAME},
> +
> +	{"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"},
> +	{"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"},
> +	{"HW Gain 2 Out", NULL, "HW Gain 2 Out Endpoint"},
> +};
> +
> +static const struct snd_kcontrol_new mtk_hw_gain_controls[] = {
> +	SOC_SINGLE("HW Gain 1 Volume", AFE_GAIN1_CON1,
> +		   GAIN1_TARGET_SFT, GAIN1_TARGET_MASK, 0),
> +	SOC_SINGLE("HW Gain 2 Volume", AFE_GAIN2_CON1,
> +		   GAIN2_TARGET_SFT, GAIN2_TARGET_MASK, 0),
> +};
> +
> +/* dai ops */
> +static int mtk_dai_gain_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 rate = params_rate(params);
> +	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id);
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> +		 __func__,
> +		 dai->id,
> +		 substream->stream,
> +		 rate);

This should be:
	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",

		 __func__, dai->id, substream->stream, rate);


_______________________________________________
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] 44+ messages in thread

* Re: [v2 07/17] ASoC: mediatek: mt8186: support pcm in platform driver
  2022-02-17 13:41 ` [v2 07/17] ASoC: mediatek: mt8186: support pcm " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-05 11:12     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 pcm dai driver.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-dai-pcm.c | 432 +++++++++++++++++++++
>   1 file changed, 432 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> new file mode 100644
> index 000000000000..73b3f720ed35
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> @@ -0,0 +1,432 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI I2S Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/regmap.h>
> +#include <sound/pcm_params.h>
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-gpio.h"
> +#include "mt8186-interconnection.h"
> +
> +struct mtk_afe_pcm_priv {
> +	unsigned int id;
> +	unsigned int fmt;
> +	unsigned int bck_invert;
> +	unsigned int lck_invert;
> +};
> +
> +enum AUD_TX_LCH_RPT {

lowercase enumeration names please...

enum aud_tx_lch_rpt {
	AUD_TX....BLAH
};

> +	AUD_TX_LCH_RPT_NO_REPEAT = 0,
> +	AUD_TX_LCH_RPT_REPEAT = 1
> +};
> +
> +enum AUD_VBT_16K_MODE {
> +	AUD_VBT_16K_MODE_DISABLE = 0,
> +	AUD_VBT_16K_MODE_ENABLE = 1
> +};
> +
> +enum AUD_EXT_MODEM {
> +	AUD_EXT_MODEM_SELECT_INTERNAL = 0,
> +	AUD_EXT_MODEM_SELECT_EXTERNAL = 1
> +};
> +
> +enum AUD_PCM_SYNC_TYPE {
> +	/* bck sync length = 1 */
> +	AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
> +	/* bck sync length = PCM_INTF_CON1[9:13] */
> +	AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
> +};
> +
> +enum AUD_BT_MODE {
> +	AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
> +	AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
> +};
> +
> +enum AUD_PCM_AFIFO_SRC {
> +	/* slave mode & external modem uses different crystal */
> +	AUD_PCM_AFIFO_ASRC = 0,
> +	/* slave mode & external modem uses the same crystal */
> +	AUD_PCM_AFIFO_AFIFO = 1
> +};
> +
> +enum AUD_PCM_CLOCK_SOURCE {
> +	AUD_PCM_CLOCK_MASTER_MODE = 0,
> +	AUD_PCM_CLOCK_SLAVE_MODE = 1
> +};
> +
> +enum AUD_PCM_WLEN {
> +	AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
> +	AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
> +};
> +
> +enum AUD_PCM_24BIT {
> +	AUD_PCM_24BIT_PCM_16_BITS = 0,
> +	AUD_PCM_24BIT_PCM_24_BITS = 1
> +};
> +
> +enum AUD_PCM_MODE {
> +	AUD_PCM_MODE_PCM_MODE_8K = 0,
> +	AUD_PCM_MODE_PCM_MODE_16K = 1,
> +	AUD_PCM_MODE_PCM_MODE_32K = 2,
> +	AUD_PCM_MODE_PCM_MODE_48K = 3,
> +};
> +
> +enum AUD_PCM_FMT {
> +	AUD_PCM_FMT_I2S = 0,
> +	AUD_PCM_FMT_EIAJ = 1,
> +	AUD_PCM_FMT_PCM_MODE_A = 2,
> +	AUD_PCM_FMT_PCM_MODE_B = 3
> +};
> +
> +enum AUD_BCLK_OUT_INV {
> +	AUD_BCLK_OUT_INV_NO_INVERSE = 0,
> +	AUD_BCLK_OUT_INV_INVERSE = 1
> +};
> +
> +enum AUD_LRCLK_OUT_INV {
> +	AUD_LRCLK_OUT_INV_NO_INVERSE = 0,
> +	AUD_LRCLK_OUT_INV_INVERSE = 1
> +};
> +
> +enum AUD_PCM_EN {
> +	AUD_PCM_EN_DISABLE = 0,
> +	AUD_PCM_EN_ENABLE = 1
> +};
> +

..snip..

> +
> +/* dai ops */
> +static int mtk_dai_pcm_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);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int pcm_id = dai->id;
> +	struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id];
> +	unsigned int rate = params_rate(params);
> +	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id);
> +	snd_pcm_format_t format = params_format(params);
> +	unsigned int data_width =
> +		snd_pcm_format_width(format);
> +	unsigned int wlen_width =
> +		snd_pcm_format_physical_width(format);
> +	unsigned int pcm_con = 0;
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n",
> +		 __func__,
> +		 dai->id,
> +		 substream->stream,
> +		 dai->playback_widget->active,
> +		 dai->capture_widget->active);
> +	dev_info(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n",
> +		 __func__,
> +		 rate,
> +		 rate_reg,
> +		 data_width,
> +		 wlen_width);

dev_dbg() - also, you don't need one line per variable.

> +
> +	if (dai->playback_widget->active || dai->capture_widget->active)
> +		return 0;
> +
> +	switch (dai->id) {
> +	case MT8186_DAI_PCM:
> +		pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
> +		pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
> +		pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT;
> +		pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
> +		pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
> +		pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
> +		pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT;
> +		pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
> +
> +		/* sampling rate */
> +		pcm_con |= rate_reg << PCM_MODE_SFT;
> +
> +		/* format */
> +		pcm_con |= pcm_priv->fmt << PCM_FMT_SFT;
> +
> +		/* 24bit data width */
> +		if (data_width > 16)
> +			pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT;
> +		else
> +			pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT;
> +
> +		/* wlen width*/
> +		if (wlen_width > 16)
> +			pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT;
> +		else
> +			pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT;
> +
> +		/* clock invert */
> +		pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT;
> +		pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT;
> +
> +		regmap_update_bits(afe->regmap, PCM_INTF_CON1,
> +				   0xfffffffe, pcm_con);

Fits in one line.

> +		break;
> +	default:
> +		dev_info(afe->dev, "%s(), id %d not support\n",
> +			 __func__, dai->id);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
> +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +

_______________________________________________
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] 44+ messages in thread

* Re: [v2 06/17] ASoC: mediatek: mt8186: support i2s in platform driver
  2022-02-17 13:41 ` [v2 06/17] ASoC: mediatek: mt8186: support i2s " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-05 11:07     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 i2s dai driver
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-dai-i2s.c | 1371 ++++++++++++++++++++
>   1 file changed, 1371 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> new file mode 100644
> index 000000000000..d6db5f6a7315
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> @@ -0,0 +1,1371 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI I2S Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/bitops.h>
> +#include <linux/regmap.h>
> +#include <sound/pcm_params.h>
> +#include "mt8186-afe-clk.h"
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-gpio.h"
> +#include "mt8186-interconnection.h"
> +
> +enum {
> +	I2S_FMT_EIAJ = 0,
> +	I2S_FMT_I2S = 1,
> +};
> +
> +enum {
> +	I2S_WLEN_16_BIT = 0,
> +	I2S_WLEN_32_BIT = 1,
> +};
> +
> +enum {
> +	I2S_HD_NORMAL = 0,
> +	I2S_HD_LOW_JITTER = 1,
> +};
> +
> +enum {
> +	I2S1_SEL_O28_O29 = 0,
> +	I2S1_SEL_O03_O04 = 1,
> +};
> +
> +enum {
> +	I2S_IN_PAD_CONNSYS = 0,
> +	I2S_IN_PAD_IO_MUX = 1,
> +};
> +
> +struct mtk_afe_i2s_priv {
> +	int id;
> +	int rate; /* for determine which apll to use */
> +	int low_jitter_en;
> +	int master; /* only i2s0 has slave mode*/
> +
> +	const char *share_property_name;
> +	int share_i2s_id;
> +
> +	int mclk_id;
> +	int mclk_rate;
> +	int mclk_apll;
> +};
> +
> +static unsigned int get_i2s_wlen(snd_pcm_format_t format)
> +{
> +	return snd_pcm_format_physical_width(format) <= 16 ?
> +	       I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;
> +}
> +
> +#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"
> +#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"
> +#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"
> +#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"
> +#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux"
> +
> +#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"
> +#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"
> +#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"
> +#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"
> +
> +#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"
> +#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"
> +#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"
> +#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"
> +
> +static int get_i2s_id_by_name(struct mtk_base_afe *afe,
> +			      const char *name)
> +{
> +	if (strncmp(name, "I2S0", 4) == 0)
> +		return MT8186_DAI_I2S_0;
> +	else if (strncmp(name, "I2S1", 4) == 0)
> +		return MT8186_DAI_I2S_1;
> +	else if (strncmp(name, "I2S2", 4) == 0)
> +		return MT8186_DAI_I2S_2;
> +	else if (strncmp(name, "I2S3", 4) == 0)
> +		return MT8186_DAI_I2S_3;

This is just

	return -EINVAL;

(without the "else").

> +	else
> +		return -EINVAL;
> +}
> +
> +static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,
> +						     const char *name)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int dai_id = get_i2s_id_by_name(afe, name);
> +
> +	if (dai_id < 0)
> +		return NULL;
> +
> +	return afe_priv->dai_priv[dai_id];
> +}
> +
> +/* low jitter control */
> +static const char * const mt8186_i2s_hd_str[] = {
> +	"Normal", "Low_Jitter"
> +};
> +
> +static const struct soc_enum mt8186_i2s_enum[] = {
> +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str),
> +			    mt8186_i2s_hd_str),
> +};
> +
> +/* clock source control */
> +static const char * const mt8186_i2s_src_str[] = {
> +	"Master", "Slave"
> +};
> +
> +static const struct soc_enum mt8186_i2s_src_enum[] = {
> +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_src_str),
> +			    mt8186_i2s_src_str),
> +};
> +
> +static int mt8186_i2s_hd_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 mtk_afe_i2s_priv *i2s_priv;
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
> +
> +	return 0;
> +}
> +
> +static int mt8186_i2s_hd_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 mtk_afe_i2s_priv *i2s_priv;
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	int hd_en;
> +
> +	if (ucontrol->value.enumerated.item[0] >= e->items)
> +		return -EINVAL;
> +
> +	hd_en = ucontrol->value.integer.value[0];
> +
> +	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
> +		 __func__, kcontrol->id.name, hd_en);

dev_dbg()

> +
> +	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	i2s_priv->low_jitter_en = hd_en;
> +
> +	return 0;
> +}
> +
> +static int mt8186_i2s_src_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 mtk_afe_i2s_priv *i2s_priv;
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	ucontrol->value.integer.value[0] = i2s_priv->master;
> +
> +	return 0;
> +}
> +
> +static int mt8186_i2s_src_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 mtk_afe_i2s_priv *i2s_priv;
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	int clk_src;
> +	int dai_id;
> +
> +	if (ucontrol->value.enumerated.item[0] >= e->items)
> +		return -EINVAL;
> +
> +	clk_src = ucontrol->value.integer.value[0];
> +
> +	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
> +		 __func__, kcontrol->id.name, clk_src);

dev_dbg()

> +
> +	i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
> +	dai_id = get_i2s_id_by_name(afe, kcontrol->id.name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	switch (dai_id) {
> +	case MT8186_DAI_I2S_0:
> +		regmap_update_bits(afe->regmap, AFE_I2S_CON,
> +				   I2S_SRC_MASK_SFT,
> +				   clk_src << I2S_SRC_SFT);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	i2s_priv->master = clk_src;
> +
> +	return 0;
> +}
> +

..snip..

> +
> +static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,
> +			    struct snd_kcontrol *kcontrol,
> +			    int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_i2s_priv *i2s_priv;
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, w->name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_apll_event(struct snd_soc_dapm_widget *w,
> +			  struct snd_kcontrol *kcontrol,
> +			  int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		if (strcmp(w->name, APLL1_W_NAME) == 0)
> +			mt8186_apll1_enable(afe);
> +		else
> +			mt8186_apll2_enable(afe);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		if (strcmp(w->name, APLL1_W_NAME) == 0)
> +			mt8186_apll1_disable(afe);
> +		else
> +			mt8186_apll2_disable(afe);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
> +			     struct snd_kcontrol *kcontrol,
> +			     int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_i2s_priv *i2s_priv;
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, w->name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		i2s_priv->mclk_rate = 0;
> +		mt8186_mck_disable(afe, i2s_priv->mclk_id);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +

..snip..

> +
> +static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
> +				     struct snd_soc_dapm_widget *sink)
> +{
> +	struct snd_soc_dapm_widget *w = sink;
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_i2s_priv *i2s_priv;
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

Is this an error? => dev_err()
Is this expected? => dev_dbg()

> +		return 0;
> +	}
> +
> +	if (i2s_priv->share_i2s_id < 0)
> +		return 0;
> +
> +	return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);
> +}
> +
> +static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
> +				  struct snd_soc_dapm_widget *sink)
> +{
> +	struct snd_soc_dapm_widget *w = sink;
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mtk_afe_i2s_priv *i2s_priv;
> +
> +	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

Is this an error? => dev_err()
Is this expected? => dev_dbg()

Please fix all of the other instances of this.

> +		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;
> +
> +	/* check if share i2s need hd en */
> +	if (i2s_priv->share_i2s_id < 0)
> +		return 0;
> +
> +	if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
> +		return i2s_priv->low_jitter_en;
> +
> +	return 0;
> +}
> +

..snip...

> +
> +/* dai ops */
> +static int mtk_dai_connsys_i2s_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 rate = params_rate(params);
> +	unsigned int rate_reg = mt8186_rate_transform(afe->dev,
> +						      rate, dai->id);
> +	unsigned int i2s_con = 0;
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> +		 __func__,
> +		 dai->id,
> +		 substream->stream,
> +		 rate);
> +
> +	/* non-inverse, i2s mode, slave, 16bits, from connsys */
> +	i2s_con |= 0 << INV_PAD_CTRL_SFT;
> +	i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
> +	i2s_con |= 1 << I2S_SRC_SFT;
> +	i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT;
> +	i2s_con |= 0 << I2SIN_PAD_SEL_SFT;
> +	regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);
> +
> +	/* use asrc */
> +	regmap_update_bits(afe->regmap,
> +			   AFE_CONNSYS_I2S_CON,
> +			   I2S_BYPSRC_MASK_SFT,
> +			   0x0 << I2S_BYPSRC_SFT);

Zero shifted of a billion bits is still zero.

regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, I2S_BYPSRC_MASK_SFT, 0);

> +
> +	/* slave mode, set i2s for asrc */
> +	regmap_update_bits(afe->regmap,
> +			   AFE_CONNSYS_I2S_CON,
> +			   I2S_MODE_MASK_SFT,
> +			   rate_reg << I2S_MODE_SFT);

	regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,

			   I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT);

> +
> +	if (rate == 44100)
> +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001B9000);

lower case hex, please, and no leading zeros.

> +	else if (rate == 32000)
> +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);
> +	else
> +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001E0000);
> +
> +	/* Calibration setting */
> +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x00140000);
> +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x00036000);
> +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x0002FC00);
> +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x00007EF4);
> +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0x00FF5986);

ditto.

> +
> +	/* 0:Stereo 1:Mono */
> +	regmap_update_bits(afe->regmap,
> +			   AFE_ASRC_2CH_CON2,
> +			   CHSET_IS_MONO_MASK_SFT,
> +			   0x0 << CHSET_IS_MONO_SFT);

0 << SOMETHING = 0

Also, this fits in one line.

> +
> +	return 0;
> +}
> +
> +static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream,
> +				       int cmd, struct snd_soc_dai *dai)
> +{
> +	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +
> +	dev_info(afe->dev, "%s(), cmd %d, stream %d\n",
> +		 __func__,
> +		 cmd,
> +		 substream->stream);

dev_dbg(), also fits in two lines.

> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +		/* i2s enable */
> +		regmap_update_bits(afe->regmap,
> +				   AFE_CONNSYS_I2S_CON,
> +				   I2S_EN_MASK_SFT,
> +				   0x1 << I2S_EN_SFT);

BIT()

> +
> +		/* calibrator enable */
> +		regmap_update_bits(afe->regmap,
> +				   AFE_ASRC_2CH_CON5,
> +				   CALI_EN_MASK_SFT,
> +				   0x1 << CALI_EN_SFT);

BIT()

> +
> +		/* asrc enable */
> +		regmap_update_bits(afe->regmap,
> +				   AFE_ASRC_2CH_CON0,
> +				   CON0_CHSET_STR_CLR_MASK_SFT,
> +				   0x1 << CON0_CHSET_STR_CLR_SFT);

BIT()

> +		regmap_update_bits(afe->regmap,
> +				   AFE_ASRC_2CH_CON0,
> +				   CON0_ASM_ON_MASK_SFT,
> +				   0x1 << CON0_ASM_ON_SFT);

BIT()

> +
> +		afe_priv->dai_on[dai->id] = true;
> +		return 0;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +		regmap_update_bits(afe->regmap,
> +				   AFE_ASRC_2CH_CON0,
> +				   CON0_ASM_ON_MASK_SFT,
> +				   0 << CON0_ASM_ON_SFT);

This is zero.

> +		regmap_update_bits(afe->regmap,
> +				   AFE_ASRC_2CH_CON5,
> +				   CALI_EN_MASK_SFT,
> +				   0 << CALI_EN_SFT);

Zero again.

> +
> +		/* i2s disable */
> +		regmap_update_bits(afe->regmap,
> +				   AFE_CONNSYS_I2S_CON,
> +				   I2S_EN_MASK_SFT,
> +				   0x0 << I2S_EN_SFT);

...and again.

> +
> +		/* bypass asrc */
> +		regmap_update_bits(afe->regmap,
> +				   AFE_CONNSYS_I2S_CON,
> +				   I2S_BYPSRC_MASK_SFT,
> +				   0x1 << I2S_BYPSRC_SFT);

BIT()

> +
> +		afe_priv->dai_on[dai->id] = false;
> +		return 0;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = {
> +	.hw_params = mtk_dai_connsys_i2s_hw_params,
> +	.trigger = mtk_dai_connsys_i2s_trigger,
> +};
> +
> +/* i2s */
> +static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
> +			      struct snd_pcm_hw_params *params,
> +			      int i2s_id)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];
> +
> +	unsigned int rate = params_rate(params);
> +	unsigned int rate_reg = mt8186_rate_transform(afe->dev,
> +						      rate, i2s_id);

Fits on a single line.

> +	snd_pcm_format_t format = params_format(params);
> +	unsigned int i2s_con = 0;
> +	int ret = 0;
> +
> +	dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n",
> +		 __func__,
> +		 i2s_id,
> +		 rate, format);

dev_dbg(), fits on two lines.

> +
> +	if (i2s_priv)
> +		i2s_priv->rate = rate;
> +	else
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

I'm not sure about this print, maybe this should also be dev_dbg()

> +
> +	switch (i2s_id) {
> +	case MT8186_DAI_I2S_0:
> +		i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
> +		i2s_con |= rate_reg << I2S_OUT_MODE_SFT;
> +		i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
> +		i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
> +		regmap_update_bits(afe->regmap, AFE_I2S_CON,
> +				   0xffffeffa, i2s_con);
> +		break;
> +	case MT8186_DAI_I2S_1:
> +		i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;
> +		i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;
> +		i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;
> +		i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;
> +		regmap_update_bits(afe->regmap, AFE_I2S_CON1,
> +				   0xffffeffa, i2s_con);
> +		break;
> +	case MT8186_DAI_I2S_2:
> +		i2s_con = 8 << I2S3_UPDATE_WORD_SFT;
> +		i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;
> +		i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;
> +		i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;
> +		regmap_update_bits(afe->regmap, AFE_I2S_CON2,
> +				   0xffffeffa, i2s_con);
> +		break;
> +	case MT8186_DAI_I2S_3:
> +		i2s_con = rate_reg << I2S4_OUT_MODE_SFT;
> +		i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;
> +		i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;
> +		regmap_update_bits(afe->regmap, AFE_I2S_CON3,
> +				   0xffffeffa, i2s_con);
> +		break;
> +	default:
> +		dev_info(afe->dev, "%s(), id %d not support\n",
> +			 __func__, i2s_id);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	/* set share i2s */
> +	if (i2s_priv && i2s_priv->share_i2s_id >= 0)
> +		ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);
> +

	if (i2s_priv && i2s_priv->share_i2s_id >= 0) {

		ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);

		if (ret)

			return ret;

	}



	return 0;

> +	return ret;
> +}
> +
> +static int mtk_dai_i2s_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);
> +
> +	return mtk_dai_i2s_config(afe, params, dai->id);
> +}
> +
> +static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
> +				  int clk_id, unsigned int freq, int dir)
> +{
> +	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];
> +	int apll;
> +	int apll_rate;
> +
> +	if (!i2s_priv) {
> +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	if (dir != SND_SOC_CLOCK_OUT) {
> +		dev_info(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);

again...

> +		return -EINVAL;
> +	}
> +
> +	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);

dev_dbg()

> +
> +	apll = mt8186_get_apll_by_rate(afe, freq);
> +	apll_rate = mt8186_get_apll_rate(afe, apll);
> +
> +	if (freq > apll_rate) {
> +		dev_info(afe->dev, "%s(), freq > apll rate", __func__);

dev_err() .... please fix the rest as well.

> +		return -EINVAL;
> +	}
> +
> +	if (apll_rate % freq != 0) {
> +		dev_info(afe->dev, "%s(), APLL cannot generate freq Hz", __func__);
> +		return -EINVAL;
> +	}
> +
> +	i2s_priv->mclk_rate = freq;
> +	i2s_priv->mclk_apll = apll;
> +
> +	if (i2s_priv->share_i2s_id > 0) {
> +		struct mtk_afe_i2s_priv *share_i2s_priv;
> +
> +		share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
> +		if (!share_i2s_priv) {
> +			dev_info(afe->dev, "%s(), share_i2s_priv == NULL", __func__);
> +			return -EINVAL;
> +		}
> +
> +		share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
> +		share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
> +	}
> +
> +	return 0;
> +}
> +

Regards,
Angelo


_______________________________________________
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] 44+ messages in thread

* Re: [v2 09/17] ASoC: mediatek: mt8186: support tdm in platform driver
  2022-02-17 13:41 ` [v2 09/17] ASoC: mediatek: mt8186: support tdm " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-03 14:10     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 tdm dai driver.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 713 +++++++++++++++++++++
>   1 file changed, 713 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> new file mode 100644
> index 000000000000..28dd3661f0e0
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> @@ -0,0 +1,713 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// MediaTek ALSA SoC Audio DAI TDM Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/regmap.h>
> +#include <sound/pcm_params.h>
> +
> +#include "mt8186-afe-clk.h"
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-gpio.h"
> +#include "mt8186-interconnection.h"
> +
> +#define TDM_HD_EN_W_NAME "TDM_HD_EN"
> +#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"
> +#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"
> +
> +struct mtk_afe_tdm_priv {
> +	unsigned int id;
> +	unsigned int rate; /* for determine which apll to use */
> +	unsigned int bck_invert;
> +	unsigned int lck_invert;
> +	unsigned int lrck_width;
> +	unsigned int mclk_id;
> +	unsigned int mclk_multiple; /* according to sample rate */
> +	unsigned int mclk_rate;
> +	unsigned int mclk_apll;
> +	unsigned int tdm_mode;
> +	unsigned int data_mode;
> +	unsigned int slave_mode;
> +	unsigned int low_jitter_en;
> +};
> +
> +enum {
> +	TDM_IN_I2S = 0,
> +	TDM_IN_LJ = 1,
> +	TDM_IN_RJ = 2,
> +	TDM_IN_DSP_A = 4,
> +	TDM_IN_DSP_B = 5,
> +};
> +
> +enum {
> +	TDM_DATA_ONE_PIN = 0,
> +	TDM_DATA_MULTI_PIN,
> +};
> +
> +enum {
> +	TDM_BCK_NON_INV = 0,
> +	TDM_BCK_INV = 1,
> +};
> +
> +enum {
> +	TDM_LCK_NON_INV = 0,
> +	TDM_LCK_INV = 1,
> +};
> +
> +static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,
> +				       unsigned int mode)
> +{
> +	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
> +		return 0;
> +	else

Drop the "else"

> +		return snd_pcm_format_physical_width(format) - 1;
> +}
> +
> +static unsigned int get_tdm_ch_fixup(unsigned int channels)
> +{
> +	if (channels > 4)
> +		return 8;
> +	else if (channels > 2)
> +		return 4;
> +	else

Same here

> +		return 2;
> +}
> +
> +static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
> +					 unsigned int channels)
> +{
> +	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
> +		return get_tdm_ch_fixup(channels);
> +	else

...and same here

> +		return 2;
> +}
> +
> +enum {
> +	SUPPLY_SEQ_APLL,
> +	SUPPLY_SEQ_TDM_MCK_EN,
> +	SUPPLY_SEQ_TDM_HD_EN,
> +	SUPPLY_SEQ_TDM_EN,
> +};
> +
> +static int get_tdm_id_by_name(const char *name)
> +{
> +	return MT8186_DAI_TDM_IN;
> +}
> +
> +static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
> +			    struct snd_kcontrol *kcontrol,
> +			    int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> +		__func__, w->name, event);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
> +				struct snd_kcontrol *kcontrol,
> +				int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);

dev_err() - please fix all other instances

> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
> +		__func__, w->name, event, dai_id);
> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
> +		break;
> +	case SND_SOC_DAPM_POST_PMD:
> +		tdm_priv->mclk_rate = 0;
> +		mt8186_mck_disable(afe, tdm_priv->mclk_id);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +

...snip...

> +
> +static int mt8186_tdm_hd_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 dai_id = get_tdm_id_by_name(kcontrol->id.name);
> +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	int hd_en;
> +
> +	if (ucontrol->value.enumerated.item[0] >= e->items)
> +		return -EINVAL;
> +
> +	hd_en = ucontrol->value.integer.value[0];
> +
> +	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
> +		 __func__, kcontrol->id.name, hd_en);

dev_dbg()

> +
> +	if (!tdm_priv) {
> +		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> +		return -EINVAL;
> +	}
> +
> +	tdm_priv->low_jitter_en = hd_en;
> +
> +	return 0;
> +}
> +
> +static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
> +	SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],
> +		     mt8186_tdm_hd_get, mt8186_tdm_hd_set),
> +};
> +
> +static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
> +	{"TDM IN", NULL, "aud_tdm_clk"},
> +	{"TDM IN", NULL, "TDM_EN"},
> +	{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},
> +	{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
> +	{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
> +
> +	{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},
> +	{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect},
> +	{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect},
> +
> +	/* allow tdm on without codec on */
> +	{"TDM IN", NULL, "TDM_In_Mux"},
> +	{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},
> +};
> +
> +/* dai ops */
> +static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
> +				struct mtk_afe_tdm_priv *tdm_priv,
> +				int freq)
> +{
> +	int apll;
> +	int apll_rate;
> +
> +	apll = mt8186_get_apll_by_rate(afe, freq);
> +	apll_rate = mt8186_get_apll_rate(afe, apll);
> +
> +	if (!freq || freq > apll_rate) {
> +		dev_info(afe->dev,
> +			 "%s(), freq(%d Hz) invalid\n", __func__, freq);
> +		return -EINVAL;
> +	}
> +
> +	if (apll_rate % freq != 0) {
> +		dev_info(afe->dev,
> +			 "%s(), APLL cannot generate %d Hz", __func__, freq);
> +		return -EINVAL;
> +	}
> +
> +	tdm_priv->mclk_rate = freq;
> +	tdm_priv->mclk_apll = apll;
> +
> +	return 0;
> +}
> +
> +static int mtk_dai_tdm_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);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int tdm_id = dai->id;
> +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
> +	unsigned int tdm_mode = tdm_priv->tdm_mode;
> +	unsigned int data_mode = tdm_priv->data_mode;
> +	unsigned int rate = params_rate(params);
> +	unsigned int channels = params_channels(params);
> +	snd_pcm_format_t format = params_format(params);
> +	unsigned int bit_width =
> +		snd_pcm_format_physical_width(format);
> +	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?
> +		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
> +	unsigned int lrck_width =
> +		get_tdm_lrck_width(format, tdm_mode);
> +	unsigned int tdm_con = 0;
> +	bool slave_mode = tdm_priv->slave_mode;
> +	bool lrck_inv = tdm_priv->lck_invert;
> +	bool bck_inv = tdm_priv->bck_invert;
> +	unsigned int ctrl_reg;
> +	unsigned int ctrl_mask;
> +	unsigned int tran_rate;
> +	unsigned int tran_relatch_rate;
> +
> +	if (tdm_priv)
> +		tdm_priv->rate = rate;
> +	else
> +		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> +
> +	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);
> +	}
> +
> +	/* ETDM_IN1_CON0 */
> +	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
> +	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
> +	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
> +	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
> +	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;
> +	/* default disable sync mode */
> +	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;

0 << (anything) == 0

(number |= 0) == number

Is this a mistake, or are you really doing nothing here?


> +	/* relatch fix to h26m */
> +	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
> +
> +	ctrl_reg = ETDM_IN1_CON0;
> +	ctrl_mask = ETDM_IN_CON0_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> +
> +	/* ETDM_IN1_CON1 */
> +	tdm_con = 0;
> +	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
> +	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
> +	tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
> +
> +	ctrl_reg = ETDM_IN1_CON1;
> +	ctrl_mask = ETDM_IN_CON1_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);

You don't need the ctrl_reg, nor ctrl_mask variables...

regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con);

> +
> +	/* ETDM_IN1_CON3 */
> +	tdm_con = 0;
> +	tdm_con = ETDM_IN_CON3_FS(tran_rate);
> +
> +	ctrl_reg = ETDM_IN1_CON3;
> +	ctrl_mask = ETDM_IN_CON3_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);

same here

> +
> +	/* ETDM_IN1_CON4 */
> +	tdm_con = 0;
> +	tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);
> +	if (slave_mode) {
> +		if (lrck_inv)
> +			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;
> +		if (bck_inv)
> +			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;
> +	} else {
> +		if (lrck_inv)
> +			tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;
> +		if (bck_inv)
> +			tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;
> +	}
> +
> +	ctrl_reg = ETDM_IN1_CON4;
> +	ctrl_mask = ETDM_IN_CON4_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);

and here

> +
> +	/* ETDM_IN1_CON2 */
> +	tdm_con = 0;
> +	if (data_mode == TDM_DATA_MULTI_PIN) {
> +		tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;
> +		tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);
> +	}
> +
> +	ctrl_reg = ETDM_IN1_CON2;
> +	ctrl_mask = ETDM_IN_CON2_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);

and here

> +
> +	/* ETDM_IN1_CON8 */
> +	tdm_con = 0;
> +	if (slave_mode) {
> +		tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
> +		tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;
> +		tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);
> +	} else {
> +		tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
> +	}
> +
> +	ctrl_reg = ETDM_IN1_CON8;
> +	ctrl_mask = ETDM_IN_CON8_CTRL_MASK;
> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);

finally, here too.

> +
> +	return 0;
> +}
> +

Thanks,
ANgelo

_______________________________________________
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] 44+ messages in thread

* Re: [v2 10/17] ASoC: mediatek: mt8186: support audio clock control in platform driver
  2022-02-17 13:41 ` [v2 10/17] ASoC: mediatek: mt8186: support audio clock control " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-03 15:16     ` Jiaxin Yu
  2022-03-03 15:17     ` Jiaxin Yu
  0 siblings, 2 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch add audio clock control with CCF interface.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 719 +++++++++++++++++++++
>   sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 210 ++++++
>   2 files changed, 929 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> new file mode 100644
> index 000000000000..14f64b935619
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> @@ -0,0 +1,719 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// mt8186-afe-clk.c  --  Mediatek 8186 afe clock ctrl
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-clk.h"
> +#include "mt8186-audsys-clk.h"
> +
> +static DEFINE_MUTEX(mutex_request_dram);
> +
> +static const char *aud_clks[CLK_NUM] = {
> +	[CLK_AFE] = "aud_afe_clk",
> +	[CLK_DAC] = "aud_dac_clk",
> +	[CLK_DAC_PREDIS] = "aud_dac_predis_clk",
> +	[CLK_ADC] = "aud_adc_clk",
> +	[CLK_TML] = "aud_tml_clk",
> +	[CLK_APLL22M] = "aud_apll22m_clk",
> +	[CLK_APLL24M] = "aud_apll24m_clk",
> +	[CLK_APLL1_TUNER] = "aud_apll_tuner_clk",
> +	[CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
> +	[CLK_TDM] = "aud_tdm_clk",
> +	[CLK_NLE] = "aud_nle_clk",
> +	[CLK_DAC_HIRES] = "aud_dac_hires_clk",
> +	[CLK_ADC_HIRES] = "aud_adc_hires_clk",
> +	[CLK_I2S1_BCLK] = "aud_i2s1_bclk",
> +	[CLK_I2S2_BCLK] = "aud_i2s2_bclk",
> +	[CLK_I2S3_BCLK] = "aud_i2s3_bclk",
> +	[CLK_I2S4_BCLK] = "aud_i2s4_bclk",
> +	[CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc",
> +	[CLK_GENERAL1_ASRC] = "aud_general1_asrc",
> +	[CLK_GENERAL2_ASRC] = "aud_general2_asrc",
> +	[CLK_ADC_HIRES_TML] = "aud_adc_hires_tml",
> +	[CLK_ADDA6_ADC] = "aud_adda6_adc",
> +	[CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> +	[CLK_3RD_DAC] = "aud_3rd_dac",
> +	[CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis",
> +	[CLK_3RD_DAC_TML] = "aud_3rd_dac_tml",
> +	[CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires",
> +	[CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk",
> +	[CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk",
> +	[CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
> +	[CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk",
> +	[CLK_MUX_AUDIO] = "top_mux_audio",
> +	[CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int",
> +	[CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4",
> +	[CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
> +	[CLK_TOP_APLL1_CK] = "top_apll1_ck",
> +	[CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
> +	[CLK_TOP_APLL2_CK] = "top_apll2_ck",
> +	[CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
> +	[CLK_TOP_APLL1_D8] = "top_apll1_d8",
> +	[CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
> +	[CLK_TOP_APLL2_D8] = "top_apll2_d8",
> +	[CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h",
> +	[CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
> +	[CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
> +	[CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
> +	[CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
> +	[CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel",
> +	[CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
> +	[CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
> +	[CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
> +	[CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
> +	[CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm",
> +	[CLK_CLK26M] = "top_clk26m_clk",
> +};
> +
> +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe,
> +				    int clk_id)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
> +			     afe_priv->clk[clk_id]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS],
> +			 aud_clks[clk_id], ret);

		dev_err(......)
		return ret;

> +	}
> +

	return 0;

> +	return ret;
> +}
> +
> +static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret = 0;
> +
> +	if (enable) {
> +		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1], ret);
> +			goto EXIT;
> +		}
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> +				     afe_priv->clk[CLK_TOP_APLL1_CK]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> +				 aud_clks[CLK_TOP_APLL1_CK], ret);

dev_err()

> +			goto EXIT;
> +		}
> +
> +		/* 180.6336 / 8 = 22.5792MHz */
> +		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
> +			goto EXIT;
> +		}
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
> +				     afe_priv->clk[CLK_TOP_APLL1_D8]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
> +				 aud_clks[CLK_TOP_APLL1_D8], ret);
> +			goto EXIT;
> +		}
> +	} else {
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
> +				     afe_priv->clk[CLK_CLK26M]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
> +				 aud_clks[CLK_CLK26M], ret);
> +			goto EXIT;
> +		}
> +		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
> +
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> +				     afe_priv->clk[CLK_CLK26M]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> +				 aud_clks[CLK_CLK26M], ret);
> +			goto EXIT;
> +		}
> +		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
> +	}
> +EXIT:
> +	return 0;

You're returning 0 even in error cases, this is wrong.

> +}
> +
> +static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret = 0;
> +
> +	if (enable) {
> +		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2], ret);
> +			goto EXIT;
> +		}
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> +				     afe_priv->clk[CLK_TOP_APLL2_CK]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> +				 aud_clks[CLK_TOP_APLL2_CK], ret);
> +			goto EXIT;
> +		}
> +
> +		/* 196.608 / 8 = 24.576MHz */
> +		ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
> +			goto EXIT;
> +		}
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
> +				     afe_priv->clk[CLK_TOP_APLL2_D8]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
> +				 aud_clks[CLK_TOP_APLL2_D8], ret);
> +			goto EXIT;
> +		}
> +	} else {
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
> +				     afe_priv->clk[CLK_CLK26M]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
> +				 aud_clks[CLK_CLK26M], ret);
> +			goto EXIT;
> +		}
> +		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
> +
> +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> +				     afe_priv->clk[CLK_CLK26M]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> +				 aud_clks[CLK_CLK26M], ret);
> +			goto EXIT;
> +		}
> +		clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
> +	}
> +
> +EXIT:
> +	return 0;
> +}
> +
> +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret = 0;
> +	int i;
> +
> +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) {
> +		ret = clk_prepare_enable(afe_priv->clk[i]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[i], ret);

dev_err()

> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int i;
> +
> +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++)
> +		clk_disable_unprepare(afe_priv->clk[i]);
> +}
> +
> +int mt8186_afe_enable_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret = 0;
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);

dev_err()

> +		goto CLK_INFRA_SYS_AUDIO_ERR;

also, please use lower-case labels (here and everywhere else).

> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret);
> +		goto CLK_INFRA_AUDIO_26M_ERR;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIO], ret);
> +		goto CLK_MUX_AUDIO_ERR;
> +	}
> +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
> +			     afe_priv->clk[CLK_CLK26M]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIO],
> +			 aud_clks[CLK_CLK26M], ret);
> +		goto CLK_MUX_AUDIO_ERR;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> +	}
> +	ret = mt8186_set_audio_int_bus_parent(afe,
> +					      CLK_TOP_MAINPLL_D2_D4);
> +	if (ret)
> +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> +
> +	ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H],
> +			     afe_priv->clk[CLK_TOP_APLL2_CK]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +			 __func__, aud_clks[CLK_TOP_MUX_AUDIO_H],
> +			 aud_clks[CLK_TOP_APLL2_CK], ret);
> +		goto CLK_MUX_AUDIO_H_PARENT_ERR;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_AFE], ret);
> +		goto CLK_AFE_ERR;
> +	}
> +
> +	return 0;
> +
> +CLK_AFE_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> +CLK_MUX_AUDIO_H_PARENT_ERR:
> +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> +CLK_MUX_AUDIO_INTBUS_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +CLK_MUX_AUDIO_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> +CLK_INFRA_SYS_AUDIO_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> +CLK_INFRA_AUDIO_26M_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> +
> +	return ret;
> +}
> +
> +void mt8186_afe_disable_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> +}
> +
> +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* set audio int bus to 26M */
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);

dev_err() - here and for the other similar instances.

> +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> +	}
> +	ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> +	if (ret)
> +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +
> +	return 0;
> +
> +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> +	mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4);
> +CLK_MUX_AUDIO_INTBUS_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	return ret;
> +}
> +
> +int mt8186_afe_resume_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* set audio int bus to normal working clock */
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> +	}
> +	ret = mt8186_set_audio_int_bus_parent(afe,
> +					      CLK_TOP_MAINPLL_D2_D4);
> +	if (ret)
> +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +
> +	return 0;
> +
> +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> +CLK_MUX_AUDIO_INTBUS_ERR:
> +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> +	return ret;
> +}
> +
> +int mt8186_apll1_enable(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* setting for APLL */
> +	apll1_mux_setting(afe, true);
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_APLL22M], ret);
> +		goto ERR_CLK_APLL22M;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_APLL1_TUNER], ret);
> +		goto ERR_CLK_APLL1_TUNER;
> +	}
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
> +			   0x0000FFF7, 0x00000832);

no leading zeroes - and without them, it fits in one line.

> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
> +
> +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> +			   AFE_22M_ON_MASK_SFT,
> +			   0x1 << AFE_22M_ON_SFT);

BIT() macro please

> +
> +	return 0;
> +
> +ERR_CLK_APLL1_TUNER:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> +ERR_CLK_APLL22M:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> +
> +	return ret;
> +}
> +
> +void mt8186_apll1_disable(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +
> +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> +			   AFE_22M_ON_MASK_SFT,
> +			   0x0 << AFE_22M_ON_SFT);
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> +
> +	apll1_mux_setting(afe, false);
> +}
> +
> +int mt8186_apll2_enable(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* setting for APLL */
> +	apll2_mux_setting(afe, true);
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_APLL24M], ret);
> +		goto ERR_CLK_APLL24M;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[CLK_APLL2_TUNER], ret);
> +		goto ERR_CLK_APLL2_TUNER;
> +	}
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
> +			   0x0000FFF7, 0x00000634);
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
> +
> +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> +			   AFE_24M_ON_MASK_SFT,
> +			   0x1 << AFE_24M_ON_SFT);
> +
> +	return 0;
> +
> +ERR_CLK_APLL2_TUNER:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> +ERR_CLK_APLL24M:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> +
> +	return ret;
> +}
> +
> +void mt8186_apll2_disable(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +
> +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> +			   AFE_24M_ON_MASK_SFT,
> +			   0x0 << AFE_24M_ON_SFT);
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> +
> +	apll2_mux_setting(afe, false);
> +}
> +
> +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll)
> +{
> +	return (apll == MT8186_APLL1) ? 180633600 : 196608000;
> +}
> +
> +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
> +{
> +	return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1;
> +}
> +
> +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
> +{
> +	if (strcmp(name, APLL1_W_NAME) == 0)
> +		return MT8186_APLL1;
> +	else
> +		return MT8186_APLL2;
> +}
> +
> +/* mck */
> +struct mt8186_mck_div {
> +	int m_sel_id;
> +	int div_clk_id;
> +	/* below will be deprecated */
> +	int div_pdn_reg;
> +	int div_pdn_mask_sft;
> +	int div_reg;
> +	int div_mask_sft;
> +	int div_mask;
> +	int div_sft;
> +	int div_msb_reg;
> +	int div_msb_mask_sft;
> +	int div_msb_mask;
> +	int div_msb_sft;
> +	int div_apll_sel_reg;
> +	int div_apll_sel_mask_sft;
> +	int div_apll_sel_sft;
> +	int div_inv_reg;
> +	int div_inv_mask_sft;



*_reg fits in u16.
*_mask_sft, *_sel_sft can be u32.

This would be nice to avoid wasting memory for variables that are larger than
needed; besides, you're also using a signed type for a number that may not
ever be less than zero.


> +};
> +
> +static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = {
> +	[MT8186_I2S0_MCK] = {
> +		.m_sel_id = CLK_TOP_I2S0_M_SEL,
> +		.div_clk_id = CLK_TOP_APLL12_DIV0,
> +		.div_pdn_reg = CLK_AUDDIV_0,
> +		.div_pdn_mask_sft = APLL12_DIV0_PDN_MASK_SFT,
> +		.div_reg = CLK_AUDDIV_2,
> +		.div_mask_sft = APLL12_CK_DIV0_MASK_SFT,
> +		.div_mask = APLL12_CK_DIV0_MASK,
> +		.div_sft = APLL12_CK_DIV0_SFT,
> +		.div_apll_sel_reg = CLK_AUDDIV_0,
> +		.div_apll_sel_mask_sft = APLL_I2S0_MCK_SEL_MASK_SFT,
> +		.div_apll_sel_sft = APLL_I2S0_MCK_SEL_SFT,
> +	},
> +	[MT8186_I2S1_MCK] = {
> +		.m_sel_id = CLK_TOP_I2S1_M_SEL,
> +		.div_clk_id = CLK_TOP_APLL12_DIV1,
> +		.div_pdn_reg = CLK_AUDDIV_0,
> +		.div_pdn_mask_sft = APLL12_DIV1_PDN_MASK_SFT,
> +		.div_reg = CLK_AUDDIV_2,
> +		.div_mask_sft = APLL12_CK_DIV1_MASK_SFT,
> +		.div_mask = APLL12_CK_DIV1_MASK,
> +		.div_sft = APLL12_CK_DIV1_SFT,
> +		.div_apll_sel_reg = CLK_AUDDIV_0,
> +		.div_apll_sel_mask_sft = APLL_I2S1_MCK_SEL_MASK_SFT,
> +		.div_apll_sel_sft = APLL_I2S1_MCK_SEL_SFT,
> +	},
> +	[MT8186_I2S2_MCK] = {
> +		.m_sel_id = CLK_TOP_I2S2_M_SEL,
> +		.div_clk_id = CLK_TOP_APLL12_DIV2,
> +		.div_pdn_reg = CLK_AUDDIV_0,
> +		.div_pdn_mask_sft = APLL12_DIV2_PDN_MASK_SFT,
> +		.div_reg = CLK_AUDDIV_2,
> +		.div_mask_sft = APLL12_CK_DIV2_MASK_SFT,
> +		.div_mask = APLL12_CK_DIV2_MASK,
> +		.div_sft = APLL12_CK_DIV2_SFT,
> +		.div_apll_sel_reg = CLK_AUDDIV_0,
> +		.div_apll_sel_mask_sft = APLL_I2S2_MCK_SEL_MASK_SFT,
> +		.div_apll_sel_sft = APLL_I2S2_MCK_SEL_SFT,
> +	},
> +	[MT8186_I2S4_MCK] = {
> +		.m_sel_id = CLK_TOP_I2S4_M_SEL,
> +		.div_clk_id = CLK_TOP_APLL12_DIV4,
> +		.div_pdn_reg = CLK_AUDDIV_0,
> +		.div_pdn_mask_sft = APLL12_DIV4_PDN_MASK_SFT,
> +		.div_reg = CLK_AUDDIV_2,
> +		.div_mask_sft = APLL12_CK_DIV4_MASK_SFT,
> +		.div_mask = APLL12_CK_DIV4_MASK,
> +		.div_sft = APLL12_CK_DIV4_SFT,
> +		.div_apll_sel_reg = CLK_AUDDIV_0,
> +		.div_apll_sel_mask_sft = APLL_I2S4_MCK_SEL_MASK_SFT,
> +		.div_apll_sel_sft = APLL_I2S4_MCK_SEL_SFT,
> +	},
> +	[MT8186_TDM_MCK] = {
> +		.m_sel_id = CLK_TOP_TDM_M_SEL,
> +		.div_clk_id = CLK_TOP_APLL12_DIV_TDM,
> +		.div_pdn_reg = CLK_AUDDIV_0,
> +		.div_pdn_mask_sft = APLL12_DIV_TDM_PDN_MASK_SFT,
> +		.div_reg = CLK_AUDDIV_3,
> +		.div_mask_sft = APLL12_CK_DIV_TDM_MASK_SFT,
> +		.div_mask = APLL12_CK_DIV_TDM_MASK,
> +		.div_sft = APLL12_CK_DIV_TDM_SFT,
> +		.div_apll_sel_reg = CLK_AUDDIV_0,
> +		.div_apll_sel_mask_sft = APLL_TDM_MCK_SEL_MASK_SFT,
> +		.div_apll_sel_sft = APLL_TDM_MCK_SEL_SFT,
> +	},
> +};
> +
> +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int apll = mt8186_get_apll_by_rate(afe, rate);
> +	int apll_clk_id = apll == MT8186_APLL1 ?
> +			  CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
> +	int m_sel_id = mck_div[mck_id].m_sel_id;
> +	int div_clk_id = mck_div[mck_id].div_clk_id;
> +	int ret;
> +
> +	/* select apll */
> +	if (m_sel_id >= 0) {
> +		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
> +				 __func__, aud_clks[m_sel_id], ret);

dev_err()

> +			return ret;
> +		}
> +		ret = clk_set_parent(afe_priv->clk[m_sel_id],
> +				     afe_priv->clk[apll_clk_id]);
> +		if (ret) {
> +			dev_info(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
> +				 __func__, aud_clks[m_sel_id],
> +				aud_clks[apll_clk_id], ret);

again

> +			return ret;
> +		}
> +	}
> +
> +	/* enable div, set rate */
> +	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
> +	if (ret) {
> +		dev_info(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
> +			 __func__, aud_clks[div_clk_id], ret);

again

> +		return ret;
> +	}
> +	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
> +	if (ret) {
> +		dev_info(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
> +			 __func__, aud_clks[div_clk_id],
> +			 rate, ret);

again - and this fits in two lines.

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int m_sel_id = mck_div[mck_id].m_sel_id;
> +	int div_clk_id = mck_div[mck_id].div_clk_id;
> +
> +	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
> +	if (m_sel_id >= 0)
> +		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
> +}
> +
> +int mt8186_init_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct device_node *of_node = afe->dev->of_node;
> +	int i = 0;
> +
> +	 mt8186_audsys_clk_register(afe);

Fix indentation please

> +
> +	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
> +				     GFP_KERNEL);
> +	if (!afe_priv->clk)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < CLK_NUM; i++) {
> +		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
> +		if (IS_ERR(afe_priv->clk[i])) {
> +			dev_info(afe->dev, "%s devm_clk_get %s fail, ret %ld\n",
> +				 __func__,
> +				 aud_clks[i], PTR_ERR(afe_priv->clk[i]));
> +			afe_priv->clk[i] = NULL;
> +		}
> +	}
> +
> +	afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node,
> +							       "mediatek,apmixedsys");
> +	if (IS_ERR(afe_priv->apmixedsys)) {
> +		dev_err(afe->dev, "%s() Cannot find apmixedsys controller: %ld\n",
> +			__func__, PTR_ERR(afe_priv->apmixedsys));
> +		return PTR_ERR(afe_priv->apmixedsys);
> +	}
> +
> +	afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node,
> +							     "mediatek,topckgen");
> +	if (IS_ERR(afe_priv->topckgen)) {
> +		dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
> +			__func__, PTR_ERR(afe_priv->topckgen));
> +		return PTR_ERR(afe_priv->topckgen);
> +	}
> +
> +	afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node,
> +							     "mediatek,infracfg");
> +	if (IS_ERR(afe_priv->infracfg)) {
> +		dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n",
> +			__func__, PTR_ERR(afe_priv->infracfg));
> +		return PTR_ERR(afe_priv->infracfg);
> +	}
> +
> +	return 0;
> +}
> +
> +void mt8186_deinit_clock(struct mtk_base_afe *afe)
> +{
> +	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
> new file mode 100644
> index 000000000000..3ce7a9a24d4a
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> @@ -0,0 +1,210 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * mt8186-afe-clk.h  --  Mediatek 8186 afe clock ctrl definition
> + *
> + * Copyright (c) 2022 MediaTek Inc.
> + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> + */
> +
> +#ifndef _MT8186_AFE_CLOCK_CTRL_H_
> +#define _MT8186_AFE_CLOCK_CTRL_H_
> +
> +#define PERI_BUS_DCM_CTRL 0x0074
> +#define MODULE_SW_CG_1_STA 0x0094
> +#define MODULE_SW_CG_2_STA 0x00ac
> +#define CLK_CFG_7 0x0080
> +#define CLK_CFG_8 0x0090
> +#define CLK_CFG_11 0x00c0
> +#define CLK_CFG_12 0x00d0
> +#define CLK_CFG_13 0x00e0
> +#define CLK_CFG_15 0x0100
> +#define AP_PLL_CON3 0x0014
> +#define APLL1_CON4 0x0328
> +#define APLL1_TUNER_CON0 0x0040
> +#define APLL2_CON4 0x033c
> +#define APLL2_TUNER_CON0 0x0044
> +
> +#define AP_PLL_CON5 0x0014
> +#define APLL1_CON0 0x02c0
> +#define APLL1_CON1 0x02c4
> +#define APLL1_CON2 0x02c8
> +#define APLL1_CON3 0x02cc
> +#define APLL1_PWR_CON0 0x02d0
> +
> +#define APLL2_CON0 0x02d4
> +#define APLL2_CON1 0x02d8
> +#define APLL2_CON2 0x02dc
> +#define APLL2_CON3 0x02e0
> +#define APLL2_PWR_CON0 0x02e4
> +
> +#define APMIXEDSYS_MAX_LENGTH APLL2_PWR_CON0
> +
> +#define CLK_CFG_6 0x0080
> +#define CLK_AUDDIV_0 0x0320
> +#define CLK_AUDDIV_1 0x0324
> +#define CLK_AUDDIV_2 0x0328
> +#define CKSYS_AUD_TOP_CFG 0x032c
> +#define CKSYS_AUD_TOP_MON 0x0330
> +#define CLK_AUDDIV_3 0x0334
> +
> +#define CLK_MAX_LENGTH CLK_AUDDIV_3
> +
> +/* CLK_CFG_6 */
> +#define CLK_AUD_INTBUS_SEL_SFT              16
> +#define CLK_AUD_INTBUS_SEL_MASK             0x3
> +#define CLK_AUD_INTBUS_SEL_MASK_SFT         (0x3 << 16)

#define CLK_AUD_INTBUS_SEL_MASK_SFT		GENMASK(23, 22)

> +
> +/* CLK_AUDDIV_0 */
> +#define APLL12_DIV0_PDN_SFT                0
> +#define APLL12_DIV0_PDN_MASK               0x1
> +#define APLL12_DIV0_PDN_MASK_SFT           (0x1 << 0)

BIT() macro please

#define APLL12_DIV0_PDN_MASK_SFT		BIT(0)

also, using tabulations instead of spaces is nicer.

> +#define APLL12_DIV1_PDN_SFT                1
> +#define APLL12_DIV1_PDN_MASK               0x1
> +#define APLL12_DIV1_PDN_MASK_SFT           (0x1 << 1)

Of course, BIT() macro again, here and everywhere else applicable.

> +#define APLL12_DIV2_PDN_SFT                2
> +#define APLL12_DIV2_PDN_MASK               0x1
> +#define APLL12_DIV2_PDN_MASK_SFT           (0x1 << 2)
> +#define APLL12_DIV4_PDN_SFT                3
> +#define APLL12_DIV4_PDN_MASK               0x1
> +#define APLL12_DIV4_PDN_MASK_SFT           (0x1 << 3)
> +#define APLL12_DIV_TDM_PDN_SFT             4
> +#define APLL12_DIV_TDM_PDN_MASK            0x1
> +#define APLL12_DIV_TDM_PDN_MASK_SFT        (0x1 << 4)
> +#define APLL_I2S0_MCK_SEL_SFT              16
> +#define APLL_I2S0_MCK_SEL_MASK             0x1
> +#define APLL_I2S0_MCK_SEL_MASK_SFT         (0x1 << 16)
> +#define APLL_I2S1_MCK_SEL_SFT              17
> +#define APLL_I2S1_MCK_SEL_MASK             0x1
> +#define APLL_I2S1_MCK_SEL_MASK_SFT         (0x1 << 17)
> +#define APLL_I2S2_MCK_SEL_SFT              18
> +#define APLL_I2S2_MCK_SEL_MASK             0x1
> +#define APLL_I2S2_MCK_SEL_MASK_SFT         (0x1 << 17)
> +#define APLL_I2S4_MCK_SEL_SFT              19
> +#define APLL_I2S4_MCK_SEL_MASK             0x1
> +#define APLL_I2S4_MCK_SEL_MASK_SFT         (0x1 << 19)
> +#define APLL_TDM_MCK_SEL_SFT               20
> +#define APLL_TDM_MCK_SEL_MASK              0x1
> +#define APLL_TDM_MCK_SEL_MASK_SFT          (0x1 << 20)
> +
> +/* CLK_AUDDIV_2 */
> +#define APLL12_CK_DIV0_SFT                 0
> +#define APLL12_CK_DIV0_MASK                0xff
> +#define APLL12_CK_DIV0_MASK_SFT            (0xff << 0)

GENMASK(7, 0)

> +#define APLL12_CK_DIV1_SFT                 8
> +#define APLL12_CK_DIV1_MASK                0xff
> +#define APLL12_CK_DIV1_MASK_SFT            (0xff << 8)

GENMASK(15, 8)

> +#define APLL12_CK_DIV2_SFT                 16
> +#define APLL12_CK_DIV2_MASK                0xff
> +#define APLL12_CK_DIV2_MASK_SFT            (0xff << 16)

Fix all the others too :))

> +#define APLL12_CK_DIV4_SFT                 24
> +#define APLL12_CK_DIV4_MASK                0xff
> +#define APLL12_CK_DIV4_MASK_SFT            (0xff << 24)
> +
> +/* CLK_AUDDIV_3 */
> +#define APLL12_CK_DIV_TDM_SFT              0
> +#define APLL12_CK_DIV_TDM_MASK             0xff
> +#define APLL12_CK_DIV_TDM_MASK_SFT         (0xff << 0)
> +
> +/* AUD_TOP_CFG */
> +#define AUD_TOP_CFG_SFT                    0
> +#define AUD_TOP_CFG_MASK                   0xffffffff
> +#define AUD_TOP_CFG_MASK_SFT               (0xffffffff << 0)

This is GENMASK(31, 0) for both MASK and MASK_SFT

> +
> +/* AUD_TOP_MON */
> +#define AUD_TOP_MON_SFT                    0
> +#define AUD_TOP_MON_MASK                   0xffffffff
> +#define AUD_TOP_MON_MASK_SFT               (0xffffffff << 0)

same here



Regards,
Angelo

_______________________________________________
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] 44+ messages in thread

* Re: [v2 08/17] ASoC: mediatek: mt8186: support src in platform driver
  2022-02-17 13:41 ` [v2 08/17] ASoC: mediatek: mt8186: support src " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch adds mt8186 src dai driver
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-dai-src.c | 758 +++++++++++++++++++++
>   1 file changed, 758 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-src.c
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-src.c b/sound/soc/mediatek/mt8186/mt8186-dai-src.c
> new file mode 100644
> index 000000000000..7ff1623b591a
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-src.c
> @@ -0,0 +1,758 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +//  MediaTek ALSA SoC Audio DAI SRC Control
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/regmap.h>
> +#include "mt8186-afe-common.h"
> +#include "mt8186-interconnection.h"
> +
> +struct mtk_afe_src_priv {
> +	int dl_rate;
> +	int ul_rate;
> +};
> +
> +static const unsigned int src_iir_coeff_32_to_16[] = {
> +	0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002,
> +	0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002,
> +	0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002,
> +	0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002,
> +	0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002,
> +	0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002,
> +	0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002,
> +	0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001
> +};
> +
> +static const unsigned int src_iir_coeff_44_to_16[] = {
> +	0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002,
> +	0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002,
> +	0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002,
> +	0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002,
> +	0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002,
> +	0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002,
> +	0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001
> +};
> +
> +static const unsigned int src_iir_coeff_44_to_32[] = {
> +	0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003,
> +	0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002,
> +	0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002,
> +	0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002,
> +	0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002,
> +	0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002,
> +	0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001
> +};
> +
> +static const unsigned int src_iir_coeff_48_to_16[] = {
> +	0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002,
> +	0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002,
> +	0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002,
> +	0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002,
> +	0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002,
> +	0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002,
> +	0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001,
> +	0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004
> +};
> +
> +static const unsigned int src_iir_coeff_48_to_32[] = {
> +	0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002,
> +	0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002,
> +	0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002,
> +	0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002,
> +	0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002,
> +	0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002,
> +	0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001
> +};
> +
> +static const unsigned int src_iir_coeff_48_to_44[] = {
> +	0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003,
> +	0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003,
> +	0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003,
> +	0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003,
> +	0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001
> +};
> +
> +static const unsigned int src_iir_coeff_96_to_16[] = {
> +	0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
> +	0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
> +	0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
> +	0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
> +	0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
> +	0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
> +	0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
> +	0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
> +};
> +
> +static const unsigned int src_iir_coeff_96_to_44[] = {
> +	0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
> +	0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
> +	0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
> +	0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
> +	0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
> +	0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
> +	0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
> +	0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
> +};
> +
> +static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate)
> +{
> +	switch (rate) {
> +	case 8000:
> +		return 0x00050000;

No leading zeroes please

> +	case 11025:
> +		return 0x0006E400;
> +	case 12000:
> +		return 0x00078000;
> +	case 16000:
> +		return 0x000A0000;
> +	case 22050:
> +		return 0x000DC800;
> +	case 24000:
> +		return 0x000F0000;
> +	case 32000:
> +		return 0x00140000;
> +	case 44100:
> +		return 0x001B9000;
> +	case 48000:
> +		return 0x001E0000;
> +	case 88200:
> +		return 0x00372000;
> +	case 96000:
> +		return 0x003C0000;
> +	case 176400:
> +		return 0x006E4000;
> +	case 192000:
> +		return 0x00780000;
> +	default:
> +		dev_info(afe->dev, "%s(), rate %d invalid!!!\n",
> +			 __func__, rate);

dev_err()

> +		return 0;
> +	}
> +}
> +
> +static const unsigned int *get_iir_coeff(unsigned int rate_in,
> +					 unsigned int rate_out,
> +					 unsigned int *param_num)
> +{
> +	if (rate_in == 32000 && rate_out == 16000) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_32_to_16);
> +		return src_iir_coeff_32_to_16;
> +	} else if (rate_in == 44100 && rate_out == 16000) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_16);
> +		return src_iir_coeff_44_to_16;
> +	} else if (rate_in == 44100 && rate_out == 32000) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_32);
> +		return src_iir_coeff_44_to_32;
> +	} else if ((rate_in == 48000 && rate_out == 16000) ||
> +		   (rate_in == 96000 && rate_out == 32000)) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_16);
> +		return src_iir_coeff_48_to_16;
> +	} else if (rate_in == 48000 && rate_out == 32000) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_32);
> +		return src_iir_coeff_48_to_32;
> +	} else if (rate_in == 48000 && rate_out == 44100) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_44);
> +		return src_iir_coeff_48_to_44;
> +	} else if (rate_in == 96000 && rate_out == 16000) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_16);
> +		return src_iir_coeff_96_to_16;
> +	} else if ((rate_in == 96000 && rate_out == 44100) ||
> +		   (rate_in == 48000 && rate_out == 22050)) {
> +		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_44);
> +		return src_iir_coeff_96_to_44;
> +	}
> +
> +	*param_num = 0;
> +	return NULL;
> +}
> +
> +#define DEBUG_COEFF
> +static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
> +	unsigned int iir_coeff_num;
> +	unsigned int iir_stage;
> +	int rate_in = src_priv->dl_rate;
> +	int rate_out = src_priv->ul_rate;
> +	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe,
> +							   rate_out);

Fits in one line.

> +	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe,
> +							  rate_in);

ditto.

> +
> +	/* set out freq mode */
> +	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3,
> +			   G_SRC_ASM_FREQ_4_MASK_SFT,
> +			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
> +
> +	/* set in freq mode */
> +	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4,
> +			   G_SRC_ASM_FREQ_5_MASK_SFT,
> +			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
> +



> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL1_ASRC_2CH_CON5, 0x003f5986);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL1_ASRC_2CH_CON5, 0x003f5987);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL1_ASRC_2CH_CON6, 0x00001fbd);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL1_ASRC_2CH_CON2, 0x00000000);

All single ones of these fit in a single line.

> +
> +	/* set iir if in_rate > out_rate */
> +	if (rate_in > rate_out) {
> +		int i;
> +#ifdef DEBUG_COEFF
> +		int reg_val;
> +#endif
> +		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
> +							      &iir_coeff_num);
> +
> +		if (iir_coeff_num == 0 || !iir_coeff) {
> +			dev_info(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
> +				 __func__, iir_coeff_num, iir_coeff);
> +			return -EINVAL;
> +		}
> +
> +		/* COEFF_SRAM_CTRL */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
> +				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
> +				   0x1 << G_SRC_COEFF_SRAM_CTRL_SFT);
> +		/* Clear coeff history to r/w coeff from the first position */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
> +				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
> +				   0x0);
> +		/* Write SRC coeff, should not read the reg during write */
> +		for (i = 0; i < iir_coeff_num; i++)
> +			regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
> +				     iir_coeff[i]);
> +
> +#ifdef DEBUG_COEFF
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
> +				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
> +				   0x0);
> +
> +		for (i = 0; i < iir_coeff_num; i++) {
> +			regmap_read(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
> +				    &reg_val);
> +			dev_info(afe->dev, "%s(), i = %d, coeff = 0x%x\n",
> +				 __func__, i, reg_val);
> +		}
> +#endif
> +		/* disable sram access */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
> +				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
> +				   0x0);
> +		/* CHSET_IIR_STAGE */
> +		iir_stage = (iir_coeff_num / 6) - 1;
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
> +				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
> +		/* CHSET_IIR_EN */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_EN_MASK_SFT,
> +				   0x1 << G_SRC_CHSET_IIR_EN_SFT);

BIT()

> +	} else {
> +		/* CHSET_IIR_EN off */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_EN_MASK_SFT,
> +				   0x0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id)
> +{
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
> +	unsigned int iir_coeff_num;
> +	unsigned int iir_stage;
> +	int rate_in = src_priv->dl_rate;
> +	int rate_out = src_priv->ul_rate;
> +	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe,
> +							   rate_out);
> +	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe,
> +							  rate_in);
> +
> +	/* set out freq mode */
> +	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3,
> +			   G_SRC_ASM_FREQ_4_MASK_SFT,
> +			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
> +
> +	/* set in freq mode */
> +	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4,
> +			   G_SRC_ASM_FREQ_5_MASK_SFT,
> +			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
> +
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL2_ASRC_2CH_CON5, 0x003f5986);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL2_ASRC_2CH_CON5, 0x003f5987);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL2_ASRC_2CH_CON6, 0x00001fbd);
> +	regmap_write(afe->regmap,
> +		     AFE_GENERAL2_ASRC_2CH_CON2, 0x00000000);

no leading zeros; fits in one line.

> +
> +	/* set iir if in_rate > out_rate */
> +	if (rate_in > rate_out) {
> +		int i;
> +#ifdef DEBUG_COEFF
> +		int reg_val;
> +#endif
> +		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
> +							      &iir_coeff_num);
> +
> +		if (iir_coeff_num == 0 || !iir_coeff) {
> +			dev_info(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
> +				 __func__, iir_coeff_num, iir_coeff);

dev_err()

> +			return -EINVAL;
> +		}
> +
> +		/* COEFF_SRAM_CTRL */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
> +				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
> +				   0x1 << G_SRC_COEFF_SRAM_CTRL_SFT);

BIT()

> +		/* Clear coeff history to r/w coeff from the first position */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
> +				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
> +				   0x0);
> +		/* Write SRC coeff, should not read the reg during write */
> +		for (i = 0; i < iir_coeff_num; i++)
> +			regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
> +				     iir_coeff[i]);
> +
> +#ifdef DEBUG_COEFF
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
> +				   G_SRC_COEFF_SRAM_ADR_MASK_SFT,
> +				   0x0);
> +
> +		for (i = 0; i < iir_coeff_num; i++) {
> +			regmap_read(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
> +				    &reg_val);
> +			dev_info(afe->dev, "%s(), i = %d, coeff = 0x%x\n",
> +				 __func__, i, reg_val);
> +		}
> +#endif
> +		/* disable sram access */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
> +				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
> +				   0x0);
> +		/* CHSET_IIR_STAGE */
> +		iir_stage = (iir_coeff_num / 6) - 1;
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
> +				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
> +		/* CHSET_IIR_EN */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_EN_MASK_SFT,
> +				   0x1 << G_SRC_CHSET_IIR_EN_SFT);
> +	} else {
> +		/* CHSET_IIR_EN off */
> +		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
> +				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0x0);
> +	}
> +
> +	return 0;
> +}
> +
> +#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable"
> +#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable"
> +
> +static int mtk_hw_src_event(struct snd_soc_dapm_widget *w,
> +			    struct snd_kcontrol *kcontrol,
> +			    int event)
> +{
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int id;
> +	struct mtk_afe_src_priv *src_priv;
> +	unsigned int reg;
> +
> +	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
> +		id = MT8186_DAI_SRC_1;
> +	else
> +		id = MT8186_DAI_SRC_2;
> +
> +	src_priv = afe_priv->dai_priv[id];
> +
> +	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",
> +		__func__,
> +		w->name, event,
> +		id, src_priv,
> +		src_priv->dl_rate,
> +		src_priv->ul_rate);
	dev_dbg(afe->dev,

		"%s: name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",

		__func__, w->name, event, id, src_priv,

		src_priv->dl_rate, src_priv->ul_rate);

> +
> +	switch (event) {
> +	case SND_SOC_DAPM_PRE_PMU:
> +		if (id == MT8186_DAI_SRC_1)
> +			mtk_set_src_1_param(afe, id);
> +		else
> +			mtk_set_src_2_param(afe, id);
> +		break;
> +	case SND_SOC_DAPM_POST_PMU:
> +		reg = (id == MT8186_DAI_SRC_1) ?
> +		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
> +		/* ASM_ON */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_ASM_ON_MASK_SFT,
> +				   0x1 << G_SRC_ASM_ON_SFT);

BIT()

> +		/* CHSET_ON */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_CHSET_ON_MASK_SFT,
> +				   0x1 << G_SRC_CHSET_ON_SFT);

same

> +		/* CHSET_STR_CLR */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_CHSET_STR_CLR_MASK_SFT,
> +				   0x1 << G_SRC_CHSET_STR_CLR_SFT);

again

> +		break;
> +	case SND_SOC_DAPM_PRE_PMD:
> +		reg = (id == MT8186_DAI_SRC_1) ?
> +		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
> +		/* ASM_OFF */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_ASM_ON_MASK_SFT, 0x0);

Fits in one line

> +		/* CHSET_OFF */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_CHSET_ON_MASK_SFT, 0x0);
> +		/* CHSET_STR_CLR */
> +		regmap_update_bits(afe->regmap, reg,
> +				   G_SRC_CHSET_STR_CLR_MASK_SFT, 0x0);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +

..snip..

> +
> +static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source,
> +				  struct snd_soc_dapm_widget *sink)
> +{
> +	struct snd_soc_dapm_widget *w = source;
> +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
> +	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_src_priv *src_priv;
> +
> +	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
> +		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1];
> +	else
> +		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2];
> +
> +	dev_info(afe->dev,
> +		 "%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n",
> +		 __func__, source->name, sink->name,
> +		 src_priv->dl_rate, src_priv->ul_rate);

dev_dbg()

> +
> +	return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0;
> +}
> +
> +static const struct snd_soc_dapm_route mtk_dai_src_routes[] = {
> +	{"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"},
> +	{"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"},
> +	{"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"},
> +	{"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"},
> +	{"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"},
> +	{"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"},
> +	{"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"},
> +	{"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"},
> +	{"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"},
> +	{"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"},
> +	{"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"},
> +	{"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"},
> +	{"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"},
> +	{"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"},
> +	{"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"},
> +	{"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"},
> +	{"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"},
> +	{"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"},
> +	{"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"},
> +	{"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"},
> +	{"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"},
> +	{"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"},
> +	{"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"},
> +	{"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"},
> +
> +	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"},
> +	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"},
> +
> +	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"},
> +	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"},
> +
> +	{"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
> +	{"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
> +	{"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
> +	{"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
> +
> +	{"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"},
> +	{"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"},
> +	{"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"},
> +	{"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"},
> +};
> +
> +/* dai ops */
> +static int mtk_dai_src_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);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int id = dai->id;
> +	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
> +	unsigned int sft, mask;
> +	unsigned int rate = params_rate(params);
> +	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id);
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> +		 __func__,
> +		 id,
> +		 substream->stream,
> +		 rate);

Fits in two lines.

> +
> +	/* rate */
> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		src_priv->dl_rate = rate;
> +		if (id == MT8186_DAI_SRC_1) {
> +			sft = GENERAL1_ASRCIN_MODE_SFT;
> +			mask = GENERAL1_ASRCIN_MODE_MASK;
> +		} else {
> +			sft = GENERAL2_ASRCIN_MODE_SFT;
> +			mask = GENERAL2_ASRCIN_MODE_MASK;
> +		}
> +	} else {
> +		src_priv->ul_rate = rate;
> +		if (id == MT8186_DAI_SRC_1) {
> +			sft = GENERAL1_ASRCOUT_MODE_SFT;
> +			mask = GENERAL1_ASRCOUT_MODE_MASK;
> +		} else {
> +			sft = GENERAL2_ASRCOUT_MODE_SFT;
> +			mask = GENERAL2_ASRCOUT_MODE_MASK;
> +		}
> +	}
> +
> +	regmap_update_bits(afe->regmap,
> +			   GENERAL_ASRC_MODE,
> +			   mask << sft,
> +			   rate_reg << sft);

Fits in one line (90 col is borderline ok)

> +
> +	return 0;
> +}
> +
> +static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream,
> +			       struct snd_soc_dai *dai)
> +{
> +	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> +	int id = dai->id;
> +	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
> +
> +	dev_info(afe->dev, "%s(), id %d, stream %d\n",
> +		 __func__,
> +		 id,
> +		 substream->stream);

dev_dbg(), fits in two lines.

> +
> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +		src_priv->dl_rate = 0;
> +	else
> +		src_priv->ul_rate = 0;
> +
> +	return 0;
> +}
> +

Thanks,
Angelo




_______________________________________________
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] 44+ messages in thread

* Re: [v2 11/17] ASoC: mediatek: mt8186: support gpio control in platform driver
  2022-02-17 13:41 ` [v2 11/17] ASoC: mediatek: mt8186: support gpio " Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-03 15:30     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> This patch add gpio control for all audio interface separately.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 210 ++++++++++++++++++++
>   sound/soc/mediatek/mt8186/mt8186-afe-gpio.h |  19 ++
>   2 files changed, 229 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> 
> diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> new file mode 100644
> index 000000000000..6faec5c95bf3
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> @@ -0,0 +1,210 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// mt8186-afe-gpio.c  --  Mediatek 8186 afe gpio ctrl
> +//
> +// Copyright (c) 2022 MediaTek Inc.
> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> +
> +#include <linux/gpio.h>
> +#include <linux/pinctrl/consumer.h>
> +
> +#include "mt8186-afe-common.h"
> +#include "mt8186-afe-gpio.h"
> +
> +struct pinctrl *aud_pinctrl;
> +
> +enum mt8186_afe_gpio {
> +	MT8186_AFE_GPIO_CLK_MOSI_OFF,
> +	MT8186_AFE_GPIO_CLK_MOSI_ON,
> +	MT8186_AFE_GPIO_CLK_MISO_OFF,
> +	MT8186_AFE_GPIO_CLK_MISO_ON,
> +	MT8186_AFE_GPIO_DAT_MISO_OFF,
> +	MT8186_AFE_GPIO_DAT_MISO_ON,
> +	MT8186_AFE_GPIO_DAT_MOSI_OFF,
> +	MT8186_AFE_GPIO_DAT_MOSI_ON,
> +	MT8186_AFE_GPIO_I2S0_OFF,
> +	MT8186_AFE_GPIO_I2S0_ON,
> +	MT8186_AFE_GPIO_I2S1_OFF,
> +	MT8186_AFE_GPIO_I2S1_ON,
> +	MT8186_AFE_GPIO_I2S2_OFF,
> +	MT8186_AFE_GPIO_I2S2_ON,
> +	MT8186_AFE_GPIO_I2S3_OFF,
> +	MT8186_AFE_GPIO_I2S3_ON,
> +	MT8186_AFE_GPIO_TDM_OFF,
> +	MT8186_AFE_GPIO_TDM_ON,
> +	MT8186_AFE_GPIO_PCM_OFF,
> +	MT8186_AFE_GPIO_PCM_ON,
> +	MT8186_AFE_GPIO_GPIO_NUM
> +};
> +
> +struct audio_gpio_attr {
> +	const char *name;
> +	bool gpio_prepare;
> +	struct pinctrl_state *gpioctrl;
> +};
> +
> +static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM] = {
> +	[MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL},
> +	[MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL},
> +	[MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false, NULL},
> +	[MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false, NULL},
> +	[MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL},
> +	[MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL},
> +	[MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL},
> +	[MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL},
> +	[MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL},
> +	[MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL},
> +	[MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL},
> +	[MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL},
> +	[MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL},
> +	[MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL},
> +	[MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL},
> +	[MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL},
> +	[MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL},
> +	[MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL},
> +	[MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL},
> +	[MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL},
> +};
> +
> +static DEFINE_MUTEX(gpio_request_mutex);
> +
> +int mt8186_afe_gpio_init(struct device *dev)
> +{
> +	int ret;
> +	int i = 0;
> +
> +	aud_pinctrl = devm_pinctrl_get(dev);
> +	if (IS_ERR(aud_pinctrl)) {
> +		ret = PTR_ERR(aud_pinctrl);
> +		dev_info(dev, "%s(), ret %d, cannot get aud_pinctrl!\n",
> +			 __func__, ret);

dev_err()
... and return ret.

> +		return -ENODEV;
> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
> +		aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl,
> +							     aud_gpios[i].name);
> +		if (IS_ERR(aud_gpios[i].gpioctrl)) {
> +			ret = PTR_ERR(aud_gpios[i].gpioctrl);
> +			dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n",
> +				 __func__, aud_gpios[i].name, ret);

dev_err()

P.S.: I think that this function should return ret, at this point, to avoid
       unexpected behavior.


> +		} else {
> +			aud_gpios[i].gpio_prepare = true;
> +		}
> +	}
> +
> +	/* gpio status init */
> +	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 0);
> +	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 1);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init);
> +
> +static int mt8186_afe_gpio_select(struct device *dev,
> +				  enum mt8186_afe_gpio type)
> +{
> +	int ret = 0;
> +
> +	if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) {
> +		dev_info(dev, "%s(), error, invalid gpio type %d\n",
> +			 __func__, type);
> +		return -EINVAL;
> +	}
> +
> +	if (!aud_gpios[type].gpio_prepare) {
> +		dev_info(dev, "%s(), error, gpio type %d not prepared\n",
> +			 __func__, type);
> +		return -EIO;
> +	}
> +
> +	ret = pinctrl_select_state(aud_pinctrl,
> +				   aud_gpios[type].gpioctrl);
> +	if (ret)
> +		dev_info(dev, "%s(), error, can not set gpio type %d\n",
> +			 __func__, type);
> +
> +	return ret;

Please change it like so:

	if (ret) {
		dev_err(dev, "Failed to select picntrl state for type %d\n", type);
		return ret;
	}

	return 0;

> +}
> +
> +static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable)
> +{
> +	if (enable) {
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON);
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON);
> +	} else {
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF);
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable)
> +{
> +	if (enable) {
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON);
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON);
> +	} else {
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF);
> +		mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF);
> +	}
> +
> +	return 0;
> +}
> +
> +int mt8186_afe_gpio_request(struct device *dev, bool enable,
> +			    int dai, int uplink)
> +{

I think that it's more readable and even shorter if you do:

	enum mt8186_afe_gpio sel;

	int ret = -EINVAL;



	mutex_lock(&gpio_request_mutex);



	switch (dai) {

	case MT8186_DAI_ADDA:
		if (uplink)
			ret = mt8186_afe_gpio_adda_ul(dev, enable);
		else
			ret = mt8186_afe_gpio_adda_dl(dev, enable);
		goto unlock;
	case MT8186_DAI_I2S_0:

		sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF;

		break;

	case MT8186_DAI_I2S_1:

		sel = enable ? MT8186_AFE_GPIO_I2S1_ON : MT8186_AFE_GPIO_I2S1_OFF;

		break;



	.................... all other cases ................

	default:

		dev_err(dev, "invalid dai %d\n", dai);

		goto unlock;

	}


	ret = mt8186_afe_gpio_select(dev, sel);


unlock:

	mutex_unlock(&gpio_request_mutex);

	return ret;
}

> +	mutex_lock(&gpio_request_mutex);
> +	switch (dai) {
> +	case MT8186_DAI_ADDA:
> +		if (uplink)
> +			mt8186_afe_gpio_adda_ul(dev, enable);
> +		else
> +			mt8186_afe_gpio_adda_dl(dev, enable);
> +		break;
> +	case MT8186_DAI_I2S_0:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S0_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S0_OFF);
> +		break;
> +	case MT8186_DAI_I2S_1:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S1_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S1_OFF);
> +		break;
> +	case MT8186_DAI_I2S_2:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S2_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S2_OFF);
> +		break;
> +	case MT8186_DAI_I2S_3:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S3_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_I2S3_OFF);
> +		break;
> +	case MT8186_DAI_TDM_IN:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_TDM_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_TDM_OFF);
> +		break;
> +	case MT8186_DAI_PCM:
> +		if (enable)
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_PCM_ON);
> +		else
> +			mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_PCM_OFF);
> +		break;
> +	default:
> +		mutex_unlock(&gpio_request_mutex);
> +		dev_info(dev, "%s(), invalid dai %d\n", __func__, dai);
> +		return -EINVAL;
> +	}
> +	mutex_unlock(&gpio_request_mutex);
> +	return 0;
> +}
> diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> new file mode 100644
> index 000000000000..1ddc27838eb1
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * mt6833-afe-gpio.h  --  Mediatek 6833 afe gpio ctrl definition
> + *
> + * Copyright (c) 2022 MediaTek Inc.
> + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> + */
> +
> +#ifndef _MT8186_AFE_GPIO_H_
> +#define _MT8186_AFE_GPIO_H_
> +
> +struct mtk_base_afe;
> +
> +int mt8186_afe_gpio_init(struct device *dev);
> +
> +int mt8186_afe_gpio_request(struct device *dev, bool enable,
> +			    int dai, int uplink);
> +
> +#endif


_______________________________________________
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] 44+ messages in thread

* Re: [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357
  2022-02-17 13:42 ` [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357 Jiaxin Yu
@ 2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-05  8:58     ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-18 14:54 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 17/02/22 14:42, Jiaxin Yu ha scritto:
> This patch adds support for mt8186 board with mt6366, da7219 and max98357.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>   .../mt8186/mt8186-mt6366-da7219-max98357.c    | 910 ++++++++++++++++++
>   1 file changed, 910 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
> 
> 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..6ba53b8d1e46
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
> @@ -0,0 +1,910 @@
> +// 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/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"
> +
> +#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 mt6366_codec_conf[] = {
> +	{
> +		.dlc = COMP_CODEC_CONF("mt6358-sound"),
> +		.name_prefix = "Mt6366",
> +	},
> +};
> +
> +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, NULL, 0);
> +	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 = 0, 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\n");

Does it really make sense to go on after this failure?

> +
> +	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\n");
> +

I think that going on past this wouldn't make sense as well, as it may result
in unexpected behavior... just return a failure here

> +			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);

and here

> +		}
> +	}
> +

So, you've covered all failure cases already, for which, you can simply
return 0 here.

> +	return ret;
> +}
> +
> +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);
> +				break;
> +			}
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +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_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, NULL, 0);
> +	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_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_info(rtd->dev, "failed to snd_soc_dapm_sync\n");

dev_err()

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
> +				      struct snd_pcm_hw_params *params)
> +{
> +	struct snd_interval *channels = hw_param_interval(params,
> +		SNDRV_PCM_HW_PARAM_CHANNELS);
> +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
> +

dev_dbg()

> +	/* fix BE i2s channel to 2 channel */
> +	channels->min = 2;
> +	channels->max = 2;
> +
> +	/* fix BE i2s format to S32_LE, 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, SNDRV_PCM_FORMAT_S32_LE);
> +
> +	return 0;
> +}
> +
> +static int mt8186_hdmi_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
> +					   struct snd_pcm_hw_params *params)
> +{
> +	struct snd_interval *channels = hw_param_interval(params,
> +		SNDRV_PCM_HW_PARAM_CHANNELS);
> +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
> +

dev_dbg()

> +	/* fix BE i2s channel to 2 channel */
> +	channels->min = 2;
> +	channels->max = 2;
> +
> +	/* fix BE i2s format to S24_LE, 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, SNDRV_PCM_FORMAT_S24_LE);
> +
> +	return 0;
> +}

Besides, I would do the following instead:

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 32bit\n", __func__);



	/* fix BE i2s channel to 2 channel */

	channels->min = 2;

	channels->max = 2;



	/* fix BE i2s format to S32_LE, 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_hdmi_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);

}

... this reduces code duplication!

> +
> +/* FE */
> +SND_SOC_DAILINK_DEFS(playback1,
> +		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
> +		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
> +		     DAILINK_COMP_ARRAY(COMP_EMPTY()));


..snip..

> +static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_card *card = &mt8186_mt6366_da7219_max98357_soc_card;
> +	struct snd_soc_dai_link *dai_link;
> +	struct mt8186_mt6366_da7219_max98357_priv *priv;
> +	struct device_node *platform_node, *hdmi_codec;
> +	int ret, i;
> +
> +	dev_info(&pdev->dev, "%s(), ++\n", __func__);
> +
> +	card->dev = &pdev->dev;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	platform_node = of_parse_phandle(pdev->dev.of_node,
> +					 "mediatek,platform", 0);
> +	if (!platform_node) {
> +		dev_info(&pdev->dev,
> +			 "Property 'platform' missing or invalid\n");

	if (!platform_node)
		return dev_err_probe(&pdev->dev, -EINVAL,
				    "mediatek,platform missing or invalid\n");

> +		return -EINVAL;
> +	}
> +
> +	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
> +				      "mediatek,hdmi-codec", 0);
> +	if (!hdmi_codec) {
> +		dev_info(&pdev->dev,
> +			 "Property 'hdmi' missing or invalid\n");

dev_err()

> +		return -EINVAL;
> +	}
> +
> +	for_each_card_prelinks(card, i, dai_link) {
> +		if (dai_link->platforms->name)
> +			continue;
> +
> +		if (hdmi_codec && strcmp(dai_link->name, "I2S3") == 0) {
> +			dai_link->codecs->of_node = hdmi_codec;
> +			dai_link->ignore = 0;
> +		}
> +
> +		dai_link->platforms->of_node = platform_node;
> +	}
> +
> +	snd_soc_card_set_drvdata(card, priv);
> +
> +	/* init gpio */
> +	ret = mt8186_afe_gpio_init(&pdev->dev);
> +	if (ret)
> +		dev_info(&pdev->dev, "init gpio error\n");

dev_err() and goto end;

> +
> +	dev_info(&pdev->dev, "%s(), devm_snd_soc_register_card\n", __func__);
> +	ret = devm_snd_soc_register_card(&pdev->dev, card);
> +	if (ret)
> +		dev_info(&pdev->dev, "%s snd_soc_register_card fail %d\n",
> +			 __func__, ret);

dev_err_probe()

end:

> +	of_node_put(platform_node);
> +	of_node_put(hdmi_codec);
> +
> +	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",},
> +	{}
> +};
> +#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");



_______________________________________________
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] 44+ messages in thread

* Re: [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document
  2022-02-17 13:42 ` [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document Jiaxin Yu
@ 2022-02-25 16:43   ` Rob Herring
  0 siblings, 0 replies; 44+ messages in thread
From: Rob Herring @ 2022-02-25 16:43 UTC (permalink / raw)
  To: Jiaxin Yu
  Cc: matthias.bgg, linux-arm-kernel, tiwai, devicetree, perex, aaronyu,
	alsa-devel, linux-mediatek, p.zabel, robh+dt, zhangqilong3,
	tzungbi, trevor.wu, lgirdwood, broonie, linux-kernel,
	geert+renesas

On Thu, 17 Feb 2022 21:42:01 +0800, Jiaxin Yu wrote:
> This patch adds mt8186 audio afe document.
> 
> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> ---
>  .../bindings/sound/mt8186-afe-pcm.yaml        | 175 ++++++++++++++++++
>  1 file changed, 175 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
> 

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] 44+ messages in thread

* Re: [v2 09/17] ASoC: mediatek: mt8186: support tdm in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-03 14:10     ` Jiaxin Yu
  2022-03-03 15:08       ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-03 14:10 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch adds mt8186 tdm dai driver.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 713
> > +++++++++++++++++++++
> >   1 file changed, 713 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > new file mode 100644
> > index 000000000000..28dd3661f0e0
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > @@ -0,0 +1,713 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// MediaTek ALSA SoC Audio DAI TDM Control
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/regmap.h>
> > +#include <sound/pcm_params.h>
> > +
> > +#include "mt8186-afe-clk.h"
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-gpio.h"
> > +#include "mt8186-interconnection.h"
> > +
> > +#define TDM_HD_EN_W_NAME "TDM_HD_EN"
> > +#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"
> > +#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"
> > +
> > +struct mtk_afe_tdm_priv {
> > +	unsigned int id;
> > +	unsigned int rate; /* for determine which apll to use */
> > +	unsigned int bck_invert;
> > +	unsigned int lck_invert;
> > +	unsigned int lrck_width;
> > +	unsigned int mclk_id;
> > +	unsigned int mclk_multiple; /* according to sample rate */
> > +	unsigned int mclk_rate;
> > +	unsigned int mclk_apll;
> > +	unsigned int tdm_mode;
> > +	unsigned int data_mode;
> > +	unsigned int slave_mode;
> > +	unsigned int low_jitter_en;
> > +};
> > +
> > +enum {
> > +	TDM_IN_I2S = 0,
> > +	TDM_IN_LJ = 1,
> > +	TDM_IN_RJ = 2,
> > +	TDM_IN_DSP_A = 4,
> > +	TDM_IN_DSP_B = 5,
> > +};
> > +
> > +enum {
> > +	TDM_DATA_ONE_PIN = 0,
> > +	TDM_DATA_MULTI_PIN,
> > +};
> > +
> > +enum {
> > +	TDM_BCK_NON_INV = 0,
> > +	TDM_BCK_INV = 1,
> > +};
> > +
> > +enum {
> > +	TDM_LCK_NON_INV = 0,
> > +	TDM_LCK_INV = 1,
> > +};
> > +
> > +static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,
> > +				       unsigned int mode)
> > +{
> > +	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
> > +		return 0;
> > +	else
> 
> Drop the "else"
> 
> > +		return snd_pcm_format_physical_width(format) - 1;
> > +}
> > +
> > +static unsigned int get_tdm_ch_fixup(unsigned int channels)
> > +{
> > +	if (channels > 4)
> > +		return 8;
> > +	else if (channels > 2)
> > +		return 4;
> > +	else
> 
> Same here
> 
> > +		return 2;
> > +}
> > +
> > +static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
> > +					 unsigned int channels)
> > +{
> > +	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
> > +		return get_tdm_ch_fixup(channels);
> > +	else
> 
> ...and same here
> 
> > +		return 2;
> > +}
> > +
> > +enum {
> > +	SUPPLY_SEQ_APLL,
> > +	SUPPLY_SEQ_TDM_MCK_EN,
> > +	SUPPLY_SEQ_TDM_HD_EN,
> > +	SUPPLY_SEQ_TDM_EN,
> > +};
> > +
> > +static int get_tdm_id_by_name(const char *name)
> > +{
> > +	return MT8186_DAI_TDM_IN;
> > +}
> > +
> > +static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
> > +			    struct snd_kcontrol *kcontrol,
> > +			    int event)
> > +{
> > +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w-
> > >dapm);
> > +	struct mtk_base_afe *afe =
> > snd_soc_component_get_drvdata(cmpnt);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
> > +		__func__, w->name, event);
> > +
> > +	switch (event) {
> > +	case SND_SOC_DAPM_PRE_PMU:
> > +		mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id,
> > 0);
> > +		break;
> > +	case SND_SOC_DAPM_POST_PMD:
> > +		mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id,
> > 0);
> > +		break;
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
> > +				struct snd_kcontrol *kcontrol,
> > +				int event)
> > +{
> > +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w-
> > >dapm);
> > +	struct mtk_base_afe *afe =
> > snd_soc_component_get_drvdata(cmpnt);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> 
> dev_err() - please fix all other instances
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
> > +		__func__, w->name, event, dai_id);
> > +
> > +	switch (event) {
> > +	case SND_SOC_DAPM_PRE_PMU:
> > +		mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv-
> > >mclk_rate);
> > +		break;
> > +	case SND_SOC_DAPM_POST_PMD:
> > +		tdm_priv->mclk_rate = 0;
> > +		mt8186_mck_disable(afe, tdm_priv->mclk_id);
> > +		break;
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> 
> ...snip...
> 
> > +
> > +static int mt8186_tdm_hd_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 dai_id = get_tdm_id_by_name(kcontrol->id.name);
> > +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
> > +	struct soc_enum *e = (struct soc_enum *)kcontrol-
> > >private_value;
> > +	int hd_en;
> > +
> > +	if (ucontrol->value.enumerated.item[0] >= e->items)
> > +		return -EINVAL;
> > +
> > +	hd_en = ucontrol->value.integer.value[0];
> > +
> > +	dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
> > +		 __func__, kcontrol->id.name, hd_en);
> 
> dev_dbg()
> 
> > +
> > +	if (!tdm_priv) {
> > +		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	tdm_priv->low_jitter_en = hd_en;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
> > +	SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],
> > +		     mt8186_tdm_hd_get, mt8186_tdm_hd_set),
> > +};
> > +
> > +static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
> > +	{"TDM IN", NULL, "aud_tdm_clk"},
> > +	{"TDM IN", NULL, "TDM_EN"},
> > +	{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},
> > +	{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME,
> > mtk_afe_tdm_apll_connect},
> > +	{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME,
> > mtk_afe_tdm_apll_connect},
> > +
> > +	{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},
> > +	{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME,
> > mtk_afe_tdm_mclk_apll_connect},
> > +	{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME,
> > mtk_afe_tdm_mclk_apll_connect},
> > +
> > +	/* allow tdm on without codec on */
> > +	{"TDM IN", NULL, "TDM_In_Mux"},
> > +	{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},
> > +};
> > +
> > +/* dai ops */
> > +static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
> > +				struct mtk_afe_tdm_priv *tdm_priv,
> > +				int freq)
> > +{
> > +	int apll;
> > +	int apll_rate;
> > +
> > +	apll = mt8186_get_apll_by_rate(afe, freq);
> > +	apll_rate = mt8186_get_apll_rate(afe, apll);
> > +
> > +	if (!freq || freq > apll_rate) {
> > +		dev_info(afe->dev,
> > +			 "%s(), freq(%d Hz) invalid\n", __func__,
> > freq);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (apll_rate % freq != 0) {
> > +		dev_info(afe->dev,
> > +			 "%s(), APLL cannot generate %d Hz", __func__,
> > freq);
> > +		return -EINVAL;
> > +	}
> > +
> > +	tdm_priv->mclk_rate = freq;
> > +	tdm_priv->mclk_apll = apll;
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dai_tdm_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);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int tdm_id = dai->id;
> > +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
> > +	unsigned int tdm_mode = tdm_priv->tdm_mode;
> > +	unsigned int data_mode = tdm_priv->data_mode;
> > +	unsigned int rate = params_rate(params);
> > +	unsigned int channels = params_channels(params);
> > +	snd_pcm_format_t format = params_format(params);
> > +	unsigned int bit_width =
> > +		snd_pcm_format_physical_width(format);
> > +	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?
> > +		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
> > +	unsigned int lrck_width =
> > +		get_tdm_lrck_width(format, tdm_mode);
> > +	unsigned int tdm_con = 0;
> > +	bool slave_mode = tdm_priv->slave_mode;
> > +	bool lrck_inv = tdm_priv->lck_invert;
> > +	bool bck_inv = tdm_priv->bck_invert;
> > +	unsigned int ctrl_reg;
> > +	unsigned int ctrl_mask;
> > +	unsigned int tran_rate;
> > +	unsigned int tran_relatch_rate;
> > +
> > +	if (tdm_priv)
> > +		tdm_priv->rate = rate;
> > +	else
> > +		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> > +
> > +	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);
> > +	}
> > +
> > +	/* ETDM_IN1_CON0 */
> > +	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
> > +	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
> > +	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
> > +	tdm_con |= (bit_width - 1) <<
> > ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
> > +	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;
> > +	/* default disable sync mode */
> > +	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;
> 
> 0 << (anything) == 0
> 
> (number |= 0) == number
> 
> Is this a mistake, or are you really doing nothing here?
> 
No, this is just to emphasize the need to set this bit to 0.
It really do nothing here, just link a reminder.
Can I keep this sentence?
> 
> > +	/* relatch fix to h26m */
> > +	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
> > +
> > +	ctrl_reg = ETDM_IN1_CON0;
> > +	ctrl_mask = ETDM_IN_CON0_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> > +
> > +	/* ETDM_IN1_CON1 */
> > +	tdm_con = 0;
> > +	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
> > +	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
> > +	tdm_con |= (lrck_width - 1) <<
> > ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
> > +
> > +	ctrl_reg = ETDM_IN1_CON1;
> > +	ctrl_mask = ETDM_IN_CON1_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> 
> You don't need the ctrl_reg, nor ctrl_mask variables...
I was trying to avoid a line of more than 80 words, so I shortened the
number of words through variables.

> 
> regmap_update_bits(afe->regmap, ETDM_IN1_CON1,
> ETDM_IN_CON1_CTRL_MASK, tdm_con);
> 
> > +
> > +	/* ETDM_IN1_CON3 */
> > +	tdm_con = 0;
> > +	tdm_con = ETDM_IN_CON3_FS(tran_rate);
> > +
> > +	ctrl_reg = ETDM_IN1_CON3;
> > +	ctrl_mask = ETDM_IN_CON3_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> 
> same here
> 
> > +
> > +	/* ETDM_IN1_CON4 */
> > +	tdm_con = 0;
> > +	tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);
> > +	if (slave_mode) {
> > +		if (lrck_inv)
> > +			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;
> > +		if (bck_inv)
> > +			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;
> > +	} else {
> > +		if (lrck_inv)
> > +			tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;
> > +		if (bck_inv)
> > +			tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;
> > +	}
> > +
> > +	ctrl_reg = ETDM_IN1_CON4;
> > +	ctrl_mask = ETDM_IN_CON4_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> 
> and here
> 
> > +
> > +	/* ETDM_IN1_CON2 */
> > +	tdm_con = 0;
> > +	if (data_mode == TDM_DATA_MULTI_PIN) {
> > +		tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;
> > +		tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);
> > +	}
> > +
> > +	ctrl_reg = ETDM_IN1_CON2;
> > +	ctrl_mask = ETDM_IN_CON2_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> 
> and here
> 
> > +
> > +	/* ETDM_IN1_CON8 */
> > +	tdm_con = 0;
> > +	if (slave_mode) {
> > +		tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
> > +		tdm_con |= 0 <<
> > ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;
> > +		tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);
> > +	} else {
> > +		tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
> > +	}
> > +
> > +	ctrl_reg = ETDM_IN1_CON8;
> > +	ctrl_mask = ETDM_IN_CON8_CTRL_MASK;
> > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
> 
> finally, here too.
> 
> > +
> > +	return 0;
> > +}
> > +
> 
> Thanks,
> ANgelo
_______________________________________________
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] 44+ messages in thread

* Re: [v2 09/17] ASoC: mediatek: mt8186: support tdm in platform driver
  2022-03-03 14:10     ` Jiaxin Yu
@ 2022-03-03 15:08       ` AngeloGioacchino Del Regno
  2022-03-03 17:39         ` Jiaxin Yu
  0 siblings, 1 reply; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-03-03 15:08 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 03/03/22 15:10, Jiaxin Yu ha scritto:
> On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
>> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
>>> This patch adds mt8186 tdm dai driver.
>>>
>>> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>> ---
>>>    sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 713
>>> +++++++++++++++++++++
>>>    1 file changed, 713 insertions(+)
>>>    create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
>>>
>>> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
>>> b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
>>> new file mode 100644
>>> index 000000000000..28dd3661f0e0
>>> --- /dev/null
>>> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
>>> @@ -0,0 +1,713 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +//
>>> +// MediaTek ALSA SoC Audio DAI TDM Control
>>> +//
>>> +// Copyright (c) 2022 MediaTek Inc.
>>> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>> +

..snip..

>>> +
>>> +static int mtk_dai_tdm_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);
>>> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
>>> +	int tdm_id = dai->id;
>>> +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
>>> +	unsigned int tdm_mode = tdm_priv->tdm_mode;
>>> +	unsigned int data_mode = tdm_priv->data_mode;
>>> +	unsigned int rate = params_rate(params);
>>> +	unsigned int channels = params_channels(params);
>>> +	snd_pcm_format_t format = params_format(params);
>>> +	unsigned int bit_width =
>>> +		snd_pcm_format_physical_width(format);
>>> +	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?
>>> +		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
>>> +	unsigned int lrck_width =
>>> +		get_tdm_lrck_width(format, tdm_mode);
>>> +	unsigned int tdm_con = 0;
>>> +	bool slave_mode = tdm_priv->slave_mode;
>>> +	bool lrck_inv = tdm_priv->lck_invert;
>>> +	bool bck_inv = tdm_priv->bck_invert;
>>> +	unsigned int ctrl_reg;
>>> +	unsigned int ctrl_mask;
>>> +	unsigned int tran_rate;
>>> +	unsigned int tran_relatch_rate;
>>> +
>>> +	if (tdm_priv)
>>> +		tdm_priv->rate = rate;
>>> +	else
>>> +		dev_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
>>> +
>>> +	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);
>>> +	}
>>> +
>>> +	/* ETDM_IN1_CON0 */
>>> +	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
>>> +	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
>>> +	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
>>> +	tdm_con |= (bit_width - 1) <<
>>> ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
>>> +	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;
>>> +	/* default disable sync mode */
>>> +	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;
>>
>> 0 << (anything) == 0
>>
>> (number |= 0) == number
>>
>> Is this a mistake, or are you really doing nothing here?
>>
> No, this is just to emphasize the need to set this bit to 0.
> It really do nothing here, just link a reminder.
> Can I keep this sentence?

If, in your judgement, it is very important to have a reminder about that
bit having to be unset, then add a comment in the code saying so.
Don't simply comment out the statement as it is.

A good way would be something like
/* sync mode bit has to be unset because this that reason, otherwise X happens */

>>
>>> +	/* relatch fix to h26m */
>>> +	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
>>> +
>>> +	ctrl_reg = ETDM_IN1_CON0;
>>> +	ctrl_mask = ETDM_IN_CON0_CTRL_MASK;
>>> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
>>> +
>>> +	/* ETDM_IN1_CON1 */
>>> +	tdm_con = 0;
>>> +	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
>>> +	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
>>> +	tdm_con |= (lrck_width - 1) <<
>>> ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
>>> +
>>> +	ctrl_reg = ETDM_IN1_CON1;
>>> +	ctrl_mask = ETDM_IN_CON1_CTRL_MASK;
>>> +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask, tdm_con);
>>
>> You don't need the ctrl_reg, nor ctrl_mask variables...
> I was trying to avoid a line of more than 80 words, so I shortened the
> number of words through variables.
> 

Yes, I know, I did understand what you were trying to do...
...but it's fine to go past 80: in this case this would be 88 columns,
which is still ok to have!

And note, this is the case with all of similar calls present in this function,
that's why I said that you don't need these two variables! :)

Thank you,
Angelo



_______________________________________________
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] 44+ messages in thread

* Re: [v2 10/17] ASoC: mediatek: mt8186: support audio clock control in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-03 15:16     ` Jiaxin Yu
  2022-03-03 15:17     ` Jiaxin Yu
  1 sibling, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-03 15:16 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch add audio clock control with CCF interface.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 719
> > +++++++++++++++++++++
> >   sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 210 ++++++
> >   2 files changed, 929 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > new file mode 100644
> > index 000000000000..14f64b935619
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > @@ -0,0 +1,719 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// mt8186-afe-clk.c  --  Mediatek 8186 afe clock ctrl
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/clk.h>
> > +#include <linux/regmap.h>
> > +#include <linux/mfd/syscon.h>
> > +
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-clk.h"
> > +#include "mt8186-audsys-clk.h"
> > +
> > +static DEFINE_MUTEX(mutex_request_dram);
> > +
> > +static const char *aud_clks[CLK_NUM] = {
> > +	[CLK_AFE] = "aud_afe_clk",
> > +	[CLK_DAC] = "aud_dac_clk",
> > +	[CLK_DAC_PREDIS] = "aud_dac_predis_clk",
> > +	[CLK_ADC] = "aud_adc_clk",
> > +	[CLK_TML] = "aud_tml_clk",
> > +	[CLK_APLL22M] = "aud_apll22m_clk",
> > +	[CLK_APLL24M] = "aud_apll24m_clk",
> > +	[CLK_APLL1_TUNER] = "aud_apll_tuner_clk",
> > +	[CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
> > +	[CLK_TDM] = "aud_tdm_clk",
> > +	[CLK_NLE] = "aud_nle_clk",
> > +	[CLK_DAC_HIRES] = "aud_dac_hires_clk",
> > +	[CLK_ADC_HIRES] = "aud_adc_hires_clk",
> > +	[CLK_I2S1_BCLK] = "aud_i2s1_bclk",
> > +	[CLK_I2S2_BCLK] = "aud_i2s2_bclk",
> > +	[CLK_I2S3_BCLK] = "aud_i2s3_bclk",
> > +	[CLK_I2S4_BCLK] = "aud_i2s4_bclk",
> > +	[CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc",
> > +	[CLK_GENERAL1_ASRC] = "aud_general1_asrc",
> > +	[CLK_GENERAL2_ASRC] = "aud_general2_asrc",
> > +	[CLK_ADC_HIRES_TML] = "aud_adc_hires_tml",
> > +	[CLK_ADDA6_ADC] = "aud_adda6_adc",
> > +	[CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> > +	[CLK_3RD_DAC] = "aud_3rd_dac",
> > +	[CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis",
> > +	[CLK_3RD_DAC_TML] = "aud_3rd_dac_tml",
> > +	[CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires",
> > +	[CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk",
> > +	[CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk",
> > +	[CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
> > +	[CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk",
> > +	[CLK_MUX_AUDIO] = "top_mux_audio",
> > +	[CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int",
> > +	[CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4",
> > +	[CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
> > +	[CLK_TOP_APLL1_CK] = "top_apll1_ck",
> > +	[CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
> > +	[CLK_TOP_APLL2_CK] = "top_apll2_ck",
> > +	[CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
> > +	[CLK_TOP_APLL1_D8] = "top_apll1_d8",
> > +	[CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
> > +	[CLK_TOP_APLL2_D8] = "top_apll2_d8",
> > +	[CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h",
> > +	[CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
> > +	[CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
> > +	[CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
> > +	[CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
> > +	[CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel",
> > +	[CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
> > +	[CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
> > +	[CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
> > +	[CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
> > +	[CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm",
> > +	[CLK_CLK26M] = "top_clk26m_clk",
> > +};
> > +
> > +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe,
> > +				    int clk_id)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
> > +			     afe_priv->clk[clk_id]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS],
> > +			 aud_clks[clk_id], ret);
> 
> 		dev_err(......)
> 		return ret;
> 
> > +	}
> > +
> 
> 	return 0;
> 
> > +	return ret;
> > +}
> > +
> > +static int apll1_mux_setting(struct mtk_base_afe *afe, bool
> > enable)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	if (enable) {
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_1]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> > +				     afe_priv->clk[CLK_TOP_APLL1_CK]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > +				 aud_clks[CLK_TOP_APLL1_CK], ret);
> 
> dev_err()
> 
> > +			goto EXIT;
> > +		}
> > +
> > +		/* 180.6336 / 8 = 22.5792MHz */
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1],
> > +				     afe_priv->clk[CLK_TOP_APLL1_D8]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1],
> > +				 aud_clks[CLK_TOP_APLL1_D8], ret);
> > +			goto EXIT;
> > +		}
> > +	} else {
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1]);
> > +
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_1]);
> > +	}
> > +EXIT:
> > +	return 0;
> 
> You're returning 0 even in error cases, this is wrong.
Thanka for your careful review. I will fix this issue in next version.

> 
> > +}
> > +
> > +static int apll2_mux_setting(struct mtk_base_afe *afe, bool
> > enable)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	if (enable) {
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_2]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> > +				     afe_priv->clk[CLK_TOP_APLL2_CK]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > +				 aud_clks[CLK_TOP_APLL2_CK], ret);
> > +			goto EXIT;
> > +		}
> > +
> > +		/* 196.608 / 8 = 24.576MHz */
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2],
> > +				     afe_priv->clk[CLK_TOP_APLL2_D8]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2],
> > +				 aud_clks[CLK_TOP_APLL2_D8], ret);
> > +			goto EXIT;
> > +		}
> > +	} else {
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2]);
> > +
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_2]);
> > +	}
> > +
> > +EXIT:
> > +	return 0;
> > +}
> > +
> > +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +	int i;
> > +
> > +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) {
> > +		ret = clk_prepare_enable(afe_priv->clk[i]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[i], ret);
> 
> dev_err()
> 
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int i;
> > +
> > +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++)
> > +		clk_disable_unprepare(afe_priv->clk[i]);
> > +}
> > +
> > +int mt8186_afe_enable_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);
> 
> dev_err()
> 
> > +		goto CLK_INFRA_SYS_AUDIO_ERR;
> 
> also, please use lower-case labels (here and everywhere else).
> 
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret);
> > +		goto CLK_INFRA_AUDIO_26M_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIO], ret);
> > +		goto CLK_MUX_AUDIO_ERR;
> > +	}
> > +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
> > +			     afe_priv->clk[CLK_CLK26M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIO],
> > +			 aud_clks[CLK_CLK26M], ret);
> > +		goto CLK_MUX_AUDIO_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe,
> > +					      CLK_TOP_MAINPLL_D2_D4);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H],
> > +			     afe_priv->clk[CLK_TOP_APLL2_CK]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_TOP_MUX_AUDIO_H],
> > +			 aud_clks[CLK_TOP_APLL2_CK], ret);
> > +		goto CLK_MUX_AUDIO_H_PARENT_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_AFE], ret);
> > +		goto CLK_AFE_ERR;
> > +	}
> > +
> > +	return 0;
> > +
> > +CLK_AFE_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> > +CLK_MUX_AUDIO_H_PARENT_ERR:
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +CLK_MUX_AUDIO_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> > +CLK_INFRA_SYS_AUDIO_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +CLK_INFRA_AUDIO_26M_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_afe_disable_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +}
> > +
> > +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* set audio int bus to 26M */
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> 
> dev_err() - here and for the other similar instances.
> 
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +
> > +	return 0;
> > +
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	return ret;
> > +}
> > +
> > +int mt8186_afe_resume_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* set audio int bus to normal working clock */
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe,
> > +					      CLK_TOP_MAINPLL_D2_D4);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +
> > +	return 0;
> > +
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	return ret;
> > +}
> > +
> > +int mt8186_apll1_enable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* setting for APLL */
> > +	apll1_mux_setting(afe, true);
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL22M], ret);
> > +		goto ERR_CLK_APLL22M;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL1_TUNER], ret);
> > +		goto ERR_CLK_APLL1_TUNER;
> > +	}
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
> > +			   0x0000FFF7, 0x00000832);
> 
> no leading zeroes - and without them, it fits in one line.
> 
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_22M_ON_MASK_SFT,
> > +			   0x1 << AFE_22M_ON_SFT);
> 
> BIT() macro please
> 
> > +
> > +	return 0;
> > +
> > +ERR_CLK_APLL1_TUNER:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> > +ERR_CLK_APLL22M:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_apll1_disable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_22M_ON_MASK_SFT,
> > +			   0x0 << AFE_22M_ON_SFT);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> > +
> > +	apll1_mux_setting(afe, false);
> > +}
> > +
> > +int mt8186_apll2_enable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* setting for APLL */
> > +	apll2_mux_setting(afe, true);
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL24M], ret);
> > +		goto ERR_CLK_APLL24M;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL2_TUNER], ret);
> > +		goto ERR_CLK_APLL2_TUNER;
> > +	}
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
> > +			   0x0000FFF7, 0x00000634);
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_24M_ON_MASK_SFT,
> > +			   0x1 << AFE_24M_ON_SFT);
> > +
> > +	return 0;
> > +
> > +ERR_CLK_APLL2_TUNER:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> > +ERR_CLK_APLL24M:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_apll2_disable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_24M_ON_MASK_SFT,
> > +			   0x0 << AFE_24M_ON_SFT);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> > +
> > +	apll2_mux_setting(afe, false);
> > +}
> > +
> > +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll)
> > +{
> > +	return (apll == MT8186_APLL1) ? 180633600 : 196608000;
> > +}
> > +
> > +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
> > +{
> > +	return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1;
> > +}
> > +
> > +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char
> > *name)
> > +{
> > +	if (strcmp(name, APLL1_W_NAME) == 0)
> > +		return MT8186_APLL1;
> > +	else
> > +		return MT8186_APLL2;
> > +}
> > +
> > +/* mck */
> > +struct mt8186_mck_div {
> > +	int m_sel_id;
> > +	int div_clk_id;
> > +	/* below will be deprecated */
> > +	int div_pdn_reg;
> > +	int div_pdn_mask_sft;
> > +	int div_reg;
> > +	int div_mask_sft;
> > +	int div_mask;
> > +	int div_sft;
> > +	int div_msb_reg;
> > +	int div_msb_mask_sft;
> > +	int div_msb_mask;
> > +	int div_msb_sft;
> > +	int div_apll_sel_reg;
> > +	int div_apll_sel_mask_sft;
> > +	int div_apll_sel_sft;
> > +	int div_inv_reg;
> > +	int div_inv_mask_sft;
> 
> 
> 
> *_reg fits in u16.
> *_mask_sft, *_sel_sft can be u32.
> 
> This would be nice to avoid wasting memory for variables that are
> larger than
> needed; besides, you're also using a signed type for a number that
> may not
> ever be less than zero.
> 
Yes, your suggestion is very correct. But I will remove some member fo
this strcut because they are not needed in audio driver.

> 
> > +};
> > +
> > +static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = {
> > +	[MT8186_I2S0_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S0_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV0,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV0_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV0_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV0_MASK,
> > +		.div_sft = APLL12_CK_DIV0_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S0_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S0_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S1_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S1_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV1,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV1_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV1_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV1_MASK,
> > +		.div_sft = APLL12_CK_DIV1_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S1_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S1_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S2_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S2_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV2,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV2_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV2_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV2_MASK,
> > +		.div_sft = APLL12_CK_DIV2_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S2_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S2_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S4_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S4_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV4,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV4_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV4_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV4_MASK,
> > +		.div_sft = APLL12_CK_DIV4_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S4_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S4_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_TDM_MCK] = {
> > +		.m_sel_id = CLK_TOP_TDM_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV_TDM,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV_TDM_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_3,
> > +		.div_mask_sft = APLL12_CK_DIV_TDM_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV_TDM_MASK,
> > +		.div_sft = APLL12_CK_DIV_TDM_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_TDM_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_TDM_MCK_SEL_SFT,
> > +	},
> > +};
> > +
> > +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int
> > rate)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int apll = mt8186_get_apll_by_rate(afe, rate);
> > +	int apll_clk_id = apll == MT8186_APLL1 ?
> > +			  CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
> > +	int m_sel_id = mck_div[mck_id].m_sel_id;
> > +	int div_clk_id = mck_div[mck_id].div_clk_id;
> > +	int ret;
> > +
> > +	/* select apll */
> > +	if (m_sel_id >= 0) {
> > +		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[m_sel_id], ret);
> 
> dev_err()
> 
> > +			return ret;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[m_sel_id],
> > +				     afe_priv->clk[apll_clk_id]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[m_sel_id],
> > +				aud_clks[apll_clk_id], ret);
> 
> again
> 
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	/* enable div, set rate */
> > +	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s(), clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[div_clk_id], ret);
> 
> again
> 
> > +		return ret;
> > +	}
> > +	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s(), clk_set_rate %s, rate %d,
> > fail %d\n",
> > +			 __func__, aud_clks[div_clk_id],
> > +			 rate, ret);
> 
> again - and this fits in two lines.
> 
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int m_sel_id = mck_div[mck_id].m_sel_id;
> > +	int div_clk_id = mck_div[mck_id].div_clk_id;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
> > +	if (m_sel_id >= 0)
> > +		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
> > +}
> > +
> > +int mt8186_init_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	struct device_node *of_node = afe->dev->of_node;
> > +	int i = 0;
> > +
> > +	 mt8186_audsys_clk_register(afe);
> 
> Fix indentation please
> 
> > +
> > +	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM,
> > sizeof(*afe_priv->clk),
> > +				     GFP_KERNEL);
> > +	if (!afe_priv->clk)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < CLK_NUM; i++) {
> > +		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
> > +		if (IS_ERR(afe_priv->clk[i])) {
> > +			dev_info(afe->dev, "%s devm_clk_get %s fail,
> > ret %ld\n",
> > +				 __func__,
> > +				 aud_clks[i], PTR_ERR(afe_priv-
> > >clk[i]));
> > +			afe_priv->clk[i] = NULL;
> > +		}
> > +	}
> > +
> > +	afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node,
> > +							       "mediate
> > k,apmixedsys");
> > +	if (IS_ERR(afe_priv->apmixedsys)) {
> > +		dev_err(afe->dev, "%s() Cannot find apmixedsys
> > controller: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->apmixedsys));
> > +		return PTR_ERR(afe_priv->apmixedsys);
> > +	}
> > +
> > +	afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node,
> > +							     "mediatek,
> > topckgen");
> > +	if (IS_ERR(afe_priv->topckgen)) {
> > +		dev_err(afe->dev, "%s() Cannot find topckgen
> > controller: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->topckgen));
> > +		return PTR_ERR(afe_priv->topckgen);
> > +	}
> > +
> > +	afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node,
> > +							     "mediatek,
> > infracfg");
> > +	if (IS_ERR(afe_priv->infracfg)) {
> > +		dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->infracfg));
> > +		return PTR_ERR(afe_priv->infracfg);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_deinit_clock(struct mtk_base_afe *afe)
> > +{
> > +	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
> > new file mode 100644
> > index 000000000000..3ce7a9a24d4a
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> > @@ -0,0 +1,210 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + *
> > + * mt8186-afe-clk.h  --  Mediatek 8186 afe clock ctrl definition
> > + *
> > + * Copyright (c) 2022 MediaTek Inc.
> > + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > + */
> > +
> > +#ifndef _MT8186_AFE_CLOCK_CTRL_H_
> > +#define _MT8186_AFE_CLOCK_CTRL_H_
> > +
> > +#define PERI_BUS_DCM_CTRL 0x0074
> > +#define MODULE_SW_CG_1_STA 0x0094
> > +#define MODULE_SW_CG_2_STA 0x00ac
> > +#define CLK_CFG_7 0x0080
> > +#define CLK_CFG_8 0x0090
> > +#define CLK_CFG_11 0x00c0
> > +#define CLK_CFG_12 0x00d0
> > +#define CLK_CFG_13 0x00e0
> > +#define CLK_CFG_15 0x0100
> > +#define AP_PLL_CON3 0x0014
> > +#define APLL1_CON4 0x0328
> > +#define APLL1_TUNER_CON0 0x0040
> > +#define APLL2_CON4 0x033c
> > +#define APLL2_TUNER_CON0 0x0044
> > +
> > +#define AP_PLL_CON5 0x0014
> > +#define APLL1_CON0 0x02c0
> > +#define APLL1_CON1 0x02c4
> > +#define APLL1_CON2 0x02c8
> > +#define APLL1_CON3 0x02cc
> > +#define APLL1_PWR_CON0 0x02d0
> > +
> > +#define APLL2_CON0 0x02d4
> > +#define APLL2_CON1 0x02d8
> > +#define APLL2_CON2 0x02dc
> > +#define APLL2_CON3 0x02e0
> > +#define APLL2_PWR_CON0 0x02e4
> > +
> > +#define APMIXEDSYS_MAX_LENGTH APLL2_PWR_CON0
> > +
> > +#define CLK_CFG_6 0x0080
> > +#define CLK_AUDDIV_0 0x0320
> > +#define CLK_AUDDIV_1 0x0324
> > +#define CLK_AUDDIV_2 0x0328
> > +#define CKSYS_AUD_TOP_CFG 0x032c
> > +#define CKSYS_AUD_TOP_MON 0x0330
> > +#define CLK_AUDDIV_3 0x0334
> > +
> > +#define CLK_MAX_LENGTH CLK_AUDDIV_3
> > +
> > +/* CLK_CFG_6 */
> > +#define CLK_AUD_INTBUS_SEL_SFT              16
> > +#define CLK_AUD_INTBUS_SEL_MASK             0x3
> > +#define CLK_AUD_INTBUS_SEL_MASK_SFT         (0x3 << 16)
> 
> #define CLK_AUD_INTBUS_SEL_MASK_SFT		GENMASK(23, 22)
> 
I will remove these define because they are not used in audio driver.

> > +
> > +/* CLK_AUDDIV_0 */
> > +#define APLL12_DIV0_PDN_SFT                0
> > +#define APLL12_DIV0_PDN_MASK               0x1
> > +#define APLL12_DIV0_PDN_MASK_SFT           (0x1 << 0)
> 
> BIT() macro please
same

> 
> #define APLL12_DIV0_PDN_MASK_SFT		BIT(0)
> 
> also, using tabulations instead of spaces is nicer.
> 
> > +#define APLL12_DIV1_PDN_SFT                1
> > +#define APLL12_DIV1_PDN_MASK               0x1
> > +#define APLL12_DIV1_PDN_MASK_SFT           (0x1 << 1)
> 
> Of course, BIT() macro again, here and everywhere else applicable.
Yes, you are right.

> 
> > +#define APLL12_DIV2_PDN_SFT                2
> > +#define APLL12_DIV2_PDN_MASK               0x1
> > +#define APLL12_DIV2_PDN_MASK_SFT           (0x1 << 2)
> > +#define APLL12_DIV4_PDN_SFT                3
> > +#define APLL12_DIV4_PDN_MASK               0x1
> > +#define APLL12_DIV4_PDN_MASK_SFT           (0x1 << 3)
> > +#define APLL12_DIV_TDM_PDN_SFT             4
> > +#define APLL12_DIV_TDM_PDN_MASK            0x1
> > +#define APLL12_DIV_TDM_PDN_MASK_SFT        (0x1 << 4)
> > +#define APLL_I2S0_MCK_SEL_SFT              16
> > +#define APLL_I2S0_MCK_SEL_MASK             0x1
> > +#define APLL_I2S0_MCK_SEL_MASK_SFT         (0x1 << 16)
> > +#define APLL_I2S1_MCK_SEL_SFT              17
> > +#define APLL_I2S1_MCK_SEL_MASK             0x1
> > +#define APLL_I2S1_MCK_SEL_MASK_SFT         (0x1 << 17)
> > +#define APLL_I2S2_MCK_SEL_SFT              18
> > +#define APLL_I2S2_MCK_SEL_MASK             0x1
> > +#define APLL_I2S2_MCK_SEL_MASK_SFT         (0x1 << 17)
> > +#define APLL_I2S4_MCK_SEL_SFT              19
> > +#define APLL_I2S4_MCK_SEL_MASK             0x1
> > +#define APLL_I2S4_MCK_SEL_MASK_SFT         (0x1 << 19)
> > +#define APLL_TDM_MCK_SEL_SFT               20
> > +#define APLL_TDM_MCK_SEL_MASK              0x1
> > +#define APLL_TDM_MCK_SEL_MASK_SFT          (0x1 << 20)
> > +
> > +/* CLK_AUDDIV_2 */
> > +#define APLL12_CK_DIV0_SFT                 0
> > +#define APLL12_CK_DIV0_MASK                0xff
> > +#define APLL12_CK_DIV0_MASK_SFT            (0xff << 0)
> 
> GENMASK(7, 0)
> 
> > +#define APLL12_CK_DIV1_SFT                 8
> > +#define APLL12_CK_DIV1_MASK                0xff
> > +#define APLL12_CK_DIV1_MASK_SFT            (0xff << 8)
> 
> GENMASK(15, 8)
> 
> > +#define APLL12_CK_DIV2_SFT                 16
> > +#define APLL12_CK_DIV2_MASK                0xff
> > +#define APLL12_CK_DIV2_MASK_SFT            (0xff << 16)
> 
> Fix all the others too :))
> 
> > +#define APLL12_CK_DIV4_SFT                 24
> > +#define APLL12_CK_DIV4_MASK                0xff
> > +#define APLL12_CK_DIV4_MASK_SFT            (0xff << 24)
> > +
> > +/* CLK_AUDDIV_3 */
> > +#define APLL12_CK_DIV_TDM_SFT              0
> > +#define APLL12_CK_DIV_TDM_MASK             0xff
> > +#define APLL12_CK_DIV_TDM_MASK_SFT         (0xff << 0)
> > +
> > +/* AUD_TOP_CFG */
> > +#define AUD_TOP_CFG_SFT                    0
> > +#define AUD_TOP_CFG_MASK                   0xffffffff
> > +#define AUD_TOP_CFG_MASK_SFT               (0xffffffff << 0)
> 
> This is GENMASK(31, 0) for both MASK and MASK_SFT
> 
> > +
> > +/* AUD_TOP_MON */
> > +#define AUD_TOP_MON_SFT                    0
> > +#define AUD_TOP_MON_MASK                   0xffffffff
> > +#define AUD_TOP_MON_MASK_SFT               (0xffffffff << 0)
> 
> same here
> 
> 
> 
> Regards,
> Angelo
_______________________________________________
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] 44+ messages in thread

* Re: [v2 10/17] ASoC: mediatek: mt8186: support audio clock control in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
  2022-03-03 15:16     ` Jiaxin Yu
@ 2022-03-03 15:17     ` Jiaxin Yu
  1 sibling, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-03 15:17 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch add audio clock control with CCF interface.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 719
> > +++++++++++++++++++++
> >   sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 210 ++++++
> >   2 files changed, 929 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > new file mode 100644
> > index 000000000000..14f64b935619
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
> > @@ -0,0 +1,719 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// mt8186-afe-clk.c  --  Mediatek 8186 afe clock ctrl
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/clk.h>
> > +#include <linux/regmap.h>
> > +#include <linux/mfd/syscon.h>
> > +
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-clk.h"
> > +#include "mt8186-audsys-clk.h"
> > +
> > +static DEFINE_MUTEX(mutex_request_dram);
> > +
> > +static const char *aud_clks[CLK_NUM] = {
> > +	[CLK_AFE] = "aud_afe_clk",
> > +	[CLK_DAC] = "aud_dac_clk",
> > +	[CLK_DAC_PREDIS] = "aud_dac_predis_clk",
> > +	[CLK_ADC] = "aud_adc_clk",
> > +	[CLK_TML] = "aud_tml_clk",
> > +	[CLK_APLL22M] = "aud_apll22m_clk",
> > +	[CLK_APLL24M] = "aud_apll24m_clk",
> > +	[CLK_APLL1_TUNER] = "aud_apll_tuner_clk",
> > +	[CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
> > +	[CLK_TDM] = "aud_tdm_clk",
> > +	[CLK_NLE] = "aud_nle_clk",
> > +	[CLK_DAC_HIRES] = "aud_dac_hires_clk",
> > +	[CLK_ADC_HIRES] = "aud_adc_hires_clk",
> > +	[CLK_I2S1_BCLK] = "aud_i2s1_bclk",
> > +	[CLK_I2S2_BCLK] = "aud_i2s2_bclk",
> > +	[CLK_I2S3_BCLK] = "aud_i2s3_bclk",
> > +	[CLK_I2S4_BCLK] = "aud_i2s4_bclk",
> > +	[CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc",
> > +	[CLK_GENERAL1_ASRC] = "aud_general1_asrc",
> > +	[CLK_GENERAL2_ASRC] = "aud_general2_asrc",
> > +	[CLK_ADC_HIRES_TML] = "aud_adc_hires_tml",
> > +	[CLK_ADDA6_ADC] = "aud_adda6_adc",
> > +	[CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> > +	[CLK_3RD_DAC] = "aud_3rd_dac",
> > +	[CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis",
> > +	[CLK_3RD_DAC_TML] = "aud_3rd_dac_tml",
> > +	[CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires",
> > +	[CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk",
> > +	[CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk",
> > +	[CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
> > +	[CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk",
> > +	[CLK_MUX_AUDIO] = "top_mux_audio",
> > +	[CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int",
> > +	[CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4",
> > +	[CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
> > +	[CLK_TOP_APLL1_CK] = "top_apll1_ck",
> > +	[CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
> > +	[CLK_TOP_APLL2_CK] = "top_apll2_ck",
> > +	[CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
> > +	[CLK_TOP_APLL1_D8] = "top_apll1_d8",
> > +	[CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
> > +	[CLK_TOP_APLL2_D8] = "top_apll2_d8",
> > +	[CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h",
> > +	[CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
> > +	[CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
> > +	[CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
> > +	[CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
> > +	[CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel",
> > +	[CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
> > +	[CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
> > +	[CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
> > +	[CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
> > +	[CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm",
> > +	[CLK_CLK26M] = "top_clk26m_clk",
> > +};
> > +
> > +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe,
> > +				    int clk_id)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
> > +			     afe_priv->clk[clk_id]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS],
> > +			 aud_clks[clk_id], ret);
> 
> 		dev_err(......)
> 		return ret;
> 
> > +	}
> > +
> 
> 	return 0;
> 
> > +	return ret;
> > +}
> > +
> > +static int apll1_mux_setting(struct mtk_base_afe *afe, bool
> > enable)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	if (enable) {
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_1]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> > +				     afe_priv->clk[CLK_TOP_APLL1_CK]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > +				 aud_clks[CLK_TOP_APLL1_CK], ret);
> 
> dev_err()
> 
> > +			goto EXIT;
> > +		}
> > +
> > +		/* 180.6336 / 8 = 22.5792MHz */
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1],
> > +				     afe_priv->clk[CLK_TOP_APLL1_D8]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1],
> > +				 aud_clks[CLK_TOP_APLL1_D8], ret);
> > +			goto EXIT;
> > +		}
> > +	} else {
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG1],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG1]);
> > +
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_1],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_1]);
> > +	}
> > +EXIT:
> > +	return 0;
> 
> You're returning 0 even in error cases, this is wrong.
> 
> > +}
> > +
> > +static int apll2_mux_setting(struct mtk_base_afe *afe, bool
> > enable)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	if (enable) {
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_2]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> > +				     afe_priv->clk[CLK_TOP_APLL2_CK]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > +				 aud_clks[CLK_TOP_APLL2_CK], ret);
> > +			goto EXIT;
> > +		}
> > +
> > +		/* 196.608 / 8 = 24.576MHz */
> > +		ret = clk_prepare_enable(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
> > +			goto EXIT;
> > +		}
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2],
> > +				     afe_priv->clk[CLK_TOP_APLL2_D8]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2],
> > +				 aud_clks[CLK_TOP_APLL2_D8], ret);
> > +			goto EXIT;
> > +		}
> > +	} else {
> > +		ret = clk_set_parent(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__,
> > aud_clks[CLK_TOP_MUX_AUD_ENG2],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_ENG2]);
> > +
> > +		ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
> > +				     afe_priv->clk[CLK_CLK26M]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[CLK_TOP_MUX_AUD_2],
> > +				 aud_clks[CLK_CLK26M], ret);
> > +			goto EXIT;
> > +		}
> > +		clk_disable_unprepare(afe_priv-
> > >clk[CLK_TOP_MUX_AUD_2]);
> > +	}
> > +
> > +EXIT:
> > +	return 0;
> > +}
> > +
> > +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +	int i;
> > +
> > +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) {
> > +		ret = clk_prepare_enable(afe_priv->clk[i]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[i], ret);
> 
> dev_err()
> 
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int i;
> > +
> > +	for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++)
> > +		clk_disable_unprepare(afe_priv->clk[i]);
> > +}
> > +
> > +int mt8186_afe_enable_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret = 0;
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);
> 
> dev_err()
> 
> > +		goto CLK_INFRA_SYS_AUDIO_ERR;
> 
> also, please use lower-case labels (here and everywhere else).
> 
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret);
> > +		goto CLK_INFRA_AUDIO_26M_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIO], ret);
> > +		goto CLK_MUX_AUDIO_ERR;
> > +	}
> > +	ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
> > +			     afe_priv->clk[CLK_CLK26M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIO],
> > +			 aud_clks[CLK_CLK26M], ret);
> > +		goto CLK_MUX_AUDIO_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe,
> > +					      CLK_TOP_MAINPLL_D2_D4);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H],
> > +			     afe_priv->clk[CLK_TOP_APLL2_CK]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> > +			 __func__, aud_clks[CLK_TOP_MUX_AUDIO_H],
> > +			 aud_clks[CLK_TOP_APLL2_CK], ret);
> > +		goto CLK_MUX_AUDIO_H_PARENT_ERR;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_AFE], ret);
> > +		goto CLK_AFE_ERR;
> > +	}
> > +
> > +	return 0;
> > +
> > +CLK_AFE_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> > +CLK_MUX_AUDIO_H_PARENT_ERR:
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +CLK_MUX_AUDIO_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> > +CLK_INFRA_SYS_AUDIO_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +CLK_INFRA_AUDIO_26M_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_afe_disable_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
> > +}
> > +
> > +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* set audio int bus to 26M */
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> 
> dev_err() - here and for the other similar instances.
> 
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +
> > +	return 0;
> > +
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	return ret;
> > +}
> > +
> > +int mt8186_afe_resume_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* set audio int bus to normal working clock */
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
> > +		goto CLK_MUX_AUDIO_INTBUS_ERR;
> > +	}
> > +	ret = mt8186_set_audio_int_bus_parent(afe,
> > +					      CLK_TOP_MAINPLL_D2_D4);
> > +	if (ret)
> > +		goto CLK_MUX_AUDIO_INTBUS_PARENT_ERR;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +
> > +	return 0;
> > +
> > +CLK_MUX_AUDIO_INTBUS_PARENT_ERR:
> > +	mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M);
> > +CLK_MUX_AUDIO_INTBUS_ERR:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
> > +	return ret;
> > +}
> > +
> > +int mt8186_apll1_enable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* setting for APLL */
> > +	apll1_mux_setting(afe, true);
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL22M], ret);
> > +		goto ERR_CLK_APLL22M;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL1_TUNER], ret);
> > +		goto ERR_CLK_APLL1_TUNER;
> > +	}
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
> > +			   0x0000FFF7, 0x00000832);
> 
> no leading zeroes - and without them, it fits in one line.
> 
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_22M_ON_MASK_SFT,
> > +			   0x1 << AFE_22M_ON_SFT);
> 
> BIT() macro please
> 
> > +
> > +	return 0;
> > +
> > +ERR_CLK_APLL1_TUNER:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> > +ERR_CLK_APLL22M:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_apll1_disable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_22M_ON_MASK_SFT,
> > +			   0x0 << AFE_22M_ON_SFT);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
> > +
> > +	apll1_mux_setting(afe, false);
> > +}
> > +
> > +int mt8186_apll2_enable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int ret;
> > +
> > +	/* setting for APLL */
> > +	apll2_mux_setting(afe, true);
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL24M], ret);
> > +		goto ERR_CLK_APLL24M;
> > +	}
> > +
> > +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[CLK_APLL2_TUNER], ret);
> > +		goto ERR_CLK_APLL2_TUNER;
> > +	}
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
> > +			   0x0000FFF7, 0x00000634);
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_24M_ON_MASK_SFT,
> > +			   0x1 << AFE_24M_ON_SFT);
> > +
> > +	return 0;
> > +
> > +ERR_CLK_APLL2_TUNER:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> > +ERR_CLK_APLL24M:
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> > +
> > +	return ret;
> > +}
> > +
> > +void mt8186_apll2_disable(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +
> > +	regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
> > +			   AFE_24M_ON_MASK_SFT,
> > +			   0x0 << AFE_24M_ON_SFT);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
> > +
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> > +	clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
> > +
> > +	apll2_mux_setting(afe, false);
> > +}
> > +
> > +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll)
> > +{
> > +	return (apll == MT8186_APLL1) ? 180633600 : 196608000;
> > +}
> > +
> > +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
> > +{
> > +	return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1;
> > +}
> > +
> > +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char
> > *name)
> > +{
> > +	if (strcmp(name, APLL1_W_NAME) == 0)
> > +		return MT8186_APLL1;
> > +	else
> > +		return MT8186_APLL2;
> > +}
> > +
> > +/* mck */
> > +struct mt8186_mck_div {
> > +	int m_sel_id;
> > +	int div_clk_id;
> > +	/* below will be deprecated */
> > +	int div_pdn_reg;
> > +	int div_pdn_mask_sft;
> > +	int div_reg;
> > +	int div_mask_sft;
> > +	int div_mask;
> > +	int div_sft;
> > +	int div_msb_reg;
> > +	int div_msb_mask_sft;
> > +	int div_msb_mask;
> > +	int div_msb_sft;
> > +	int div_apll_sel_reg;
> > +	int div_apll_sel_mask_sft;
> > +	int div_apll_sel_sft;
> > +	int div_inv_reg;
> > +	int div_inv_mask_sft;
> 
> 
> 
> *_reg fits in u16.
> *_mask_sft, *_sel_sft can be u32.
> 
> This would be nice to avoid wasting memory for variables that are
> larger than
> needed; besides, you're also using a signed type for a number that
> may not
> ever be less than zero.
> 
> 
> > +};
> > +
> > +static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = {
> > +	[MT8186_I2S0_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S0_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV0,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV0_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV0_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV0_MASK,
> > +		.div_sft = APLL12_CK_DIV0_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S0_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S0_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S1_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S1_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV1,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV1_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV1_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV1_MASK,
> > +		.div_sft = APLL12_CK_DIV1_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S1_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S1_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S2_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S2_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV2,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV2_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV2_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV2_MASK,
> > +		.div_sft = APLL12_CK_DIV2_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S2_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S2_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_I2S4_MCK] = {
> > +		.m_sel_id = CLK_TOP_I2S4_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV4,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV4_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_2,
> > +		.div_mask_sft = APLL12_CK_DIV4_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV4_MASK,
> > +		.div_sft = APLL12_CK_DIV4_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_I2S4_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_I2S4_MCK_SEL_SFT,
> > +	},
> > +	[MT8186_TDM_MCK] = {
> > +		.m_sel_id = CLK_TOP_TDM_M_SEL,
> > +		.div_clk_id = CLK_TOP_APLL12_DIV_TDM,
> > +		.div_pdn_reg = CLK_AUDDIV_0,
> > +		.div_pdn_mask_sft = APLL12_DIV_TDM_PDN_MASK_SFT,
> > +		.div_reg = CLK_AUDDIV_3,
> > +		.div_mask_sft = APLL12_CK_DIV_TDM_MASK_SFT,
> > +		.div_mask = APLL12_CK_DIV_TDM_MASK,
> > +		.div_sft = APLL12_CK_DIV_TDM_SFT,
> > +		.div_apll_sel_reg = CLK_AUDDIV_0,
> > +		.div_apll_sel_mask_sft = APLL_TDM_MCK_SEL_MASK_SFT,
> > +		.div_apll_sel_sft = APLL_TDM_MCK_SEL_SFT,
> > +	},
> > +};
> > +
> > +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int
> > rate)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int apll = mt8186_get_apll_by_rate(afe, rate);
> > +	int apll_clk_id = apll == MT8186_APLL1 ?
> > +			  CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
> > +	int m_sel_id = mck_div[mck_id].m_sel_id;
> > +	int div_clk_id = mck_div[mck_id].div_clk_id;
> > +	int ret;
> > +
> > +	/* select apll */
> > +	if (m_sel_id >= 0) {
> > +		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), clk_prepare_enable %s
> > fail %d\n",
> > +				 __func__, aud_clks[m_sel_id], ret);
> 
> dev_err()
> 
> > +			return ret;
> > +		}
> > +		ret = clk_set_parent(afe_priv->clk[m_sel_id],
> > +				     afe_priv->clk[apll_clk_id]);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), clk_set_parent %s-%s
> > fail %d\n",
> > +				 __func__, aud_clks[m_sel_id],
> > +				aud_clks[apll_clk_id], ret);
> 
> again
> 
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	/* enable div, set rate */
> > +	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s(), clk_prepare_enable %s fail
> > %d\n",
> > +			 __func__, aud_clks[div_clk_id], ret);
> 
> again
> 
> > +		return ret;
> > +	}
> > +	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
> > +	if (ret) {
> > +		dev_info(afe->dev, "%s(), clk_set_rate %s, rate %d,
> > fail %d\n",
> > +			 __func__, aud_clks[div_clk_id],
> > +			 rate, ret);
> 
> again - and this fits in two lines.
> 
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int m_sel_id = mck_div[mck_id].m_sel_id;
> > +	int div_clk_id = mck_div[mck_id].div_clk_id;
> > +
> > +	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
> > +	if (m_sel_id >= 0)
> > +		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
> > +}
> > +
> > +int mt8186_init_clock(struct mtk_base_afe *afe)
> > +{
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	struct device_node *of_node = afe->dev->of_node;
> > +	int i = 0;
> > +
> > +	 mt8186_audsys_clk_register(afe);
> 
> Fix indentation please
> 
> > +
> > +	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM,
> > sizeof(*afe_priv->clk),
> > +				     GFP_KERNEL);
> > +	if (!afe_priv->clk)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < CLK_NUM; i++) {
> > +		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
> > +		if (IS_ERR(afe_priv->clk[i])) {
> > +			dev_info(afe->dev, "%s devm_clk_get %s fail,
> > ret %ld\n",
> > +				 __func__,
> > +				 aud_clks[i], PTR_ERR(afe_priv-
> > >clk[i]));
> > +			afe_priv->clk[i] = NULL;
> > +		}
> > +	}
> > +
> > +	afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node,
> > +							       "mediate
> > k,apmixedsys");
> > +	if (IS_ERR(afe_priv->apmixedsys)) {
> > +		dev_err(afe->dev, "%s() Cannot find apmixedsys
> > controller: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->apmixedsys));
> > +		return PTR_ERR(afe_priv->apmixedsys);
> > +	}
> > +
> > +	afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node,
> > +							     "mediatek,
> > topckgen");
> > +	if (IS_ERR(afe_priv->topckgen)) {
> > +		dev_err(afe->dev, "%s() Cannot find topckgen
> > controller: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->topckgen));
> > +		return PTR_ERR(afe_priv->topckgen);
> > +	}
> > +
> > +	afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node,
> > +							     "mediatek,
> > infracfg");
> > +	if (IS_ERR(afe_priv->infracfg)) {
> > +		dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n",
> > +			__func__, PTR_ERR(afe_priv->infracfg));
> > +		return PTR_ERR(afe_priv->infracfg);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void mt8186_deinit_clock(struct mtk_base_afe *afe)
> > +{
> > +	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
> > new file mode 100644
> > index 000000000000..3ce7a9a24d4a
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
> > @@ -0,0 +1,210 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + *
> > + * mt8186-afe-clk.h  --  Mediatek 8186 afe clock ctrl definition
> > + *
> > + * Copyright (c) 2022 MediaTek Inc.
> > + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > + */
> > +
> > +#ifndef _MT8186_AFE_CLOCK_CTRL_H_
> > +#define _MT8186_AFE_CLOCK_CTRL_H_
> > +
> > +#define PERI_BUS_DCM_CTRL 0x0074
> > +#define MODULE_SW_CG_1_STA 0x0094
> > +#define MODULE_SW_CG_2_STA 0x00ac
> > +#define CLK_CFG_7 0x0080
> > +#define CLK_CFG_8 0x0090
> > +#define CLK_CFG_11 0x00c0
> > +#define CLK_CFG_12 0x00d0
> > +#define CLK_CFG_13 0x00e0
> > +#define CLK_CFG_15 0x0100
> > +#define AP_PLL_CON3 0x0014
> > +#define APLL1_CON4 0x0328
> > +#define APLL1_TUNER_CON0 0x0040
> > +#define APLL2_CON4 0x033c
> > +#define APLL2_TUNER_CON0 0x0044
> > +
> > +#define AP_PLL_CON5 0x0014
> > +#define APLL1_CON0 0x02c0
> > +#define APLL1_CON1 0x02c4
> > +#define APLL1_CON2 0x02c8
> > +#define APLL1_CON3 0x02cc
> > +#define APLL1_PWR_CON0 0x02d0
> > +
> > +#define APLL2_CON0 0x02d4
> > +#define APLL2_CON1 0x02d8
> > +#define APLL2_CON2 0x02dc
> > +#define APLL2_CON3 0x02e0
> > +#define APLL2_PWR_CON0 0x02e4
> > +
> > +#define APMIXEDSYS_MAX_LENGTH APLL2_PWR_CON0
> > +
> > +#define CLK_CFG_6 0x0080
> > +#define CLK_AUDDIV_0 0x0320
> > +#define CLK_AUDDIV_1 0x0324
> > +#define CLK_AUDDIV_2 0x0328
> > +#define CKSYS_AUD_TOP_CFG 0x032c
> > +#define CKSYS_AUD_TOP_MON 0x0330
> > +#define CLK_AUDDIV_3 0x0334
> > +
> > +#define CLK_MAX_LENGTH CLK_AUDDIV_3
> > +
> > +/* CLK_CFG_6 */
> > +#define CLK_AUD_INTBUS_SEL_SFT              16
> > +#define CLK_AUD_INTBUS_SEL_MASK             0x3
> > +#define CLK_AUD_INTBUS_SEL_MASK_SFT         (0x3 << 16)
> 
> #define CLK_AUD_INTBUS_SEL_MASK_SFT		GENMASK(23, 22)
> 
> > +
> > +/* CLK_AUDDIV_0 */
> > +#define APLL12_DIV0_PDN_SFT                0
> > +#define APLL12_DIV0_PDN_MASK               0x1
> > +#define APLL12_DIV0_PDN_MASK_SFT           (0x1 << 0)
> 
> BIT() macro please
> 
> #define APLL12_DIV0_PDN_MASK_SFT		BIT(0)
> 
> also, using tabulations instead of spaces is nicer.
> 
> > +#define APLL12_DIV1_PDN_SFT                1
> > +#define APLL12_DIV1_PDN_MASK               0x1
> > +#define APLL12_DIV1_PDN_MASK_SFT           (0x1 << 1)
> 
> Of course, BIT() macro again, here and everywhere else applicable.
> 
> > +#define APLL12_DIV2_PDN_SFT                2
> > +#define APLL12_DIV2_PDN_MASK               0x1
> > +#define APLL12_DIV2_PDN_MASK_SFT           (0x1 << 2)
> > +#define APLL12_DIV4_PDN_SFT                3
> > +#define APLL12_DIV4_PDN_MASK               0x1
> > +#define APLL12_DIV4_PDN_MASK_SFT           (0x1 << 3)
> > +#define APLL12_DIV_TDM_PDN_SFT             4
> > +#define APLL12_DIV_TDM_PDN_MASK            0x1
> > +#define APLL12_DIV_TDM_PDN_MASK_SFT        (0x1 << 4)
> > +#define APLL_I2S0_MCK_SEL_SFT              16
> > +#define APLL_I2S0_MCK_SEL_MASK             0x1
> > +#define APLL_I2S0_MCK_SEL_MASK_SFT         (0x1 << 16)
> > +#define APLL_I2S1_MCK_SEL_SFT              17
> > +#define APLL_I2S1_MCK_SEL_MASK             0x1
> > +#define APLL_I2S1_MCK_SEL_MASK_SFT         (0x1 << 17)
> > +#define APLL_I2S2_MCK_SEL_SFT              18
> > +#define APLL_I2S2_MCK_SEL_MASK             0x1
> > +#define APLL_I2S2_MCK_SEL_MASK_SFT         (0x1 << 17)
> > +#define APLL_I2S4_MCK_SEL_SFT              19
> > +#define APLL_I2S4_MCK_SEL_MASK             0x1
> > +#define APLL_I2S4_MCK_SEL_MASK_SFT         (0x1 << 19)
> > +#define APLL_TDM_MCK_SEL_SFT               20
> > +#define APLL_TDM_MCK_SEL_MASK              0x1
> > +#define APLL_TDM_MCK_SEL_MASK_SFT          (0x1 << 20)
> > +
> > +/* CLK_AUDDIV_2 */
> > +#define APLL12_CK_DIV0_SFT                 0
> > +#define APLL12_CK_DIV0_MASK                0xff
> > +#define APLL12_CK_DIV0_MASK_SFT            (0xff << 0)
> 
> GENMASK(7, 0)
> 
> > +#define APLL12_CK_DIV1_SFT                 8
> > +#define APLL12_CK_DIV1_MASK                0xff
> > +#define APLL12_CK_DIV1_MASK_SFT            (0xff << 8)
> 
> GENMASK(15, 8)
> 
> > +#define APLL12_CK_DIV2_SFT                 16
> > +#define APLL12_CK_DIV2_MASK                0xff
> > +#define APLL12_CK_DIV2_MASK_SFT            (0xff << 16)
> 
> Fix all the others too :))
> 
> > +#define APLL12_CK_DIV4_SFT                 24
> > +#define APLL12_CK_DIV4_MASK                0xff
> > +#define APLL12_CK_DIV4_MASK_SFT            (0xff << 24)
> > +
> > +/* CLK_AUDDIV_3 */
> > +#define APLL12_CK_DIV_TDM_SFT              0
> > +#define APLL12_CK_DIV_TDM_MASK             0xff
> > +#define APLL12_CK_DIV_TDM_MASK_SFT         (0xff << 0)
> > +
> > +/* AUD_TOP_CFG */
> > +#define AUD_TOP_CFG_SFT                    0
> > +#define AUD_TOP_CFG_MASK                   0xffffffff
> > +#define AUD_TOP_CFG_MASK_SFT               (0xffffffff << 0)
> 
> This is GENMASK(31, 0) for both MASK and MASK_SFT
> 
> > +
> > +/* AUD_TOP_MON */
> > +#define AUD_TOP_MON_SFT                    0
> > +#define AUD_TOP_MON_MASK                   0xffffffff
> > +#define AUD_TOP_MON_MASK_SFT               (0xffffffff << 0)
> 
> same here
> 
> 
> 
> Regards,
> Angelo
_______________________________________________
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] 44+ messages in thread

* Re: [v2 11/17] ASoC: mediatek: mt8186: support gpio control in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-03 15:30     ` Jiaxin Yu
  0 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-03 15:30 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch add gpio control for all audio interface separately.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 210
> > ++++++++++++++++++++
> >   sound/soc/mediatek/mt8186/mt8186-afe-gpio.h |  19 ++
> >   2 files changed, 229 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> > b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> > new file mode 100644
> > index 000000000000..6faec5c95bf3
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
> > @@ -0,0 +1,210 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// mt8186-afe-gpio.c  --  Mediatek 8186 afe gpio ctrl
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/gpio.h>
> > +#include <linux/pinctrl/consumer.h>
> > +
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-gpio.h"
> > +
> > +struct pinctrl *aud_pinctrl;
> > +
> > +enum mt8186_afe_gpio {
> > +	MT8186_AFE_GPIO_CLK_MOSI_OFF,
> > +	MT8186_AFE_GPIO_CLK_MOSI_ON,
> > +	MT8186_AFE_GPIO_CLK_MISO_OFF,
> > +	MT8186_AFE_GPIO_CLK_MISO_ON,
> > +	MT8186_AFE_GPIO_DAT_MISO_OFF,
> > +	MT8186_AFE_GPIO_DAT_MISO_ON,
> > +	MT8186_AFE_GPIO_DAT_MOSI_OFF,
> > +	MT8186_AFE_GPIO_DAT_MOSI_ON,
> > +	MT8186_AFE_GPIO_I2S0_OFF,
> > +	MT8186_AFE_GPIO_I2S0_ON,
> > +	MT8186_AFE_GPIO_I2S1_OFF,
> > +	MT8186_AFE_GPIO_I2S1_ON,
> > +	MT8186_AFE_GPIO_I2S2_OFF,
> > +	MT8186_AFE_GPIO_I2S2_ON,
> > +	MT8186_AFE_GPIO_I2S3_OFF,
> > +	MT8186_AFE_GPIO_I2S3_ON,
> > +	MT8186_AFE_GPIO_TDM_OFF,
> > +	MT8186_AFE_GPIO_TDM_ON,
> > +	MT8186_AFE_GPIO_PCM_OFF,
> > +	MT8186_AFE_GPIO_PCM_ON,
> > +	MT8186_AFE_GPIO_GPIO_NUM
> > +};
> > +
> > +struct audio_gpio_attr {
> > +	const char *name;
> > +	bool gpio_prepare;
> > +	struct pinctrl_state *gpioctrl;
> > +};
> > +
> > +static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM]
> > = {
> > +	[MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL},
> > +	[MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL},
> > +	[MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL},
> > +	[MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false,
> > NULL},
> > +	[MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL},
> > +	[MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL},
> > +	[MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL},
> > +	[MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL},
> > +	[MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL},
> > +};
> > +
> > +static DEFINE_MUTEX(gpio_request_mutex);
> > +
> > +int mt8186_afe_gpio_init(struct device *dev)
> > +{
> > +	int ret;
> > +	int i = 0;
> > +
> > +	aud_pinctrl = devm_pinctrl_get(dev);
> > +	if (IS_ERR(aud_pinctrl)) {
> > +		ret = PTR_ERR(aud_pinctrl);
> > +		dev_info(dev, "%s(), ret %d, cannot get
> > aud_pinctrl!\n",
> > +			 __func__, ret);
> 
> dev_err()
> ... and return ret.
> 
> > +		return -ENODEV;
> > +	}
> > +
> > +	for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
> > +		aud_gpios[i].gpioctrl =
> > pinctrl_lookup_state(aud_pinctrl,
> > +							     aud_gpios[
> > i].name);
> > +		if (IS_ERR(aud_gpios[i].gpioctrl)) {
> > +			ret = PTR_ERR(aud_gpios[i].gpioctrl);
> > +			dev_info(dev, "%s(), pinctrl_lookup_state %s
> > fail, ret %d\n",
> > +				 __func__, aud_gpios[i].name, ret);
> 
> dev_err()
> 
> P.S.: I think that this function should return ret, at this point, to
> avoid
>        unexpected behavior.

Because we maybe don't need to config all of audio interface gpio in
dtsi. for example, we may only use I2S0/I2S1 instead of I2S3/I2S4, so
there only config I2S0/I2S1's pinctrl in dtsi. So I think there only
need dev_info() as a reminder. How do you suggest for it?

> 
> 
> > +		} else {
> > +			aud_gpios[i].gpio_prepare = true;
> > +		}
> > +	}
> > +
> > +	/* gpio status init */
> > +	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 0);
> > +	mt8186_afe_gpio_request(dev, false, MT8186_DAI_ADDA, 1);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init);
> > +
> > +static int mt8186_afe_gpio_select(struct device *dev,
> > +				  enum mt8186_afe_gpio type)
> > +{
> > +	int ret = 0;
> > +
> > +	if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) {
> > +		dev_info(dev, "%s(), error, invalid gpio type %d\n",
> > +			 __func__, type);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!aud_gpios[type].gpio_prepare) {
> > +		dev_info(dev, "%s(), error, gpio type %d not
> > prepared\n",
> > +			 __func__, type);
> > +		return -EIO;
> > +	}
> > +
> > +	ret = pinctrl_select_state(aud_pinctrl,
> > +				   aud_gpios[type].gpioctrl);
> > +	if (ret)
> > +		dev_info(dev, "%s(), error, can not set gpio type
> > %d\n",
> > +			 __func__, type);
> > +
> > +	return ret;
> 
> Please change it like so:
> 
> 	if (ret) {
> 		dev_err(dev, "Failed to select picntrl state for type
> %d\n", type);
> 		return ret;
> 	}
> 
> 	return 0;
> 
> > +}
> > +
> > +static int mt8186_afe_gpio_adda_dl(struct device *dev, bool
> > enable)
> > +{
> > +	if (enable) {
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_CLK_MOSI_ON);
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_DAT_MOSI_ON);
> > +	} else {
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_DAT_MOSI_OFF);
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_CLK_MOSI_OFF);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mt8186_afe_gpio_adda_ul(struct device *dev, bool
> > enable)
> > +{
> > +	if (enable) {
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_CLK_MISO_ON);
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_DAT_MISO_ON);
> > +	} else {
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_DAT_MISO_OFF);
> > +		mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_CLK_MISO_OFF);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int mt8186_afe_gpio_request(struct device *dev, bool enable,
> > +			    int dai, int uplink)
> > +{
> 
> I think that it's more readable and even shorter if you do:
> 
> 	enum mt8186_afe_gpio sel;
> 
> 	int ret = -EINVAL;
> 
> 
> 
> 	mutex_lock(&gpio_request_mutex);
> 
> 
> 
> 	switch (dai) {
> 
> 	case MT8186_DAI_ADDA:
> 		if (uplink)
> 			ret = mt8186_afe_gpio_adda_ul(dev, enable);
> 		else
> 			ret = mt8186_afe_gpio_adda_dl(dev, enable);
> 		goto unlock;
> 	case MT8186_DAI_I2S_0:
> 
> 		sel = enable ? MT8186_AFE_GPIO_I2S0_ON :
> MT8186_AFE_GPIO_I2S0_OFF;
> 
> 		break;
> 
> 	case MT8186_DAI_I2S_1:
> 
> 		sel = enable ? MT8186_AFE_GPIO_I2S1_ON :
> MT8186_AFE_GPIO_I2S1_OFF;
> 
> 		break;
> 
> 
> 
> 	.................... all other cases ................
> 
> 	default:
> 
> 		dev_err(dev, "invalid dai %d\n", dai);
> 
> 		goto unlock;
> 
> 	}
> 
> 
> 	ret = mt8186_afe_gpio_select(dev, sel);
> 
> 
> unlock:
> 
> 	mutex_unlock(&gpio_request_mutex);
> 
> 	return ret;
> }
> 
> > +	mutex_lock(&gpio_request_mutex);
> > +	switch (dai) {
> > +	case MT8186_DAI_ADDA:
> > +		if (uplink)
> > +			mt8186_afe_gpio_adda_ul(dev, enable);
> > +		else
> > +			mt8186_afe_gpio_adda_dl(dev, enable);
> > +		break;
> > +	case MT8186_DAI_I2S_0:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S0_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S0_OFF);
> > +		break;
> > +	case MT8186_DAI_I2S_1:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S1_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S1_OFF);
> > +		break;
> > +	case MT8186_DAI_I2S_2:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S2_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S2_OFF);
> > +		break;
> > +	case MT8186_DAI_I2S_3:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S3_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_I2S3_OFF);
> > +		break;
> > +	case MT8186_DAI_TDM_IN:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_TDM_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_TDM_OFF);
> > +		break;
> > +	case MT8186_DAI_PCM:
> > +		if (enable)
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_PCM_ON);
> > +		else
> > +			mt8186_afe_gpio_select(dev,
> > MT8186_AFE_GPIO_PCM_OFF);
> > +		break;
> > +	default:
> > +		mutex_unlock(&gpio_request_mutex);
> > +		dev_info(dev, "%s(), invalid dai %d\n", __func__, dai);
> > +		return -EINVAL;
> > +	}
> > +	mutex_unlock(&gpio_request_mutex);
> > +	return 0;
> > +}
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> > b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> > new file mode 100644
> > index 000000000000..1ddc27838eb1
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h
> > @@ -0,0 +1,19 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + *
> > + * mt6833-afe-gpio.h  --  Mediatek 6833 afe gpio ctrl definition
> > + *
> > + * Copyright (c) 2022 MediaTek Inc.
> > + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > + */
> > +
> > +#ifndef _MT8186_AFE_GPIO_H_
> > +#define _MT8186_AFE_GPIO_H_
> > +
> > +struct mtk_base_afe;
> > +
> > +int mt8186_afe_gpio_init(struct device *dev);
> > +
> > +int mt8186_afe_gpio_request(struct device *dev, bool enable,
> > +			    int dai, int uplink);
> > +
> > +#endif
> 
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 09/17] ASoC: mediatek: mt8186: support tdm in platform driver
  2022-03-03 15:08       ` AngeloGioacchino Del Regno
@ 2022-03-03 17:39         ` Jiaxin Yu
  0 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-03 17:39 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Thu, 2022-03-03 at 16:08 +0100, AngeloGioacchino Del Regno wrote:
> Il 03/03/22 15:10, Jiaxin Yu ha scritto:
> > On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno
> > wrote:
> > > Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > > > This patch adds mt8186 tdm dai driver.
> > > > 
> > > > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > > > ---
> > > >    sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 713
> > > > +++++++++++++++++++++
> > > >    1 file changed, 713 insertions(+)
> > > >    create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-
> > > > tdm.c
> > > > 
> > > > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > > > b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > > > new file mode 100644
> > > > index 000000000000..28dd3661f0e0
> > > > --- /dev/null
> > > > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
> > > > @@ -0,0 +1,713 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +//
> > > > +// MediaTek ALSA SoC Audio DAI TDM Control
> > > > +//
> > > > +// Copyright (c) 2022 MediaTek Inc.
> > > > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > > > +
> 
> ..snip..
> 
> > > > +
> > > > +static int mtk_dai_tdm_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);
> > > > +	struct mt8186_afe_private *afe_priv = afe-
> > > > >platform_priv;
> > > > +	int tdm_id = dai->id;
> > > > +	struct mtk_afe_tdm_priv *tdm_priv = afe_priv-
> > > > >dai_priv[tdm_id];
> > > > +	unsigned int tdm_mode = tdm_priv->tdm_mode;
> > > > +	unsigned int data_mode = tdm_priv->data_mode;
> > > > +	unsigned int rate = params_rate(params);
> > > > +	unsigned int channels = params_channels(params);
> > > > +	snd_pcm_format_t format = params_format(params);
> > > > +	unsigned int bit_width =
> > > > +		snd_pcm_format_physical_width(format);
> > > > +	unsigned int tdm_channels = (data_mode ==
> > > > TDM_DATA_ONE_PIN) ?
> > > > +		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
> > > > +	unsigned int lrck_width =
> > > > +		get_tdm_lrck_width(format, tdm_mode);
> > > > +	unsigned int tdm_con = 0;
> > > > +	bool slave_mode = tdm_priv->slave_mode;
> > > > +	bool lrck_inv = tdm_priv->lck_invert;
> > > > +	bool bck_inv = tdm_priv->bck_invert;
> > > > +	unsigned int ctrl_reg;
> > > > +	unsigned int ctrl_mask;
> > > > +	unsigned int tran_rate;
> > > > +	unsigned int tran_relatch_rate;
> > > > +
> > > > +	if (tdm_priv)
> > > > +		tdm_priv->rate = rate;
> > > > +	else
> > > > +		dev_info(afe->dev, "%s(), tdm_priv == NULL",
> > > > __func__);
> > > > +
> > > > +	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);
> > > > +	}
> > > > +
> > > > +	/* ETDM_IN1_CON0 */
> > > > +	tdm_con |= slave_mode <<
> > > > ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
> > > > +	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
> > > > +	tdm_con |= (bit_width - 1) <<
> > > > ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
> > > > +	tdm_con |= (bit_width - 1) <<
> > > > ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
> > > > +	tdm_con |= (tdm_channels - 1) <<
> > > > ETDM_IN1_CON0_REG_CH_NUM_SFT;
> > > > +	/* default disable sync mode */
> > > > +	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;
> > > 
> > > 0 << (anything) == 0
> > > 
> > > (number |= 0) == number
> > > 
> > > Is this a mistake, or are you really doing nothing here?
> > > 
> > 
> > No, this is just to emphasize the need to set this bit to 0.
> > It really do nothing here, just link a reminder.
> > Can I keep this sentence?
> 
> If, in your judgement, it is very important to have a reminder about
> that
> bit having to be unset, then add a comment in the code saying so.
> Don't simply comment out the statement as it is.
> 
> A good way would be something like
> /* sync mode bit has to be unset because this that reason, otherwise
> X happens */

I see, thanks for your kind advise.
> 
> > > 
> > > > +	/* relatch fix to h26m */
> > > > +	tdm_con |= 0 <<
> > > > ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
> > > > +
> > > > +	ctrl_reg = ETDM_IN1_CON0;
> > > > +	ctrl_mask = ETDM_IN_CON0_CTRL_MASK;
> > > > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask,
> > > > tdm_con);
> > > > +
> > > > +	/* ETDM_IN1_CON1 */
> > > > +	tdm_con = 0;
> > > > +	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
> > > > +	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
> > > > +	tdm_con |= (lrck_width - 1) <<
> > > > ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
> > > > +
> > > > +	ctrl_reg = ETDM_IN1_CON1;
> > > > +	ctrl_mask = ETDM_IN_CON1_CTRL_MASK;
> > > > +	regmap_update_bits(afe->regmap, ctrl_reg, ctrl_mask,
> > > > tdm_con);
> > > 
> > > You don't need the ctrl_reg, nor ctrl_mask variables...
> > 
> > I was trying to avoid a line of more than 80 words, so I shortened
> > the
> > number of words through variables.
> > 
> 
> Yes, I know, I did understand what you were trying to do...
> ...but it's fine to go past 80: in this case this would be 88
> columns,
> which is still ok to have!
> 
> And note, this is the case with all of similar calls present in this
> function,
> that's why I said that you don't need these two variables! :)
> 
> Thank you,
> Angelo
Ok, I got it. This function will be corrected in the next version.

Thank you.
Jiaxin.Yu


> 
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 01/17] ASoC: mediatek: mt6366: add codec driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-05  4:24     ` Jiaxin Yu
  2022-03-07  9:07       ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05  4:24 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > Mt6366 is a new version of mt6358, and they are same about audio
> > part.
> > So we can reuse the driver of mt6358.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> 
> Hello Jiaxin,
> I'm sorry but this commit makes very little sense.
> 
> If you want to advertise MT6366 support, please write a note and/or
> a new compatible string inside of the mt6358 driver (and dt-
> bindings),
> then, please drop this commit.
> 

Hello angelogioacchino,

Thank you for your advice.

If I add a new compatible string inside of the mt6358 driver and dt-
bindings, then the machine driver which want to use mt6366 should
select SND_SOC_MT6358.

like below:

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_MT6366   ==> SND_SOC_MT6358
	...

I just doubt it's enough to make sense. I originally wanted to put this
relationship in the sound/soc/codecs layer. So that this relationship
is not perceived by users(machine driver).
However, if the general practice is like this, I will adopt your
suggestion. Thank you again.

> 
> > ---
> >   sound/soc/codecs/Kconfig  | 8 ++++++++
> >   sound/soc/codecs/Makefile | 1 +
> >   2 files changed, 9 insertions(+)
> > 
> > diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> > index 8fa24783ce01..6631094678f5 100644
> > --- a/sound/soc/codecs/Kconfig
> > +++ b/sound/soc/codecs/Kconfig
> > @@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS
> >   	imply SND_SOC_MT6351
> >   	imply SND_SOC_MT6358
> >   	imply SND_SOC_MT6359
> > +	imply SND_SOC_MT6366
> >   	imply SND_SOC_MT6660
> >   	imply SND_SOC_NAU8315
> >   	imply SND_SOC_NAU8540
> > @@ -1888,6 +1889,13 @@ config SND_SOC_MT6359_ACCDET
> >   	  for ASoC codec soc-jack detection mechanism.
> >   	  Select N if you don't have jack on board.
> >   
> > +config SND_SOC_MT6366
> > +	tristate "MediaTek MT6366 Codec"
> > +	depends on MTK_PMIC_WRAP
> > +	help
> > +	  Enable support for the platform which uses MT6366 as
> > +	  external codec device.
> > +
> >   config SND_SOC_MT6660
> >   	tristate "Mediatek MT6660 Speaker Amplifier"
> >   	depends on I2C
> > diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> > index 42d00aa4ee46..1279684feaf0 100644
> > --- a/sound/soc/codecs/Makefile
> > +++ b/sound/soc/codecs/Makefile
> > @@ -465,6 +465,7 @@ obj-$(CONFIG_SND_SOC_MT6351)	+= snd-soc-
> > mt6351.o
> >   obj-$(CONFIG_SND_SOC_MT6358)	+= snd-soc-mt6358.o
> >   obj-$(CONFIG_SND_SOC_MT6359)	+= snd-soc-mt6359.o
> >   obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o
> > +obj-$(CONFIG_SND_SOC_MT6366)	+= snd-soc-mt6358.o
> >   obj-$(CONFIG_SND_SOC_MT6660)	+= snd-soc-mt6660.o
> >   obj-$(CONFIG_SND_SOC_NAU8315)   += snd-soc-nau8315.o
> >   obj-$(CONFIG_SND_SOC_NAU8540)   += snd-soc-nau8540.o
> 
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-05  8:58     ` Jiaxin Yu
  2022-03-07  9:14       ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05  8:58 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:42, Jiaxin Yu ha scritto:
> > This patch adds support for mt8186 board with mt6366, da7219 and
> > max98357.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   .../mt8186/mt8186-mt6366-da7219-max98357.c    | 910
> > ++++++++++++++++++
> >   1 file changed, 910 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-
> > da7219-max98357.c
> > 
> > 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..6ba53b8d1e46
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
> > @@ -0,0 +1,910 @@
> > +// 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/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"
> > +
> > +#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 mt6366_codec_conf[] = {
> > +	{
> > +		.dlc = COMP_CODEC_CONF("mt6358-sound"),
> > +		.name_prefix = "Mt6366",
> > +	},
> > +};
> > +
> > +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, NULL, 0);
> > +	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 = 0, 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\n");
> 
> Does it really make sense to go on after this failure?
> 
> > +
> > +	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\n");
> > +
> 
> I think that going on past this wouldn't make sense as well, as it
> may result
> in unexpected behavior... just return a failure here

Yes, it is.
> 
> > +			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);
> 
> and here
Yes, you are right.

> 
> > +		}
> > +	}
> > +
> 
> So, you've covered all failure cases already, for which, you can
> simply
> return 0 here.
Yes, it is.

> 
> > +	return ret;
> > +}
> > +
> > +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);
> > +				break;
> > +			}
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +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_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, NULL, 0);
> > +	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_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_info(rtd->dev, "failed to snd_soc_dapm_sync\n");
> 
> dev_err()
> 
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime
> > *rtd,
> > +				      struct snd_pcm_hw_params *params)
> > +{
> > +	struct snd_interval *channels = hw_param_interval(params,
> > +		SNDRV_PCM_HW_PARAM_CHANNELS);
> > +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
> > +
> 
> dev_dbg()
> 
> > +	/* fix BE i2s channel to 2 channel */
> > +	channels->min = 2;
> > +	channels->max = 2;
> > +
> > +	/* fix BE i2s format to S32_LE, 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, SNDRV_PCM_FORMAT_S32_LE);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mt8186_hdmi_i2s_hw_params_fixup(struct
> > snd_soc_pcm_runtime *rtd,
> > +					   struct snd_pcm_hw_params
> > *params)
> > +{
> > +	struct snd_interval *channels = hw_param_interval(params,
> > +		SNDRV_PCM_HW_PARAM_CHANNELS);
> > +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
> > +
> 
> dev_dbg()
> 
> > +	/* fix BE i2s channel to 2 channel */
> > +	channels->min = 2;
> > +	channels->max = 2;
> > +
> > +	/* fix BE i2s format to S24_LE, 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, SNDRV_PCM_FORMAT_S24_LE);
> > +
> > +	return 0;
> > +}
> 

Ok, I will use this code which is really more concise.

> Besides, I would do the following instead:
> 
> 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 32bit\n", __func__);
> 
> 
> 
> 	/* fix BE i2s channel to 2 channel */
> 
> 	channels->min = 2;
> 
> 	channels->max = 2;
> 
> 
> 
> 	/* fix BE i2s format to S32_LE, 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_hdmi_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);
> 
> }
> 
> ... this reduces code duplication!
> 
> > +
> > +/* FE */
> > +SND_SOC_DAILINK_DEFS(playback1,
> > +		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
> > +		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
> > +		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
> 
> 
> ..snip..
> 
> > +static int mt8186_mt6366_da7219_max98357_dev_probe(struct
> > platform_device *pdev)
> > +{
> > +	struct snd_soc_card *card =
> > &mt8186_mt6366_da7219_max98357_soc_card;
> > +	struct snd_soc_dai_link *dai_link;
> > +	struct mt8186_mt6366_da7219_max98357_priv *priv;
> > +	struct device_node *platform_node, *hdmi_codec;
> > +	int ret, i;
> > +
> > +	dev_info(&pdev->dev, "%s(), ++\n", __func__);
> > +
> > +	card->dev = &pdev->dev;
> > +
> > +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	platform_node = of_parse_phandle(pdev->dev.of_node,
> > +					 "mediatek,platform", 0);
> > +	if (!platform_node) {
> > +		dev_info(&pdev->dev,
> > +			 "Property 'platform' missing or invalid\n");
> 
> 	if (!platform_node)
> 		return dev_err_probe(&pdev->dev, -EINVAL,
> 				    "mediatek,platform missing or
> invalid\n");
> 
> > +		return -EINVAL;
got err_platform_node;
> > +	}
> > +
> > +	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
> > +				      "mediatek,hdmi-codec", 0);
> > +	if (!hdmi_codec) {
> > +		dev_info(&pdev->dev,
> > +			 "Property 'hdmi' missing or invalid\n");
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
Should I of_node_put(platform_node) befor return?

goto err_hdmi_node;


> > +
> > +	for_each_card_prelinks(card, i, dai_link) {
> > +		if (dai_link->platforms->name)
> > +			continue;
> > +
> > +		if (hdmi_codec && strcmp(dai_link->name, "I2S3") == 0)
> > {
> > +			dai_link->codecs->of_node = hdmi_codec;
> > +			dai_link->ignore = 0;
> > +		}
> > +
> > +		dai_link->platforms->of_node = platform_node;
> > +	}
> > +
> > +	snd_soc_card_set_drvdata(card, priv);
> > +
> > +	/* init gpio */
> > +	ret = mt8186_afe_gpio_init(&pdev->dev);
> > +	if (ret)
> > +		dev_info(&pdev->dev, "init gpio error\n");
> 
> dev_err() and goto end;
Yes, goto err_init_gpio and of_node_put for hdmi_codec and
platform_node.
> 
> > +
> > +	dev_info(&pdev->dev, "%s(), devm_snd_soc_register_card\n",
> > __func__);
> > +	ret = devm_snd_soc_register_card(&pdev->dev, card);
> > +	if (ret)
> > +		dev_info(&pdev->dev, "%s snd_soc_register_card fail
> > %d\n",
> > +			 __func__, ret);
> 
> dev_err_probe()
> 
> end:
> 
err_init_gpio:
> > +	of_node_put(hdmi_codec);
err_hdmi_node:
> > +	of_node_put(platform_node);
> > +
err_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",},
> > +	{}
> > +};
> > +#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");
> 
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 12/17] ASoC: mediatek: mt8186: add platform driver
       [not found]   ` <58cc2df8-5503-b38f-2a6d-9bbef809a60f@collabora.com>
@ 2022-03-05  9:10     ` Jiaxin Yu
  0 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05  9:10 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:42, Jiaxin Yu ha scritto:
> > This patch adds mt8186 platform and affiliated driver.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/Kconfig                    |   44 +
> >   sound/soc/mediatek/Makefile                   |    1 +
> >   sound/soc/mediatek/mt8186/Makefile            |   21 +
> >   sound/soc/mediatek/mt8186/mt8186-afe-common.h |  245 ++
> >   .../soc/mediatek/mt8186/mt8186-afe-control.c  |  261 ++
> >   sound/soc/mediatek/mt8186/mt8186-afe-pcm.c    | 3029
> > +++++++++++++++
> >   .../mediatek/mt8186/mt8186-interconnection.h  |   69 +
> >   .../soc/mediatek/mt8186/mt8186-misc-control.c | 1728 +++++++++
> >   sound/soc/mediatek/mt8186/mt8186-reg.h        | 3433
> > +++++++++++++++++
> >   9 files changed, 8831 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/Makefile
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-common.h
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-control.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-
> > interconnection.h
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-misc-
> > control.c
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-reg.h
> > 
> > diff --git a/sound/soc/mediatek/Kconfig
> > b/sound/soc/mediatek/Kconfig
> > index 3b1ddea26a9e..d3528bdbb00a 100644
> > --- a/sound/soc/mediatek/Kconfig
> > +++ b/sound/soc/mediatek/Kconfig
> > @@ -152,6 +152,50 @@ 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 MFD_SYSCON if SND_SOC_MT6366
> > +	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_MT6366
> > +	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 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_MT6366
> > +	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 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/mt8186/Makefile
> > b/sound/soc/mediatek/mt8186/Makefile
> > new file mode 100644
> > index 000000000000..9f3bead9cdf8
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/Makefile
> > @@ -0,0 +1,21 @@
> > +# 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
> > +
> > +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-common.h
> > b/sound/soc/mediatek/mt8186/mt8186-afe-common.h
> > new file mode 100644
> > index 000000000000..b2b50faa3887
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-common.h
> > @@ -0,0 +1,245 @@
> > +/* 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"
> > +
> > +#if IS_ENABLED(CONFIG_MTK_AEE_FEATURE)
> > +#define AUDIO_AEE(message) \
> > +	(aee_kernel_exception_api(__FILE__, \
> > +				  __LINE__, \
> > +				  DB_OPT_FTRACE, message, \
> > +				  "audio assert"))
> > +#else
> > +#define AUDIO_AEE(message) WARN_ON(true)
> > +#endif
> 
> There is no such AEE upstream, please remove this block entirely.
> 
Ok, got it.

> ...snip...
> 
> > 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..cb863716a74b
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-control.c
> > @@ -0,0 +1,261 @@
> > +// 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,
> 
> You just need to define the first one as zero and you don't need to
> assign numbers to the others, since they are sequential.
> Please fix.
> 
Ok, got it.

> > +	MTK_AFE_RATE_11K = 1,
> > +	MTK_AFE_RATE_12K = 2,
> > +	MTK_AFE_RATE_384K = 3,
> > +	MTK_AFE_RATE_16K = 4,
> > +	MTK_AFE_RATE_22K = 5,
> > +	MTK_AFE_RATE_24K = 6,
> > +	MTK_AFE_RATE_352K = 7,
> > +	MTK_AFE_RATE_32K = 8,
> > +	MTK_AFE_RATE_44K = 9,
> > +	MTK_AFE_RATE_48K = 10,
> > +	MTK_AFE_RATE_88K = 11,
> > +	MTK_AFE_RATE_96K = 12,
> > +	MTK_AFE_RATE_176K = 13,
> > +	MTK_AFE_RATE_192K = 14,
> > +	MTK_AFE_RATE_260K = 15,
> > +};
> > +
> > +enum {
> > +	MTK_AFE_PCM_RATE_8K = 0,
> > +	MTK_AFE_PCM_RATE_16K = 1,
> > +	MTK_AFE_PCM_RATE_32K = 2,
> > +	MTK_AFE_PCM_RATE_48K = 3,
> 
> same here
> 
> > +};
> > +
> > +enum {
> > +	MTK_AFE_TDM_RATE_8K = 0,
> > +	MTK_AFE_TDM_RATE_12K = 1,
> > +	MTK_AFE_TDM_RATE_16K = 2,
> > +	MTK_AFE_TDM_RATE_24K = 3,
> > +	MTK_AFE_TDM_RATE_32K = 4,
> > +	MTK_AFE_TDM_RATE_48K = 5,
> > +	MTK_AFE_TDM_RATE_64K = 6,
> > +	MTK_AFE_TDM_RATE_96K = 7,
> > +	MTK_AFE_TDM_RATE_128K = 8,
> > +	MTK_AFE_TDM_RATE_192K = 9,
> > +	MTK_AFE_TDM_RATE_256K = 10,
> > +	MTK_AFE_TDM_RATE_384K = 11,
> > +	MTK_AFE_TDM_RATE_11K = 16,
> > +	MTK_AFE_TDM_RATE_22K = 17,
> > +	MTK_AFE_TDM_RATE_44K = 18,
> > +	MTK_AFE_TDM_RATE_88K = 19,
> > +	MTK_AFE_TDM_RATE_176K = 20,
> > +	MTK_AFE_TDM_RATE_352K = 21, > +};
> > +
> > +enum {
> > +	MTK_AFE_TDM_RELATCH_RATE_8K = 0,
> > +	MTK_AFE_TDM_RELATCH_RATE_11K = 1,
> > +	MTK_AFE_TDM_RELATCH_RATE_12K = 2,
> > +	MTK_AFE_TDM_RELATCH_RATE_16K = 4,
> > +	MTK_AFE_TDM_RELATCH_RATE_22K = 5,
> > +	MTK_AFE_TDM_RELATCH_RATE_24K = 6,
> > +	MTK_AFE_TDM_RELATCH_RATE_32K = 8,
> > +	MTK_AFE_TDM_RELATCH_RATE_44K = 9,
> > +	MTK_AFE_TDM_RELATCH_RATE_48K = 10,
> > +	MTK_AFE_TDM_RELATCH_RATE_88K = 13,
> > +	MTK_AFE_TDM_RELATCH_RATE_96K = 14,
> > +	MTK_AFE_TDM_RELATCH_RATE_176K = 17,
> > +	MTK_AFE_TDM_RELATCH_RATE_192K = 18,
> > +	MTK_AFE_TDM_RELATCH_RATE_352K = 21,
> > +	MTK_AFE_TDM_RELATCH_RATE_384K = 22,
> > +};
> > +
> > +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_info(dev, "%s(), rate %u invalid, use %d!!!\n",
> > +			 __func__,
> > +			 rate, MTK_AFE_RATE_48K);
> 
> dev_err(); ... and don't return here, but...
> 
> > +		return MTK_AFE_RATE_48K;
> > +	}
> 
> 
> ... return here, outside of the switch.
> 
> > +}
> > +
> > +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_info(dev, "%s(), rate %u invalid, use %d!!!\n",
> > +			 __func__,
> > +			 rate, MTK_AFE_TDM_RATE_48K);
> > +		return MTK_AFE_TDM_RATE_48K;
> 
> ditto.
> here and for all the other instances.
> 
> > +	}
> > +}
> > +
> 
> ...snip...
> 
> > +}
> > 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..e1e17a934245
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
> > @@ -0,0 +1,3029 @@
> > +// 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_info(afe->dev, "snd_pcm_hw_constraint_integer
> > failed\n");
> 
> 	if (ret < 0) {
> 		dev_err .....
> 		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_info(afe->dev, "%s() error: no more asys
> > irq\n",
> > +				 __func__);
> > +			ret = -EBUSY;
> 
> 			return -EBUSY;
> > +		}
> > +	}
> > +
> 
> 	return 0;
> 
> > +	return ret;
> > +}
> > +
> > +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;
> > +		goto exit;
> > +
> > +	/* 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 |
> > +			0 << CHANNEL_MERGE0_DEBUG_MODE_SFT |
> > +			0 << CM1_DEBUG_MODE_SEL_SFT;
> 
> 0 << number == 0!!!
> 
> > +		mask = CM1_FS_SELECT_MASK_SFT |
> > +			CHANNEL_MERGE0_CHNUM_MASK_SFT |
> > +			CHANNEL_MERGE0_UPDATE_CNT_MASK_SFT |
> > +			CHANNEL_MERGE0_DEBUG_MODE_MASK_SFT |
> > +			CM1_DEBUG_MODE_SEL_MASK_SFT;
> > +		regmap_update_bits(afe->regmap, AFE_CM1_CON, mask,
> > val);
> > +	}
> > +
> 
> 	return 0;
> 
> ... and remove the label, as it's not needed
> > +exit:
> > +	return ret;
> > +}
> > +
> > +static int mt8186_fe_hw_free(struct snd_pcm_substream *substream,
> > +			     struct snd_soc_dai *dai)
> > +{
> > +	int ret;
> > +
> > +	ret = mtk_afe_fe_hw_free(substream, dai);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	/* wait for some platform related operation */
> > +exit:
> > +	return ret;
> > +}
> > +
> > +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 counter = runtime->period_size;
> > +	unsigned int rate = runtime->rate;
> > +	int fs;
> > +	int ret;
> > +
> > +	dev_info(afe->dev, "%s(), %s cmd %d, irq_id %d\n",
> > +		 __func__, memif->data->name, cmd, irq_id);
> 
> 
> dev_dbg()
> 
> > +
> > +	switch (cmd) {
> > +	case SNDRV_PCM_TRIGGER_START:
> > +	case SNDRV_PCM_TRIGGER_RESUME:
> > +		ret = mtk_memif_set_enable(afe, id);
> 
> 		if (ret) {
> 			dev_err ........
> 			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)
> 				usleep_range(300, 310);
> 
> 
> > +		/*
> > +		 * for small latency record
> > +		 * ul memif need read some data before irq enable
> > +		 */
> > +		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
> > +			if ((runtime->period_size * 1000) / rate <= 10)
> > +				usleep_range(300, 310);
> > +		}
> > +
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), error, id %d, memif
> > enable, ret %d\n",
> > +				 __func__, id, ret);
> > +			return ret;
> > +		}
> > +
> > +		/* set irq counter */
> > +		if (afe_priv->irq_cnt[id] > 0)
> > +			counter = afe_priv->irq_cnt[id];
> > +
> > +		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);
> > +
> 
> empty line: remove.
> 
> > +		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);
> > +
> > +				if (avail >= runtime->buffer_size) {
> > +					dev_info(afe->dev, "%s(), id
> > %d, xrun assert\n",
> > +						 __func__, id);
> > +				}
> > +			}
> > +		}
> > +
> > +		ret = mtk_memif_set_disable(afe, id);
> > +		if (ret) {
> > +			dev_info(afe->dev, "%s(), error, id %d, memif
> > enable, ret %d\n",
> > +				 __func__, id, ret);
> 
> dev_err()
> 
> > +		}
> > +
> > +		/* 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;
> > +	else
> 
> drop "else"... and just return MT8186_MEMIF_PBUF_SIZE_32_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;
> 
> > +		goto exit;
> > +
> > +	/* 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);
> > +exit:
> 
> unneeded label, and return 0;
> 
> > +	return ret;
> > +}
> > +
> 
> ..snip..
> 
> > +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_info(afe->dev, "%s(), irq_id %d, irq_cnt = %d, value =
> > %ld\n",
> > +		 __func__,
> > +		 irq_id, irq_cnt,
> > +		 ucontrol->value.integer.value[0]);
> 
> dev_dbg() - and fits in less lines.
> 
> > +
> > +	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) {
> > +		dev_info(afe->dev, "%s(), suspended || irq_id %d, not
> > set\n",
> > +			 __func__, irq_id);
> > +	} else {
> > +		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);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +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_info(afe->dev, "%s(), irq_id %d, irq_cnt = %d, value =
> > %ld\n",
> > +		 __func__,
> > +		 irq_id, irq_cnt,
> > +		 ucontrol->value.integer.value[0]);
> 
> dev_dbg() - and fits in less lines.
> 
> > +
> > +	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) {
> > +		dev_info(afe->dev, "%s(), suspended || irq_id %d, not
> > set\n",
> > +			 __func__, irq_id);
> > +	} else {
> > +		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);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> 
> 
> 
> > +
> > +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 */
> > +	regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en);
> 
> ret = regmap_read ....
> if (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_info(afe->dev, "%s(), irq status err, ret %d,
> > status 0x%x, mcu_en 0x%x\n",
> > +			 __func__, ret, status, mcu_en);
> 
> dev_err()
> 
> > +
> > +		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);
> 
> fits in a single line.
> 
> > +
> > +	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_info(afe->dev, "%s(), ret %d\n", __func__, ret);
> 
> dev_err()!!
> P.S.: Are you sure that we shouldn't return here?

No, this should return error, I will correct here.

> 
> > +
> > +	/* 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, 0x1 << 29, 0x1 << 29);
> 
> BIT(29)
> 
> > +	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 0x1 << 29, 0x1
> > << 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 <<
> > CPU_HD_ALIGN_SFT);
> 
> 0 << number == 0, so write 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, 0x1, 0x1);
> > +
> > +skip_regmap:
> > +	return 0;
> > +}
> 
> ..snip..
> 
> > +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;
> > +
> > +	dev_info(dev, "%s(), ++\n", __func__);
> 
> Drop this print.
> 
> > +
> > +	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(&pdev->dev, res);
> > +	if (IS_ERR(afe->base_addr))
> > +		return PTR_ERR(afe->base_addr);
> > +
> > +	dev_info(dev, "%s(), mt8186_init_clock\n", __func__);
> 
> Drop this print.
> 
> > +	/* init audio related clock */
> > +	ret = mt8186_init_clock(afe);
> > +	if (ret) {
> > +		dev_info(dev, "init clock error\n");
> 
> dev_err()
> 
> > +		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
> > */
> > +
> > +	dev_info(dev, "%s(), init irq\n", __func__);
> 
> Drop this print.
> 
> > +
> > +	/* 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];
> > +
> > +	dev_info(dev, "%s(), devm_request_irq\n", __func__);
> 
> Drop.
> 
> > +
> > +	/* request irq */
> > +	irq_id = platform_get_irq(pdev, 0);
> > +	if (irq_id <= 0) {
> > +		dev_info(dev, "%pOFn no irq found\n", dev->of_node);
> 
> 		return dev_err_probe(dev, irq_id < 0 ? irq_id : -ENXIO,
> 				     "no irq found");
> 
> > +		return irq_id < 0 ? irq_id : -ENXIO;
> > +	}
> > +	ret = devm_request_irq(dev, irq_id, mt8186_afe_irq_handler,
> > +			       IRQF_TRIGGER_NONE,
> > +			       "Afe_ISR_Handle", (void *)afe);
> > +	if (ret) {
> > +		dev_info(dev, "could not request_irq for
> > Afe_ISR_Handle\n");
> 
> return dev_err_probe(dev, ret, "could not request Afe_ISR_Handle
> irq\n");
> 
> > +		return ret;
> > +	}
> > +
> > +	ret = enable_irq_wake(irq_id);
> > +	if (ret < 0)
> > +		dev_info(dev, "enable_irq_wake %d err: %d\n", irq_id,
> > ret);
> 
> Isn't this a critical error?
> 		return dev_err_probe(.......
Yes it is, I will correct here that return dev_err_probe(...).

> 
> > +
> > +	/* 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_info(dev, "dai register i %d fail, ret
> > %d\n",
> > +				 i, ret);
> > +			return ret;
> 
> return dev_err_probe()
> 
> > +		}
> > +	}
> > +
> > +	dev_info(dev, "%s(), mtk_afe_combine_sub_dai\n", __func__);
> 
> drop this.
> 
> > +
> > +	/* init dai_driver and component_driver */
> > +	ret = mtk_afe_combine_sub_dai(afe);
> > +	if (ret) {
> > +		dev_info(dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
> > +			 ret);
> > +		return ret;
> 
> return dev_err_probe()
> 
> > +	}
> > +
> > +	/* reset controller to reset audio regs before regmap cache */
> > +	rstc = devm_reset_control_get_exclusive(dev, "audiosys");
> > +	if (IS_ERR(rstc)) {
> > +		ret = PTR_ERR(rstc);
> > +		dev_info(dev, "could not get audiosys reset:%d\n",
> > ret);
> > +		return ret;
> 
> return dev_err_probe(dev, PTR_ERR(rstc), "Could not get audiosys
> reset\n");
> 
> > +	}
> > +
> > +	ret = reset_control_reset(rstc);
> > +	if (ret) {
> > +		dev_info(dev, "failed to trigger audio reset:%d\n",
> > ret);
> > +		return ret;
> 
> dev_err_probe()
> 
> > +	}
> > +
> > +	/* enable clock for regcache get default value from hw */
> > +	afe_priv->pm_runtime_bypass_reg_ctl = true;
> > +	pm_runtime_enable(dev);
> > +	ret = pm_runtime_get_sync(dev);
> > +	if (ret)
> > +		dev_info(dev, "get_ret:%d, rpm_error:%d\n",
> > +			 ret, dev->power.runtime_error);
> 
> You should also return the error here.
> 
> > +
> > +	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_info(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_info(dev, "err_dai_component\n");
> 
> dev_err()
> 
> > +		goto err_pm_disable;
> > +	}
> > +
> > +	ret = pm_runtime_put_sync(dev);
> > +	if (ret)
> > +		dev_info(dev, "put_ret:%d, rpm_error:%d\n",
> > +			 ret, dev->power.runtime_error);
> 
> dev_err()
> 
> > +	afe_priv->pm_runtime_bypass_reg_ctl = false;
> > +
> > +	regcache_cache_only(afe->regmap, true);
> > +	regcache_mark_dirty(afe->regmap);
> > +
> > +	dev_info(dev, "%s(), --\n", __func__);
> > +
> > +	return 0;
> > +
> > +err_pm_disable:
> > +	pm_runtime_put_sync(dev);
> > +	pm_runtime_disable(dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static int mt8186_afe_pcm_dev_remove(struct platform_device *pdev)
> > +{
> > +	struct mtk_base_afe *afe = platform_get_drvdata(pdev);
> > +
> > +	pm_runtime_disable(&pdev->dev);
> > +	if (!pm_runtime_status_suspended(&pdev->dev))
> > +		mt8186_afe_runtime_suspend(&pdev->dev);
> > +
> > +	mt8186_deinit_clock(afe);
> > +
> > +	return 0;
> > +}
> > +
> > +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,
> > +	.remove = mt8186_afe_pcm_dev_remove,
> > +};
> > +
> > +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-interconnection.h
> > b/sound/soc/mediatek/mt8186/mt8186-interconnection.h
> > new file mode 100644
> > index 000000000000..5b188d93ebd3
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-interconnection.h
> > @@ -0,0 +1,69 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + *
> > + * Mediatek MT8186 audio driver interconnection definition
> > + *
> > + * Copyright (c) 2022 MediaTek Inc.
> > + * Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > + */
> > +
> > +#ifndef _MT8186_INTERCONNECTION_H_
> > +#define _MT8186_INTERCONNECTION_H_
> > +
> > +/* in port define */
> > +#define I_I2S0_CH1 0
> > +#define I_I2S0_CH2 1
> > +#define I_ADDA_UL_CH1 3
> > +#define I_ADDA_UL_CH2 4
> > +#define I_DL1_CH1 5
> > +#define I_DL1_CH2 6
> > +#define I_DL2_CH1 7
> > +#define I_DL2_CH2 8
> > +#define I_PCM_1_CAP_CH1 9
> > +#define I_GAIN1_OUT_CH1 10
> > +#define I_GAIN1_OUT_CH2 11
> > +#define I_GAIN2_OUT_CH1 12
> > +#define I_GAIN2_OUT_CH2 13
> > +#define I_PCM_2_CAP_CH1 14
> > +#define I_ADDA_UL_CH3 17
> > +#define I_ADDA_UL_CH4 18
> > +#define I_DL12_CH1 19
> > +#define I_DL12_CH2 20
> > +#define I_DL12_CH3 5
> > +#define I_DL12_CH4 6
> > +#define I_PCM_2_CAP_CH2 21
> > +#define I_PCM_1_CAP_CH2 22
> > +#define I_DL3_CH1 23
> > +#define I_DL3_CH2 24
> > +#define I_I2S2_CH1 25
> > +#define I_I2S2_CH2 26
> > +#define I_I2S2_CH3 27
> > +#define I_I2S2_CH4 28
> > +
> > +/* in port define >= 32 */
> > +#define I_32_OFFSET 32
> > +#define I_CONNSYS_I2S_CH1 (34 - I_32_OFFSET)
> > +#define I_CONNSYS_I2S_CH2 (35 - I_32_OFFSET)
> > +#define I_SRC_1_OUT_CH1 (36 - I_32_OFFSET)
> > +#define I_SRC_1_OUT_CH2 (37 - I_32_OFFSET)
> > +#define I_SRC_2_OUT_CH1 (38 - I_32_OFFSET)
> > +#define I_SRC_2_OUT_CH2 (39 - I_32_OFFSET)
> > +#define I_DL4_CH1 (40 - I_32_OFFSET)
> > +#define I_DL4_CH2 (41 - I_32_OFFSET)
> > +#define I_DL5_CH1 (42 - I_32_OFFSET)
> > +#define I_DL5_CH2 (43 - I_32_OFFSET)
> > +#define I_DL6_CH1 (44 - I_32_OFFSET)
> > +#define I_DL6_CH2 (45 - I_32_OFFSET)
> > +#define I_DL7_CH1 (46 - I_32_OFFSET)
> > +#define I_DL7_CH2 (47 - I_32_OFFSET)
> > +#define I_DL8_CH1 (48 - I_32_OFFSET)
> > +#define I_DL8_CH2 (49 - I_32_OFFSET)
> > +#define I_TDM_IN_CH1 (56 - I_32_OFFSET)
> > +#define I_TDM_IN_CH2 (57 - I_32_OFFSET)
> > +#define I_TDM_IN_CH3 (58 - I_32_OFFSET)
> > +#define I_TDM_IN_CH4 (59 - I_32_OFFSET)
> > +#define I_TDM_IN_CH5 (60 - I_32_OFFSET)
> > +#define I_TDM_IN_CH6 (61 - I_32_OFFSET)
> > +#define I_TDM_IN_CH7 (62 - I_32_OFFSET)
> > +#define I_TDM_IN_CH8 (63 - I_32_OFFSET)
> > +
> > +#endif
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-misc-control.c
> > b/sound/soc/mediatek/mt8186/mt8186-misc-control.c
> > new file mode 100644
> > index 000000000000..c097248b37b6
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-misc-control.c
> > @@ -0,0 +1,1728 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// MediaTek ALSA SoC Audio Misc Control
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/delay.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/io.h>
> > +#include <linux/regmap.h>
> > +#include <sound/soc.h>
> > +
> > +#include "../common/mtk-afe-fe-dai.h"
> > +#include "../common/mtk-afe-platform-driver.h"
> > +#include "mt8186-afe-common.h"
> > +
> > +#define SGEN_MUTE_CH1_KCONTROL_NAME "Audio_SineGen_Mute_Ch1"
> > +#define SGEN_MUTE_CH2_KCONTROL_NAME "Audio_SineGen_Mute_Ch2"
> > +
> > +static const char * const mt8186_sgen_mode_str[] = {
> > +	"I0I1",   "I2",     "I3I4",   "I5I6",
> > +	"I7I8",   "I9I22",  "I10I11", "I12I13",
> > +	"I14I21", "I15I16", "I17I18", "I19I20",
> > +	"I23I24", "I25I26", "I27I28", "I33",
> > +	"I34I35", "I36I37", "I38I39", "I40I41",
> > +	"I42I43", "I44I45", "I46I47", "I48I49",
> > +	"I56I57", "I58I59", "I60I61", "I62I63",
> > +	"O0O1",   "O2",     "O3O4",   "O5O6",
> > +	"O7O8",   "O9O10",  "O11",    "O12",
> > +	"O13O14", "O15O16", "O17O18", "O19O20",
> > +	"O21O22", "O23O24", "O25",    "O28O29",
> > +	"O34",    "O35",    "O32O33", "O36O37",
> > +	"O38O39", "O30O31", "O40O41", "O42O43",
> > +	"O44O45", "O46O47", "O48O49", "O50O51",
> > +	"O58O59", "O60O61", "O62O63", "O64O65",
> > +	"O66O67", "O68O69", "O26O27", "OFF",
> > +};
> > +
> > +static const int mt8186_sgen_mode_idx[] = {
> > +	0, 2, 4, 6,
> > +	8, 22, 10, 12,
> > +	14, -1, 18, 20,
> > +	24, 26, 28, 33,
> > +	34, 36, 38, 40,
> > +	42, 44, 46, 48,
> > +	56, 58, 60, 62,
> > +	128, 130, 132, 134,
> > +	135, 138, 139, 140,
> > +	142, 144, 166, 148,
> > +	150, 152, 153, 156,
> > +	162, 163, 160, 164,
> > +	166, -1, 168, 170,
> > +	172, 174, 176, 178,
> > +	186, 188, 190, 192,
> > +	194, 196, -1, -1,
> > +};
> > +
> > +static const char * const mt8186_sgen_rate_str[] = {
> > +	"8K", "11K", "12K", "16K",
> > +	"22K", "24K", "32K", "44K",
> > +	"48K", "88k", "96k", "176k",
> > +	"192k"
> > +};
> > +
> > +static const int mt8186_sgen_rate_idx[] = {
> > +	0, 1, 2, 4,
> > +	5, 6, 8, 9,
> > +	10, 11, 12, 13,
> > +	14
> > +};
> > +
> > +/* this order must match reg bit amp_div_ch1/2 */
> > +static const char * const mt8186_sgen_amp_str[] = {
> > +	"1/128", "1/64", "1/32", "1/16", "1/8", "1/4", "1/2", "1" };
> > +static const char * const mt8186_sgen_mute_str[] = {
> > +	"Off", "On"
> > +};
> > +
> > +static int mt8186_sgen_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->sgen_mode;
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_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;
> > +	struct soc_enum *e = (struct soc_enum *)kcontrol-
> > >private_value;
> > +	int mode;
> > +	int mode_idx;
> > +
> > +	if (ucontrol->value.enumerated.item[0] >= e->items)
> > +		return -EINVAL;
> > +
> > +	mode = ucontrol->value.integer.value[0];
> > +	mode_idx = mt8186_sgen_mode_idx[mode];
> > +
> > +	dev_info(afe->dev, "%s(), mode %d, mode_idx %d\n",
> > +		 __func__, mode, mode_idx);
> > +
> > +	if (mode_idx >= 0) {
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2,
> > +				   INNER_LOOP_BACK_MODE_MASK_SFT,
> > +				   mode_idx <<
> > INNER_LOOP_BACK_MODE_SFT);
> > +		//regmap_write(afe->regmap, AFE_SINEGEN_CON0,
> > 0x04ac2ac1);
> 
> Why is this commented out?
> Either remove the comment, or remove the line entirely.
> 
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +				   DAC_EN_MASK_SFT,
> > +				   0x1 << DAC_EN_SFT);
> 
> BIT()
> 
> > +	} else {
> > +		/* disable sgen */
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +				   DAC_EN_MASK_SFT,
> > +				   0x0);
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2,
> > +				   INNER_LOOP_BACK_MODE_MASK_SFT,
> > +				   0x3f << INNER_LOOP_BACK_MODE_SFT);
> > +	}
> > +
> > +	afe_priv->sgen_mode = mode;
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_rate_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->sgen_rate;
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_rate_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;
> > +	struct soc_enum *e = (struct soc_enum *)kcontrol-
> > >private_value;
> > +	int rate;
> > +
> > +	if (ucontrol->value.enumerated.item[0] >= e->items)
> > +		return -EINVAL;
> > +
> > +	rate = ucontrol->value.integer.value[0];
> > +
> > +	dev_info(afe->dev, "%s(), rate %d\n", __func__, rate);
> 
> dev_dbg()
> 
> > +
> > +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +			   SINE_MODE_CH1_MASK_SFT,
> > +			   mt8186_sgen_rate_idx[rate] <<
> > SINE_MODE_CH1_SFT);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +			   SINE_MODE_CH2_MASK_SFT,
> > +			   mt8186_sgen_rate_idx[rate] <<
> > SINE_MODE_CH2_SFT);
> > +
> > +	afe_priv->sgen_rate = rate;
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_amplitude_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->sgen_amplitude;
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_amplitude_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;
> > +	struct soc_enum *e = (struct soc_enum *)kcontrol-
> > >private_value;
> > +	int amplitude;
> > +
> > +	if (ucontrol->value.enumerated.item[0] >= e->items)
> > +		return -EINVAL;
> > +
> > +	amplitude = ucontrol->value.integer.value[0];
> > +	if (amplitude > AMP_DIV_CH1_MASK) {
> > +		dev_info(afe->dev, "%s(), amplitude %d invalid\n",
> > +			 __func__, amplitude);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_info(afe->dev, "%s(), amplitude %d\n", __func__,
> > amplitude);
> > +
> > +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +			   AMP_DIV_CH1_MASK_SFT,
> > +			   amplitude << AMP_DIV_CH1_SFT);
> > +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +			   AMP_DIV_CH2_MASK_SFT,
> > +			   amplitude << AMP_DIV_CH2_SFT);
> > +
> > +	afe_priv->sgen_amplitude = amplitude;
> > +
> > +	return 0;
> > +}
> > +
> > +static int mt8186_sgen_mute_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);
> > +	int mute;
> > +
> > +	regmap_read(afe->regmap, AFE_SINEGEN_CON0, &mute);
> > +
> > +	if (strcmp(kcontrol->id.name, SGEN_MUTE_CH1_KCONTROL_NAME) ==
> > 0)
> > +		return (mute >> MUTE_SW_CH1_SFT) & MUTE_SW_CH1_MASK;
> > +	else
> > +		return (mute >> MUTE_SW_CH2_SFT) & MUTE_SW_CH2_MASK;
> 
> 	if (strcmp(kcontrol->id.name, SGEN_MUTE_CH1_KCONTROL_NAME) ==
> 0)
> 		return (mute >> MUTE_SW_CH1_SFT) & MUTE_SW_CH1_MASK;
> 
> 	return (mute >> MUTE_SW_CH2_SFT) & MUTE_SW_CH2_MASK;
> 
> > +}
> > +
> > +static int mt8186_sgen_mute_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 soc_enum *e = (struct soc_enum *)kcontrol-
> > >private_value;
> > +	int mute;
> > +
> > +	if (ucontrol->value.enumerated.item[0] >= e->items)
> > +		return -EINVAL;
> > +
> > +	mute = ucontrol->value.integer.value[0];
> > +
> > +	dev_info(afe->dev, "%s(), kcontrol name %s, mute %d\n",
> > +		 __func__, kcontrol->id.name, mute);
> 
> dev_dbg()
> 
> > +
> > +	if (strcmp(kcontrol->id.name, SGEN_MUTE_CH1_KCONTROL_NAME) ==
> > 0) {
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +				   MUTE_SW_CH1_MASK_SFT,
> > +				   mute << MUTE_SW_CH1_SFT);
> > +	} else {
> > +		regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0,
> > +				   MUTE_SW_CH2_MASK_SFT,
> > +				   mute << MUTE_SW_CH2_SFT);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct soc_enum mt8186_afe_sgen_enum[] = {
> > +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_mode_str),
> > +			    mt8186_sgen_mode_str),
> > +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_rate_str),
> > +			    mt8186_sgen_rate_str),
> > +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_amp_str),
> > +			    mt8186_sgen_amp_str),
> > +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_mute_str),
> > +			    mt8186_sgen_mute_str),
> > +};
> > +
> > +static const struct snd_kcontrol_new mt8186_afe_sgen_controls[] =
> > {
> > +	SOC_ENUM_EXT("Audio_SineGen_Switch", mt8186_afe_sgen_enum[0],
> > +		     mt8186_sgen_get, mt8186_sgen_set),
> > +	SOC_ENUM_EXT("Audio_SineGen_SampleRate",
> > mt8186_afe_sgen_enum[1],
> > +		     mt8186_sgen_rate_get, mt8186_sgen_rate_set),
> > +	SOC_ENUM_EXT("Audio_SineGen_Amplitude",
> > mt8186_afe_sgen_enum[2],
> > +		     mt8186_sgen_amplitude_get,
> > mt8186_sgen_amplitude_set),
> > +	SOC_ENUM_EXT(SGEN_MUTE_CH1_KCONTROL_NAME,
> > mt8186_afe_sgen_enum[3],
> > +		     mt8186_sgen_mute_get, mt8186_sgen_mute_set),
> > +	SOC_ENUM_EXT(SGEN_MUTE_CH2_KCONTROL_NAME,
> > mt8186_afe_sgen_enum[3],
> > +		     mt8186_sgen_mute_get, mt8186_sgen_mute_set),
> > +	SOC_SINGLE("Audio_SineGen_Freq_Div_Ch1", AFE_SINEGEN_CON0,
> > +		   FREQ_DIV_CH1_SFT, FREQ_DIV_CH1_MASK, 0),
> > +	SOC_SINGLE("Audio_SineGen_Freq_Div_Ch2", AFE_SINEGEN_CON0,
> > +		   FREQ_DIV_CH2_SFT, FREQ_DIV_CH2_MASK, 0),
> > +};
> > +
> > +/* audio debug log */
> > +static const char * const mt8186_afe_off_on_str[] = {
> > +	"Off", "On"
> > +};
> > +
> > +static int mt8186_afe_debug_get(struct snd_kcontrol *kcontrol,
> > +				struct snd_ctl_elem_value *ucontrol)
> > +{
> > +	return 0;
> > +}
> > +
> > +static int mt8186_afe_debug_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);
> > +	unsigned int value;
> > +
> 
> This should be debugfs, instead of spitting a full register dump in
> the kmsg:
> doing so is horrible (sorry).
Yes, I will remove them in next version.

> 
> > +	regmap_read(afe->regmap, AUDIO_TOP_CON0, &value);
> > +	dev_info(afe->dev, "AUDIO_TOP_CON0 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AUDIO_TOP_CON1, &value);
> > +	dev_info(afe->dev, "AUDIO_TOP_CON1 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AUDIO_TOP_CON2, &value);
> > +	dev_info(afe->dev, "AUDIO_TOP_CON2 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AUDIO_TOP_CON3, &value);
> > +	dev_info(afe->dev, "AUDIO_TOP_CON3 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AFE_DAC_CON0, &value);
> > +	dev_info(afe->dev, "AFE_DAC_CON0 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AFE_I2S_CON, &value);
> > +	dev_info(afe->dev, "AFE_I2S_CON = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AFE_CONN0, &value);
> > +	dev_info(afe->dev, "AFE_CONN0 = 0x%x\n", value);
> > 
snip ...

> > +	regmap_read(afe->regmap, AFE_SECURE_MASK_CONN54_1, &value);
> > +	dev_info(afe->dev, "AFE_SECURE_MASK_CONN54_1 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AFE_SECURE_MASK_CONN55_1, &value);
> > +	dev_info(afe->dev, "AFE_SECURE_MASK_CONN55_1 = 0x%x\n", value);
> > +	regmap_read(afe->regmap, AFE_SECURE_MASK_CONN56_1, &value);
> > +	dev_info(afe->dev, "AFE_SECURE_MASK_CONN56_1 = 0x%x\n", value);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct soc_enum mt8186_afe_misc_enum[] = {
> > +	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_afe_off_on_str),
> > +			    mt8186_afe_off_on_str),
> > +};
> > +
> > +static const struct snd_kcontrol_new mt8186_afe_debug_controls[] =
> > {
> > +	SOC_ENUM_EXT("Audio_Debug_Setting", mt8186_afe_misc_enum[0],
> > +		     mt8186_afe_debug_get, mt8186_afe_debug_set),
> > +};
> > +
> > +int mt8186_add_misc_control(struct snd_soc_component *component)
> > +{
> > +	snd_soc_add_component_controls(component,
> > +				       mt8186_afe_sgen_controls,
> > +				       ARRAY_SIZE(mt8186_afe_sgen_contr
> > ols));
> > +
> > +	snd_soc_add_component_controls(component,
> > +				       mt8186_afe_debug_controls,
> > +				       ARRAY_SIZE(mt8186_afe_debug_cont
> > rols));
> > +
> > +	return 0;
> > +}

_______________________________________________
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] 44+ messages in thread

* Re: [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-05 10:49     ` Jiaxin Yu
  2022-03-07  9:25       ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05 10:49 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch adds mt8186 adda dai driver
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 891
> > ++++++++++++++++++++
> >   1 file changed, 891 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> > b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> > new file mode 100644
> > index 000000000000..6d7dd1533da0
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
> > @@ -0,0 +1,891 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// MediaTek ALSA SoC Audio DAI ADDA Control
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/regmap.h>
> > +#include <linux/delay.h>
> > +#include "mt8186-afe-clk.h"
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-gpio.h"
> > +#include "mt8186-interconnection.h"
> > +
...snip...
> > 
> > +/* dai ops */
> > +static int mtk_dai_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);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	unsigned int rate = params_rate(params);
> > +	int id = dai->id;
> > +	struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id];
> > +
> > +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> > +		 __func__,
> > +		 id,
> > +		 substream->stream,
> > +		 rate);
> > +
> > +	if (!adda_priv) {
> > +		dev_info(afe->dev, "%s(), adda_priv == NULL",
> > __func__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> > +		unsigned int dl_src2_con0 = 0;
> > +		unsigned int dl_src2_con1 = 0;
> 
> This initialization is redundant: you're never using these variables
> before initializing them later, so initializing them to zero is not
> needed here.
Yes, got it. Thank you.
> 
> > +
> > +		adda_priv->dl_rate = rate;
> > +
> > +		/* set sampling rate */
> > +		dl_src2_con0 = adda_dl_rate_transform(afe, rate) <<
> > +			       DL_2_INPUT_MODE_CTL_SFT;
> > +
> > +		/* set output mode, UP_SAMPLING_RATE_X8 */
> > +		dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT);
> > +
> > +		/* turn off mute function */
> > +		dl_src2_con0 |= (0x01 <<
> > DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);
> 
> BIT() macro, please
> 
> > +		dl_src2_con0 |= (0x01 <<
> > DL_2_MUTE_CH1_OFF_CTL_PRE_SFT);
> > +
> > +		/* set voice input data if input sample rate is 8k or
> > 16k */
> > +		if (rate == 8000 || rate == 16000)
> > +			dl_src2_con0 |= 0x01 <<
> > DL_2_VOICE_MODE_CTL_PRE_SFT;
> > +
> > +		/* SA suggest apply -0.3db to audio/speech path */
> > +		dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL <<
> > +			       DL_2_GAIN_CTL_PRE_SFT;
> > +
> > +		/* turn on down-link gain */
> > +		dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT);
> > +
> > +		if (id == MT8186_DAI_ADDA) {
> > +			/* clean predistortion */
> > +			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,
> > dl_src2_con0);
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_DL_SRC2_CON1,
> > dl_src2_con1);
> > +
> > +			/* set sdm gain */
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
> > +					   ATTGAIN_CTL_MASK_SFT,
> > +					   AUDIO_SDM_LEVEL_NORMAL <<
> > +					   ATTGAIN_CTL_SFT);
> > +
> > +			/* Use new 2nd sdm */
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_DL_SDM_DITHER_CON,
> > +					   AFE_DL_SDM_DITHER_64TAP_EN_M
> > ASK_SFT,
> > +					   0x1 <<
> > AFE_DL_SDM_DITHER_64TAP_EN_SFT);
> 
> BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)
> 
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_DL_SDM_AUTO_RESET_C
> > ON,
> > +					   AFE_DL_USE_NEW_2ND_SDM_MASK_
> > SFT,
> > +					   0x1 <<
> > AFE_DL_USE_NEW_2ND_SDM_SFT);
> 
> BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)
> 
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
> > +					   USE_3RD_SDM_MASK_SFT,
> > +					   AUDIO_SDM_2ND <<
> > USE_3RD_SDM_SFT);
> > +
> > +			/* sdm auto reset */
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_DL_SDM_AUTO_RESET_CON,
> > +				     SDM_AUTO_RESET_THRESHOLD);
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_DL_SDM_AUTO_RESET_C
> > ON,
> > +					   SDM_AUTO_RESET_TEST_ON_MASK_
> > SFT,
> > +					   0x1 <<
> > SDM_AUTO_RESET_TEST_ON_SFT);
> 
> BIT(SDM_AUTO_RESET_TEST_ON_SFT)
> 
> > +		}
> > +	} else {
> > +		unsigned int voice_mode = 0;
> 
> what about...
> 		unsigned int ul_src_con0 = 0; /* default value */
> 		unsigned int voice_mode =  adda_ul_rate_transform(afe,
> rate);
Agree with you.

> > +		unsigned int ul_src_con0 = 0;	/* default value */
> > +
> > +		adda_priv->ul_rate = rate;
> > +
> > +		voice_mode = adda_ul_rate_transform(afe, rate);
> > +
> > +		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
> > +
> > +		/* enable iir */
> > +		ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
> > +			       UL_IIR_ON_TMP_CTL_MASK_SFT;
> > +		ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
> > +			       UL_IIRMODE_CTL_MASK_SFT;
> > +		switch (id) {
> > +		case MT8186_DAI_ADDA:
> > +		case MT8186_DAI_AP_DMIC:
> > +			/* 35Hz @ 48k */
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_IIR_COEF_02_01,
> > 0x00000000);
> 
> Please drop leading zeroes:
> 
> regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0);
> 
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_IIR_COEF_04_03,
> > 0x00003FB8);
> 
> ... and also please write hex in lower-case:
> 
Got it.
> regmap_write(afe->regmap,
> 	     AFE_ADDA_IIR_COEF_04_03, 0x03fb8);
> 
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_IIR_COEF_06_05,
> > 0x3FB80000);
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_IIR_COEF_08_07,
> > 0x3FB80000);
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_IIR_COEF_10_09,
> > 0x0000C048);
> > +
> > +			regmap_write(afe->regmap,
> > +				     AFE_ADDA_UL_SRC_CON0,
> > ul_src_con0);
> > +
> > +			/* Using Internal ADC */
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_TOP_CON0,
> > +					   0x1 << 0,
> > +					   0x0 << 0);
> 
> Please use the BIT() macro:
> 
> regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0);
> 
> P.S.: 87 columns is ok

How can I judge whether it can exceed 80 lines?
> 
> > +
> > +			/* mtkaif_rxif_data_mode = 0, amic */
> > +			regmap_update_bits(afe->regmap,
> > +					   AFE_ADDA_MTKAIF_RX_CFG0,
> > +					   0x1 << 0,
> > +					   0x0 << 0);
> 
> same here.
> 
> > +			break;
> > +		default:
> > +			break;
> > +		}
> > +
> > +		/* ap dmic */
> > +		switch (id) {
> > +		case MT8186_DAI_AP_DMIC:
> > +			mtk_adda_ul_src_dmic(afe, id);
> > +			break;
> > +		default:
> > +			break;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> 
> Regards,
> Angelo
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 06/17] ASoC: mediatek: mt8186: support i2s in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-05 11:07     ` Jiaxin Yu
  0 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05 11:07 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch adds mt8186 i2s dai driver
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-dai-i2s.c | 1371
> > ++++++++++++++++++++
> >   1 file changed, 1371 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> > b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> > new file mode 100644
> > index 000000000000..d6db5f6a7315
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
> > @@ -0,0 +1,1371 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// MediaTek ALSA SoC Audio DAI I2S Control
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/regmap.h>
> > +#include <sound/pcm_params.h>
> > +#include "mt8186-afe-clk.h"
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-gpio.h"
> > +#include "mt8186-interconnection.h"
> > +
> > 
> > +static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget
> > *source,
> > +				     struct snd_soc_dapm_widget *sink)
> > +{
> > +	struct snd_soc_dapm_widget *w = sink;
> > +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w-
> > >dapm);
> > +	struct mtk_base_afe *afe =
> > snd_soc_component_get_drvdata(cmpnt);
> > +	struct mtk_afe_i2s_priv *i2s_priv;
> > +
> > +	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
> > +
> > +	if (!i2s_priv) {
> > +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
> 
> Is this an error? => dev_err()
> Is this expected? => dev_dbg()
> 
It should be an error here and use dev_err().
I will fix the rest of the similar log level issues.

> > +		return 0;
> > +	}
> > +
> > +	if (i2s_priv->share_i2s_id < 0)
> > +		return 0;
> > +
> > +	return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe,
> > source->name);
> > +}
> > +
> > +static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget
> > *source,
> > +				  struct snd_soc_dapm_widget *sink)
> > +{
> > +	struct snd_soc_dapm_widget *w = sink;
> > +	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w-
> > >dapm);
> > +	struct mtk_base_afe *afe =
> > snd_soc_component_get_drvdata(cmpnt);
> > +	struct mtk_afe_i2s_priv *i2s_priv;
> > +
> > +	i2s_priv = get_i2s_priv_by_name(afe, sink->name);
> > +
> > +	if (!i2s_priv) {
> > +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
> 
> Is this an error? => dev_err()
> Is this expected? => dev_dbg()
> 
> Please fix all of the other instances of this.
> 
Yes, I know.

> > +		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;
> > +
> > +	/* check if share i2s need hd en */
> > +	if (i2s_priv->share_i2s_id < 0)
> > +		return 0;
> > +
> > +	if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source-
> > >name))
> > +		return i2s_priv->low_jitter_en;
> > +
> > +	return 0;
> > +}
> > +
> 
> ..snip...
> 
> > +
> > +/* dai ops */
> > +static int mtk_dai_connsys_i2s_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 rate = params_rate(params);
> > +	unsigned int rate_reg = mt8186_rate_transform(afe->dev,
> > +						      rate, dai->id);
> > +	unsigned int i2s_con = 0;
> > +
> > +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
> > +		 __func__,
> > +		 dai->id,
> > +		 substream->stream,
> > +		 rate);
> > +
> > +	/* non-inverse, i2s mode, slave, 16bits, from connsys */
> > +	i2s_con |= 0 << INV_PAD_CTRL_SFT;
> > +	i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
> > +	i2s_con |= 1 << I2S_SRC_SFT;
> > +	i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) <<
> > I2S_WLEN_SFT;
> > +	i2s_con |= 0 << I2SIN_PAD_SEL_SFT;
> > +	regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);
> > +
> > +	/* use asrc */
> > +	regmap_update_bits(afe->regmap,
> > +			   AFE_CONNSYS_I2S_CON,
> > +			   I2S_BYPSRC_MASK_SFT,
> > +			   0x0 << I2S_BYPSRC_SFT);
> 
> Zero shifted of a billion bits is still zero.
> 
Got it.

> regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,
> I2S_BYPSRC_MASK_SFT, 0);
> 
> > +
> > +	/* slave mode, set i2s for asrc */
> > +	regmap_update_bits(afe->regmap,
> > +			   AFE_CONNSYS_I2S_CON,
> > +			   I2S_MODE_MASK_SFT,
> > +			   rate_reg << I2S_MODE_SFT);
> 
> 	regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,
> 
> 			   I2S_MODE_MASK_SFT, rate_reg <<
> I2S_MODE_SFT);
> 
> > +
> > +	if (rate == 44100)
> > +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3,
> > 0x001B9000);
> 
> lower case hex, please, and no leading zeros.
> 
Got it.
> > +	else if (rate == 32000)
> > +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);
> > +	else
> > +		regmap_write(afe->regmap, AFE_ASRC_2CH_CON3,
> > 0x001E0000);
> > +
> > +	/* Calibration setting */
> > +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x00140000);
> > +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x00036000);
> > +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x0002FC00);
> > +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x00007EF4);
> > +	regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0x00FF5986);
> 

snip...
> > +
> > +	if (i2s_priv)
> > +		i2s_priv->rate = rate;
> > +	else
> > +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
> 
> I'm not sure about this print, maybe this should also be dev_dbg()
> 
It should be return error.
> > +
> > +	switch (i2s_id) {
> > +	case MT8186_DAI_I2S_0:
> > +		i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
> > +		i2s_con |= rate_reg << I2S_OUT_MODE_SFT;
> > +		i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
> > +		i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
> > +		regmap_update_bits(afe->regmap, AFE_I2S_CON,
> > +				   0xffffeffa, i2s_con);
> > +		break;
> > +	case MT8186_DAI_I2S_1:
> > +		i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;
> > +		i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;
> > +		i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;
> > +		i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;
> > +		regmap_update_bits(afe->regmap, AFE_I2S_CON1,
> > +				   0xffffeffa, i2s_con);
> > +		break;
> > +	case MT8186_DAI_I2S_2:
> > +		i2s_con = 8 << I2S3_UPDATE_WORD_SFT;
> > +		i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;
> > +		i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;
> > +		i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;
> > +		regmap_update_bits(afe->regmap, AFE_I2S_CON2,
> > +				   0xffffeffa, i2s_con);
> > +		break;
> > +	case MT8186_DAI_I2S_3:
> > +		i2s_con = rate_reg << I2S4_OUT_MODE_SFT;
> > +		i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;
> > +		i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;
> > +		regmap_update_bits(afe->regmap, AFE_I2S_CON3,
> > +				   0xffffeffa, i2s_con);
> > +		break;
> > +	default:
> > +		dev_info(afe->dev, "%s(), id %d not support\n",
> > +			 __func__, i2s_id);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* set share i2s */
> > +	if (i2s_priv && i2s_priv->share_i2s_id >= 0)
> > +		ret = mtk_dai_i2s_config(afe, params, i2s_priv-
> > >share_i2s_id);
> > +
> 
> 	if (i2s_priv && i2s_priv->share_i2s_id >= 0) {
> 
> 		ret = mtk_dai_i2s_config(afe, params, i2s_priv-
> >share_i2s_id);
> 
> 		if (ret)
> 
> 			return ret;
> 
> 	}
> 
> 
> 
> 	return 0;
> 
> > +	return ret;
> > +}
> > +
> > +static int mtk_dai_i2s_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);
> > +
> > +	return mtk_dai_i2s_config(afe, params, dai->id);
> > +}
> > +
> > +static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
> > +				  int clk_id, unsigned int freq, int
> > dir)
> > +{
> > +	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai-
> > >id];
> > +	int apll;
> > +	int apll_rate;
> > +
> > +	if (!i2s_priv) {
> > +		dev_info(afe->dev, "%s(), i2s_priv == NULL", __func__);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (dir != SND_SOC_CLOCK_OUT) {
> > +		dev_info(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT",
> > __func__);
> 
> again...
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
> 
> dev_dbg()
> 
> > +
> > +	apll = mt8186_get_apll_by_rate(afe, freq);
> > +	apll_rate = mt8186_get_apll_rate(afe, apll);
> > +
> > +	if (freq > apll_rate) {
> > +		dev_info(afe->dev, "%s(), freq > apll rate", __func__);
> 
> dev_err() .... please fix the rest as well.
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (apll_rate % freq != 0) {
> > +		dev_info(afe->dev, "%s(), APLL cannot generate freq
> > Hz", __func__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	i2s_priv->mclk_rate = freq;
> > +	i2s_priv->mclk_apll = apll;
> > +
> > +	if (i2s_priv->share_i2s_id > 0) {
> > +		struct mtk_afe_i2s_priv *share_i2s_priv;
> > +
> > +		share_i2s_priv = afe_priv->dai_priv[i2s_priv-
> > >share_i2s_id];
> > +		if (!share_i2s_priv) {
> > +			dev_info(afe->dev, "%s(), share_i2s_priv ==
> > NULL", __func__);
> > +			return -EINVAL;
> > +		}
> > +
> > +		share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
> > +		share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> 
> Regards,
> Angelo
> 
_______________________________________________
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] 44+ messages in thread

* Re: [v2 07/17] ASoC: mediatek: mt8186: support pcm in platform driver
  2022-02-18 14:54   ` AngeloGioacchino Del Regno
@ 2022-03-05 11:12     ` Jiaxin Yu
  0 siblings, 0 replies; 44+ messages in thread
From: Jiaxin Yu @ 2022-03-05 11:12 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
> > This patch adds mt8186 pcm dai driver.
> > 
> > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > ---
> >   sound/soc/mediatek/mt8186/mt8186-dai-pcm.c | 432
> > +++++++++++++++++++++
> >   1 file changed, 432 insertions(+)
> >   create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> > 
> > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> > b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> > new file mode 100644
> > index 000000000000..73b3f720ed35
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c
> > @@ -0,0 +1,432 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// MediaTek ALSA SoC Audio DAI I2S Control
> > +//
> > +// Copyright (c) 2022 MediaTek Inc.
> > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
> > +
> > +#include <linux/regmap.h>
> > +#include <sound/pcm_params.h>
> > +#include "mt8186-afe-common.h"
> > +#include "mt8186-afe-gpio.h"
> > +#include "mt8186-interconnection.h"
> > +
> > +struct mtk_afe_pcm_priv {
> > +	unsigned int id;
> > +	unsigned int fmt;
> > +	unsigned int bck_invert;
> > +	unsigned int lck_invert;
> > +};
> > +
> > +enum AUD_TX_LCH_RPT {
> 
> lowercase enumeration names please...
> 
> enum aud_tx_lch_rpt {
> 	AUD_TX....BLAH
> };
> 
Ok, I will fix them.

> > +	AUD_TX_LCH_RPT_NO_REPEAT = 0,
> > +	AUD_TX_LCH_RPT_REPEAT = 1
> > +};
> > +
> > +enum AUD_VBT_16K_MODE {
> > +	AUD_VBT_16K_MODE_DISABLE = 0,
> > +	AUD_VBT_16K_MODE_ENABLE = 1
> > +};
> > +
> > +enum AUD_EXT_MODEM {
> > +	AUD_EXT_MODEM_SELECT_INTERNAL = 0,
> > +	AUD_EXT_MODEM_SELECT_EXTERNAL = 1
> > +};
> > +
> > +enum AUD_PCM_SYNC_TYPE {
> > +	/* bck sync length = 1 */
> > +	AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
> > +	/* bck sync length = PCM_INTF_CON1[9:13] */
> > +	AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
> > +};
> > +
> > +enum AUD_BT_MODE {
> > +	AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
> > +	AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
> > +};
> > +
> > +enum AUD_PCM_AFIFO_SRC {
> > +	/* slave mode & external modem uses different crystal */
> > +	AUD_PCM_AFIFO_ASRC = 0,
> > +	/* slave mode & external modem uses the same crystal */
> > +	AUD_PCM_AFIFO_AFIFO = 1
> > +};
> > +
> > +enum AUD_PCM_CLOCK_SOURCE {
> > +	AUD_PCM_CLOCK_MASTER_MODE = 0,
> > +	AUD_PCM_CLOCK_SLAVE_MODE = 1
> > +};
> > +
> > +enum AUD_PCM_WLEN {
> > +	AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
> > +	AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
> > +};
> > +
> > +enum AUD_PCM_24BIT {
> > +	AUD_PCM_24BIT_PCM_16_BITS = 0,
> > +	AUD_PCM_24BIT_PCM_24_BITS = 1
> > +};
> > +
> > +enum AUD_PCM_MODE {
> > +	AUD_PCM_MODE_PCM_MODE_8K = 0,
> > +	AUD_PCM_MODE_PCM_MODE_16K = 1,
> > +	AUD_PCM_MODE_PCM_MODE_32K = 2,
> > +	AUD_PCM_MODE_PCM_MODE_48K = 3,
> > +};
> > +
> > +enum AUD_PCM_FMT {
> > +	AUD_PCM_FMT_I2S = 0,
> > +	AUD_PCM_FMT_EIAJ = 1,
> > +	AUD_PCM_FMT_PCM_MODE_A = 2,
> > +	AUD_PCM_FMT_PCM_MODE_B = 3
> > +};
> > +
> > +enum AUD_BCLK_OUT_INV {
> > +	AUD_BCLK_OUT_INV_NO_INVERSE = 0,
> > +	AUD_BCLK_OUT_INV_INVERSE = 1
> > +};
> > +
> > +enum AUD_LRCLK_OUT_INV {
> > +	AUD_LRCLK_OUT_INV_NO_INVERSE = 0,
> > +	AUD_LRCLK_OUT_INV_INVERSE = 1
> > +};
> > +
> > +enum AUD_PCM_EN {
> > +	AUD_PCM_EN_DISABLE = 0,
> > +	AUD_PCM_EN_ENABLE = 1
> > +};
> > +
> 
> ..snip..
> 
> > +
> > +/* dai ops */
> > +static int mtk_dai_pcm_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);
> > +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
> > +	int pcm_id = dai->id;
> > +	struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id];
> > +	unsigned int rate = params_rate(params);
> > +	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate,
> > dai->id);
> > +	snd_pcm_format_t format = params_format(params);
> > +	unsigned int data_width =
> > +		snd_pcm_format_width(format);
> > +	unsigned int wlen_width =
> > +		snd_pcm_format_physical_width(format);
> > +	unsigned int pcm_con = 0;
> > +
> > +	dev_info(afe->dev, "%s(), id %d, stream %d, widget active p %d,
> > c %d\n",
> > +		 __func__,
> > +		 dai->id,
> > +		 substream->stream,
> > +		 dai->playback_widget->active,
> > +		 dai->capture_widget->active);
> > +	dev_info(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d,
> > wlen_width %d\n",
> > +		 __func__,
> > +		 rate,
> > +		 rate_reg,
> > +		 data_width,
> > +		 wlen_width);
> 
> dev_dbg() - also, you don't need one line per variable.
> 

Yes, I will line them up in two.
> > +
> > +	if (dai->playback_widget->active || dai->capture_widget-
> > >active)
> > +		return 0;
> > +
> > +	switch (dai->id) {
> > +	case MT8186_DAI_PCM:
> > +		pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT <<
> > PCM_TX_LCH_RPT_SFT;
> > +		pcm_con |= AUD_VBT_16K_MODE_DISABLE <<
> > PCM_VBT_16K_MODE_SFT;
> > +		pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL <<
> > PCM_EXT_MODEM_SFT;
> > +		pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC <<
> > PCM_SYNC_TYPE_SFT;
> > +		pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX <<
> > PCM_BT_MODE_SFT;
> > +		pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
> > +		pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT;
> > +		pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
> > +
> > +		/* sampling rate */
> > +		pcm_con |= rate_reg << PCM_MODE_SFT;
> > +
> > +		/* format */
> > +		pcm_con |= pcm_priv->fmt << PCM_FMT_SFT;
> > +
> > +		/* 24bit data width */
> > +		if (data_width > 16)
> > +			pcm_con |= AUD_PCM_24BIT_PCM_24_BITS <<
> > PCM_24BIT_SFT;
> > +		else
> > +			pcm_con |= AUD_PCM_24BIT_PCM_16_BITS <<
> > PCM_24BIT_SFT;
> > +
> > +		/* wlen width*/
> > +		if (wlen_width > 16)
> > +			pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES <<
> > PCM_WLEN_SFT;
> > +		else
> > +			pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES <<
> > PCM_WLEN_SFT;
> > +
> > +		/* clock invert */
> > +		pcm_con |= pcm_priv->lck_invert <<
> > PCM_SYNC_OUT_INV_SFT;
> > +		pcm_con |= pcm_priv->bck_invert <<
> > PCM_BCLK_OUT_INV_SFT;
> > +
> > +		regmap_update_bits(afe->regmap, PCM_INTF_CON1,
> > +				   0xfffffffe, pcm_con);
> 
> Fits in one line.
> 
> > +		break;
> > +	default:
> > +		dev_info(afe->dev, "%s(), id %d not support\n",
> > +			 __func__, dai->id);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned
> > int fmt)
> > +{
> > +	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
> > +	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_info(afe->dev, "%s(), tdm_priv == NULL", __func__);
> 
> dev_err()
> 
> > +		return -EINVAL;
> > +	}
> > +
_______________________________________________
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] 44+ messages in thread

* Re: [v2 01/17] ASoC: mediatek: mt6366: add codec driver
  2022-03-05  4:24     ` Jiaxin Yu
@ 2022-03-07  9:07       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-03-07  9:07 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 05/03/22 05:24, Jiaxin Yu ha scritto:
> On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
>> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
>>> Mt6366 is a new version of mt6358, and they are same about audio
>>> part.
>>> So we can reuse the driver of mt6358.
>>>
>>> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>
>> Hello Jiaxin,
>> I'm sorry but this commit makes very little sense.
>>
>> If you want to advertise MT6366 support, please write a note and/or
>> a new compatible string inside of the mt6358 driver (and dt-
>> bindings),
>> then, please drop this commit.
>>
> 
> Hello angelogioacchino,
> 
> Thank you for your advice.
> 
> If I add a new compatible string inside of the mt6358 driver and dt-
> bindings, then the machine driver which want to use mt6366 should
> select SND_SOC_MT6358.
> 
> like below:
> 
> 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_MT6366   ==> SND_SOC_MT6358
> 	...
> 
> I just doubt it's enough to make sense. I originally wanted to put this
> relationship in the sound/soc/codecs layer. So that this relationship
> is not perceived by users(machine driver).
> However, if the general practice is like this, I will adopt your
> suggestion. Thank you again.
> 

Yes this is acceptable, please do it like that.

Thanks,
Angelo

>>
>>> ---
>>>    sound/soc/codecs/Kconfig  | 8 ++++++++
>>>    sound/soc/codecs/Makefile | 1 +
>>>    2 files changed, 9 insertions(+)
>>>
>>> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
>>> index 8fa24783ce01..6631094678f5 100644
>>> --- a/sound/soc/codecs/Kconfig
>>> +++ b/sound/soc/codecs/Kconfig
>>> @@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS
>>>    	imply SND_SOC_MT6351
>>>    	imply SND_SOC_MT6358
>>>    	imply SND_SOC_MT6359
>>> +	imply SND_SOC_MT6366
>>>    	imply SND_SOC_MT6660
>>>    	imply SND_SOC_NAU8315
>>>    	imply SND_SOC_NAU8540
>>> @@ -1888,6 +1889,13 @@ config SND_SOC_MT6359_ACCDET
>>>    	  for ASoC codec soc-jack detection mechanism.
>>>    	  Select N if you don't have jack on board.
>>>    
>>> +config SND_SOC_MT6366
>>> +	tristate "MediaTek MT6366 Codec"
>>> +	depends on MTK_PMIC_WRAP
>>> +	help
>>> +	  Enable support for the platform which uses MT6366 as
>>> +	  external codec device.
>>> +
>>>    config SND_SOC_MT6660
>>>    	tristate "Mediatek MT6660 Speaker Amplifier"
>>>    	depends on I2C
>>> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
>>> index 42d00aa4ee46..1279684feaf0 100644
>>> --- a/sound/soc/codecs/Makefile
>>> +++ b/sound/soc/codecs/Makefile
>>> @@ -465,6 +465,7 @@ obj-$(CONFIG_SND_SOC_MT6351)	+= snd-soc-
>>> mt6351.o
>>>    obj-$(CONFIG_SND_SOC_MT6358)	+= snd-soc-mt6358.o
>>>    obj-$(CONFIG_SND_SOC_MT6359)	+= snd-soc-mt6359.o
>>>    obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o
>>> +obj-$(CONFIG_SND_SOC_MT6366)	+= snd-soc-mt6358.o
>>>    obj-$(CONFIG_SND_SOC_MT6660)	+= snd-soc-mt6660.o
>>>    obj-$(CONFIG_SND_SOC_NAU8315)   += snd-soc-nau8315.o
>>>    obj-$(CONFIG_SND_SOC_NAU8540)   += snd-soc-nau8540.o
>>
>>
> 


_______________________________________________
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] 44+ messages in thread

* Re: [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357
  2022-03-05  8:58     ` Jiaxin Yu
@ 2022-03-07  9:14       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-03-07  9:14 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 05/03/22 09:58, Jiaxin Yu ha scritto:
> On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
>> Il 17/02/22 14:42, Jiaxin Yu ha scritto:
>>> This patch adds support for mt8186 board with mt6366, da7219 and
>>> max98357.
>>>
>>> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>> ---
>>>    .../mt8186/mt8186-mt6366-da7219-max98357.c    | 910
>>> ++++++++++++++++++
>>>    1 file changed, 910 insertions(+)
>>>    create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-
>>> da7219-max98357.c
>>>
>>> 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..6ba53b8d1e46
>>> --- /dev/null
>>> +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
>>> @@ -0,0 +1,910 @@
>>> +// 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/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"
>>> +
>>> +#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 mt6366_codec_conf[] = {
>>> +	{
>>> +		.dlc = COMP_CODEC_CONF("mt6358-sound"),
>>> +		.name_prefix = "Mt6366",
>>> +	},
>>> +};
>>> +
>>> +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, NULL, 0);
>>> +	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 = 0, 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\n");
>>
>> Does it really make sense to go on after this failure?
>>
>>> +
>>> +	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\n");
>>> +
>>
>> I think that going on past this wouldn't make sense as well, as it
>> may result
>> in unexpected behavior... just return a failure here
> 
> Yes, it is.
>>
>>> +			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);
>>
>> and here
> Yes, you are right.
> 
>>
>>> +		}
>>> +	}
>>> +
>>
>> So, you've covered all failure cases already, for which, you can
>> simply
>> return 0 here.
> Yes, it is.
> 
>>
>>> +	return ret;
>>> +}
>>> +
>>> +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);
>>> +				break;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +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_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, NULL, 0);
>>> +	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_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_info(rtd->dev, "failed to snd_soc_dapm_sync\n");
>>
>> dev_err()
>>
>>> +		return ret;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime
>>> *rtd,
>>> +				      struct snd_pcm_hw_params *params)
>>> +{
>>> +	struct snd_interval *channels = hw_param_interval(params,
>>> +		SNDRV_PCM_HW_PARAM_CHANNELS);
>>> +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
>>> +
>>
>> dev_dbg()
>>
>>> +	/* fix BE i2s channel to 2 channel */
>>> +	channels->min = 2;
>>> +	channels->max = 2;
>>> +
>>> +	/* fix BE i2s format to S32_LE, 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, SNDRV_PCM_FORMAT_S32_LE);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int mt8186_hdmi_i2s_hw_params_fixup(struct
>>> snd_soc_pcm_runtime *rtd,
>>> +					   struct snd_pcm_hw_params
>>> *params)
>>> +{
>>> +	struct snd_interval *channels = hw_param_interval(params,
>>> +		SNDRV_PCM_HW_PARAM_CHANNELS);
>>> +	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
>>> +
>>
>> dev_dbg()
>>
>>> +	/* fix BE i2s channel to 2 channel */
>>> +	channels->min = 2;
>>> +	channels->max = 2;
>>> +
>>> +	/* fix BE i2s format to S24_LE, 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, SNDRV_PCM_FORMAT_S24_LE);
>>> +
>>> +	return 0;
>>> +}
>>
> 
> Ok, I will use this code which is really more concise.
> 
>> Besides, I would do the following instead:
>>
>> 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 32bit\n", __func__);
>>
>>
>>
>> 	/* fix BE i2s channel to 2 channel */
>>
>> 	channels->min = 2;
>>
>> 	channels->max = 2;
>>
>>
>>
>> 	/* fix BE i2s format to S32_LE, 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_hdmi_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);
>>
>> }
>>
>> ... this reduces code duplication!
>>
>>> +
>>> +/* FE */
>>> +SND_SOC_DAILINK_DEFS(playback1,
>>> +		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
>>> +		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
>>> +		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
>>
>>
>> ..snip..
>>
>>> +static int mt8186_mt6366_da7219_max98357_dev_probe(struct
>>> platform_device *pdev)
>>> +{
>>> +	struct snd_soc_card *card =
>>> &mt8186_mt6366_da7219_max98357_soc_card;
>>> +	struct snd_soc_dai_link *dai_link;
>>> +	struct mt8186_mt6366_da7219_max98357_priv *priv;
>>> +	struct device_node *platform_node, *hdmi_codec;
>>> +	int ret, i;
>>> +
>>> +	dev_info(&pdev->dev, "%s(), ++\n", __func__);
>>> +
>>> +	card->dev = &pdev->dev;
>>> +
>>> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>>> +	if (!priv)
>>> +		return -ENOMEM;
>>> +
>>> +	platform_node = of_parse_phandle(pdev->dev.of_node,
>>> +					 "mediatek,platform", 0);
>>> +	if (!platform_node) {
>>> +		dev_info(&pdev->dev,
>>> +			 "Property 'platform' missing or invalid\n");
>>
>> 	if (!platform_node)
>> 		return dev_err_probe(&pdev->dev, -EINVAL,
>> 				    "mediatek,platform missing or
>> invalid\n");
>>
>>> +		return -EINVAL;
> got err_platform_node;
>>> +	}
>>> +
>>> +	hdmi_codec = of_parse_phandle(pdev->dev.of_node,
>>> +				      "mediatek,hdmi-codec", 0);
>>> +	if (!hdmi_codec) {
>>> +		dev_info(&pdev->dev,
>>> +			 "Property 'hdmi' missing or invalid\n");
>>
>> dev_err()
>>
>>> +		return -EINVAL;
>>> +	}
> Should I of_node_put(platform_node) befor return?
> 
> goto err_hdmi_node;
> 

of_node_put() has to be called only when of_parse_phandle() succeeds,
otherwise there is nothing to put.

> 
>>> +
>>> +	for_each_card_prelinks(card, i, dai_link) {
>>> +		if (dai_link->platforms->name)
>>> +			continue;
>>> +
>>> +		if (hdmi_codec && strcmp(dai_link->name, "I2S3") == 0)
>>> {
>>> +			dai_link->codecs->of_node = hdmi_codec;
>>> +			dai_link->ignore = 0;
>>> +		}
>>> +
>>> +		dai_link->platforms->of_node = platform_node;
>>> +	}
>>> +
>>> +	snd_soc_card_set_drvdata(card, priv);
>>> +
>>> +	/* init gpio */
>>> +	ret = mt8186_afe_gpio_init(&pdev->dev);
>>> +	if (ret)
>>> +		dev_info(&pdev->dev, "init gpio error\n");
>>
>> dev_err() and goto end;
> Yes, goto err_init_gpio and of_node_put for hdmi_codec and
> platform_node.

Yes, agreed.


Regards,
Angelo

>>
>>> +
>>> +	dev_info(&pdev->dev, "%s(), devm_snd_soc_register_card\n",
>>> __func__);
>>> +	ret = devm_snd_soc_register_card(&pdev->dev, card);
>>> +	if (ret)
>>> +		dev_info(&pdev->dev, "%s snd_soc_register_card fail
>>> %d\n",
>>> +			 __func__, ret);
>>
>> dev_err_probe()
>>
>> end:
>>
> err_init_gpio:
>>> +	of_node_put(hdmi_codec);
> err_hdmi_node:
>>> +	of_node_put(platform_node);
>>> +
> err_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",},
>>> +	{}
>>> +};
>>> +#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");
>>
>>
> 


_______________________________________________
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] 44+ messages in thread

* Re: [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver
  2022-03-05 10:49     ` Jiaxin Yu
@ 2022-03-07  9:25       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 44+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-03-07  9:25 UTC (permalink / raw)
  To: Jiaxin Yu, broonie
  Cc: lgirdwood, tiwai, robh+dt, matthias.bgg, perex, p.zabel,
	geert+renesas, trevor.wu, tzungbi, aaronyu, zhangqilong3,
	alsa-devel, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel

Il 05/03/22 11:49, Jiaxin Yu ha scritto:
> On Fri, 2022-02-18 at 15:54 +0100, AngeloGioacchino Del Regno wrote:
>> Il 17/02/22 14:41, Jiaxin Yu ha scritto:
>>> This patch adds mt8186 adda dai driver
>>>
>>> Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>> ---
>>>    sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 891
>>> ++++++++++++++++++++
>>>    1 file changed, 891 insertions(+)
>>>    create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c
>>>
>>> diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
>>> b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
>>> new file mode 100644
>>> index 000000000000..6d7dd1533da0
>>> --- /dev/null
>>> +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c
>>> @@ -0,0 +1,891 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +//
>>> +// MediaTek ALSA SoC Audio DAI ADDA Control
>>> +//
>>> +// Copyright (c) 2022 MediaTek Inc.
>>> +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
>>> +
>>> +#include <linux/regmap.h>
>>> +#include <linux/delay.h>
>>> +#include "mt8186-afe-clk.h"
>>> +#include "mt8186-afe-common.h"
>>> +#include "mt8186-afe-gpio.h"
>>> +#include "mt8186-interconnection.h"
>>> +
> ...snip...
>>>
>>> +/* dai ops */
>>> +static int mtk_dai_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);
>>> +	struct mt8186_afe_private *afe_priv = afe->platform_priv;
>>> +	unsigned int rate = params_rate(params);
>>> +	int id = dai->id;
>>> +	struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id];
>>> +
>>> +	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
>>> +		 __func__,
>>> +		 id,
>>> +		 substream->stream,
>>> +		 rate);
>>> +
>>> +	if (!adda_priv) {
>>> +		dev_info(afe->dev, "%s(), adda_priv == NULL",
>>> __func__);
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>>> +		unsigned int dl_src2_con0 = 0;
>>> +		unsigned int dl_src2_con1 = 0;
>>
>> This initialization is redundant: you're never using these variables
>> before initializing them later, so initializing them to zero is not
>> needed here.
> Yes, got it. Thank you.
>>
>>> +
>>> +		adda_priv->dl_rate = rate;
>>> +
>>> +		/* set sampling rate */
>>> +		dl_src2_con0 = adda_dl_rate_transform(afe, rate) <<
>>> +			       DL_2_INPUT_MODE_CTL_SFT;
>>> +
>>> +		/* set output mode, UP_SAMPLING_RATE_X8 */
>>> +		dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT);
>>> +
>>> +		/* turn off mute function */
>>> +		dl_src2_con0 |= (0x01 <<
>>> DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);
>>
>> BIT() macro, please
>>
>>> +		dl_src2_con0 |= (0x01 <<
>>> DL_2_MUTE_CH1_OFF_CTL_PRE_SFT);
>>> +
>>> +		/* set voice input data if input sample rate is 8k or
>>> 16k */
>>> +		if (rate == 8000 || rate == 16000)
>>> +			dl_src2_con0 |= 0x01 <<
>>> DL_2_VOICE_MODE_CTL_PRE_SFT;
>>> +
>>> +		/* SA suggest apply -0.3db to audio/speech path */
>>> +		dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL <<
>>> +			       DL_2_GAIN_CTL_PRE_SFT;
>>> +
>>> +		/* turn on down-link gain */
>>> +		dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT);
>>> +
>>> +		if (id == MT8186_DAI_ADDA) {
>>> +			/* clean predistortion */
>>> +			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,
>>> dl_src2_con0);
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_DL_SRC2_CON1,
>>> dl_src2_con1);
>>> +
>>> +			/* set sdm gain */
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
>>> +					   ATTGAIN_CTL_MASK_SFT,
>>> +					   AUDIO_SDM_LEVEL_NORMAL <<
>>> +					   ATTGAIN_CTL_SFT);
>>> +
>>> +			/* Use new 2nd sdm */
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_DL_SDM_DITHER_CON,
>>> +					   AFE_DL_SDM_DITHER_64TAP_EN_M
>>> ASK_SFT,
>>> +					   0x1 <<
>>> AFE_DL_SDM_DITHER_64TAP_EN_SFT);
>>
>> BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)
>>
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_DL_SDM_AUTO_RESET_C
>>> ON,
>>> +					   AFE_DL_USE_NEW_2ND_SDM_MASK_
>>> SFT,
>>> +					   0x1 <<
>>> AFE_DL_USE_NEW_2ND_SDM_SFT);
>>
>> BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)
>>
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_DL_SDM_DCCOMP_CON,
>>> +					   USE_3RD_SDM_MASK_SFT,
>>> +					   AUDIO_SDM_2ND <<
>>> USE_3RD_SDM_SFT);
>>> +
>>> +			/* sdm auto reset */
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_DL_SDM_AUTO_RESET_CON,
>>> +				     SDM_AUTO_RESET_THRESHOLD);
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_DL_SDM_AUTO_RESET_C
>>> ON,
>>> +					   SDM_AUTO_RESET_TEST_ON_MASK_
>>> SFT,
>>> +					   0x1 <<
>>> SDM_AUTO_RESET_TEST_ON_SFT);
>>
>> BIT(SDM_AUTO_RESET_TEST_ON_SFT)
>>
>>> +		}
>>> +	} else {
>>> +		unsigned int voice_mode = 0;
>>
>> what about...
>> 		unsigned int ul_src_con0 = 0; /* default value */
>> 		unsigned int voice_mode =  adda_ul_rate_transform(afe,
>> rate);
> Agree with you.
> 
>>> +		unsigned int ul_src_con0 = 0;	/* default value */
>>> +
>>> +		adda_priv->ul_rate = rate;
>>> +
>>> +		voice_mode = adda_ul_rate_transform(afe, rate);
>>> +
>>> +		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
>>> +
>>> +		/* enable iir */
>>> +		ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
>>> +			       UL_IIR_ON_TMP_CTL_MASK_SFT;
>>> +		ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
>>> +			       UL_IIRMODE_CTL_MASK_SFT;
>>> +		switch (id) {
>>> +		case MT8186_DAI_ADDA:
>>> +		case MT8186_DAI_AP_DMIC:
>>> +			/* 35Hz @ 48k */
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_IIR_COEF_02_01,
>>> 0x00000000);
>>
>> Please drop leading zeroes:
>>
>> regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0);
>>
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_IIR_COEF_04_03,
>>> 0x00003FB8);
>>
>> ... and also please write hex in lower-case:
>>
> Got it.
>> regmap_write(afe->regmap,
>> 	     AFE_ADDA_IIR_COEF_04_03, 0x03fb8);
>>
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_IIR_COEF_06_05,
>>> 0x3FB80000);
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_IIR_COEF_08_07,
>>> 0x3FB80000);
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_IIR_COEF_10_09,
>>> 0x0000C048);
>>> +
>>> +			regmap_write(afe->regmap,
>>> +				     AFE_ADDA_UL_SRC_CON0,
>>> ul_src_con0);
>>> +
>>> +			/* Using Internal ADC */
>>> +			regmap_update_bits(afe->regmap,
>>> +					   AFE_ADDA_TOP_CON0,
>>> +					   0x1 << 0,
>>> +					   0x0 << 0);
>>
>> Please use the BIT() macro:
>>
>> regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0);
>>
>> P.S.: 87 columns is ok
> 
> How can I judge whether it can exceed 80 lines?

https://www.kernel.org/doc/html/latest/process/coding-style.html

Besides, the 80 columns rule was made for old terminals (like VT100 and such)
that supported displaying a maximum of 80 cols... in the modern era, that's
not the case anymore.
It's somewhat preferred if something can fit in 80 columns, but if it does
impact on readability, then you can go over that, up to 100 columns.

scripts/checkpatch.pl was also changed to complain about 100 columns and not
80 anymore...

my $max_line_length = 100;

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/checkpatch.pl?h=v5.17-rc7#n59

Cheers,
Angelo


_______________________________________________
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] 44+ messages in thread

end of thread, other threads:[~2022-03-07  9:35 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-17 13:41 [v2 00/17] ASoC: mediatek: Add support for MT8186 SoC Jiaxin Yu
2022-02-17 13:41 ` [v2 01/17] ASoC: mediatek: mt6366: add codec driver Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-05  4:24     ` Jiaxin Yu
2022-03-07  9:07       ` AngeloGioacchino Del Regno
2022-02-17 13:41 ` [v2 02/17] ASoC: mediatek: mt8186: support audsys clock control Jiaxin Yu
2022-02-17 13:41 ` [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-05 10:49     ` Jiaxin Yu
2022-03-07  9:25       ` AngeloGioacchino Del Regno
2022-02-17 13:41 ` [v2 04/17] ASoC: mediatek: mt8186: support hostless " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-02-17 13:41 ` [v2 05/17] ASoC: mediatek: mt8186: support hw gain " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-02-17 13:41 ` [v2 06/17] ASoC: mediatek: mt8186: support i2s " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-05 11:07     ` Jiaxin Yu
2022-02-17 13:41 ` [v2 07/17] ASoC: mediatek: mt8186: support pcm " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-05 11:12     ` Jiaxin Yu
2022-02-17 13:41 ` [v2 08/17] ASoC: mediatek: mt8186: support src " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-02-17 13:41 ` [v2 09/17] ASoC: mediatek: mt8186: support tdm " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-03 14:10     ` Jiaxin Yu
2022-03-03 15:08       ` AngeloGioacchino Del Regno
2022-03-03 17:39         ` Jiaxin Yu
2022-02-17 13:41 ` [v2 10/17] ASoC: mediatek: mt8186: support audio clock control " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-03 15:16     ` Jiaxin Yu
2022-03-03 15:17     ` Jiaxin Yu
2022-02-17 13:41 ` [v2 11/17] ASoC: mediatek: mt8186: support gpio " Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-03 15:30     ` Jiaxin Yu
2022-02-17 13:42 ` [v2 13/17] dt-bindings: mediatek: mt8186: add audio afe document Jiaxin Yu
2022-02-25 16:43   ` Rob Herring
2022-02-17 13:42 ` [v2 14/17] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357 Jiaxin Yu
2022-02-18 14:54   ` AngeloGioacchino Del Regno
2022-03-05  8:58     ` Jiaxin Yu
2022-03-07  9:14       ` AngeloGioacchino Del Regno
2022-02-17 13:42 ` [v2 15/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357 document Jiaxin Yu
2022-02-17 13:42 ` [v2 16/17] ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and rt5682s Jiaxin Yu
2022-02-17 13:42 ` [v2 17/17] dt-bindings: mediatek: mt8186: add mt8186-mt6366-rt1019-rt5682s document Jiaxin Yu
     [not found] ` <20220217134205.15400-13-jiaxin.yu@mediatek.com>
     [not found]   ` <58cc2df8-5503-b38f-2a6d-9bbef809a60f@collabora.com>
2022-03-05  9:10     ` [v2 12/17] ASoC: mediatek: mt8186: add platform driver Jiaxin Yu

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).