aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2025-11-19 02:10:20 +0000
committerMark Brown <broonie@kernel.org>2025-11-19 02:10:20 +0000
commit683c03b95c2ae95ff05ebf0dcc040bf3db633135 (patch)
tree467cb93969d50a0aac9c35e5a89450c63dc4b603
parente45979641a9a9dbb48fc77c5b36a5091a92e7227 (diff)
parentd218ea171430e49412804efb794942dd121a8032 (diff)
ASoC: mediatek: Add support for MT8189 SoC
Merge series from Cyril Chao <Cyril.Chao@mediatek.com>: This series of patches adds support for Mediatek AFE of MT8189 SoC.
-rw-r--r--Documentation/devicetree/bindings/sound/mediatek,mt8189-afe-pcm.yaml178
-rw-r--r--Documentation/devicetree/bindings/sound/mediatek,mt8189-nau8825.yaml101
-rw-r--r--sound/soc/mediatek/Kconfig31
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/mt8189/Makefile18
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-afe-clk.c750
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-afe-clk.h76
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-afe-common.h240
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-afe-pcm.c2617
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-dai-adda.c1228
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-dai-i2s.c1463
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-dai-pcm.c332
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-dai-tdm.c672
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-interconnection.h97
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-nau8825.c1178
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-reg.h10773
16 files changed, 19755 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8189-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8189-afe-pcm.yaml
new file mode 100644
index 000000000000..9c9f21652af9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8189-afe-pcm.yaml
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8189-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Audio Front End PCM controller for MT8189
+
+maintainers:
+ - Darren Ye <darren.ye@mediatek.com>
+ - Cyril Chao <cyril.chao@mediatek.com>
+
+properties:
+ compatible:
+ const: mediatek,mt8189-afe-pcm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ memory-region:
+ maxItems: 1
+
+ mediatek,apmixedsys:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: To set up the apll12 tuner
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: mux for audio intbus
+ - description: mux for audio engen1
+ - description: mux for audio engen2
+ - description: mux for audio h
+ - description: audio apll1 clock
+ - description: audio apll2 clock
+ - description: audio apll1 divide4
+ - description: audio apll2 divide4
+ - description: audio apll12 divide for i2sin0
+ - description: audio apll12 divide for i2sin1
+ - description: audio apll12 divide for i2sout0
+ - description: audio apll12 divide for i2sout1
+ - description: audio apll12 divide for fmi2s
+ - description: audio apll12 divide for tdmout mck
+ - description: audio apll12 divide for tdmout bck
+ - description: mux for audio apll1
+ - description: mux for audio apll2
+ - description: mux for i2sin0 mck
+ - description: mux for i2sin1 mck
+ - description: mux for i2sout0 mck
+ - description: mux for i2sout1 mck
+ - description: mux for fmi2s mck
+ - description: mux for tdmout mck
+ - description: 26m clock
+ - description: audio slv clock
+ - description: audio mst clock
+ - description: audio intbus clock
+
+ clock-names:
+ items:
+ - const: top_aud_intbus
+ - const: top_aud_eng1
+ - const: top_aud_eng2
+ - const: top_aud_h
+ - const: apll1
+ - const: apll2
+ - const: apll1_d4
+ - const: apll2_d4
+ - const: apll12_div_i2sin0
+ - const: apll12_div_i2sin1
+ - const: apll12_div_i2sout0
+ - const: apll12_div_i2sout1
+ - const: apll12_div_fmi2s
+ - const: apll12_div_tdmout_m
+ - const: apll12_div_tdmout_b
+ - const: top_apll1
+ - const: top_apll2
+ - const: top_i2sin0
+ - const: top_i2sin1
+ - const: top_i2sout0
+ - const: top_i2sout1
+ - const: top_fmi2s
+ - const: top_dptx
+ - const: clk26m
+ - const: aud_slv_ck_peri
+ - const: aud_mst_ck_peri
+ - const: aud_intbus_ck_peri
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - memory-region
+ - power-domains
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ afe@11050000 {
+ compatible = "mediatek,mt8189-afe-pcm";
+ reg = <0 0x11050000 0 0x10000>;
+ interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
+ memory-region = <&afe_dma_mem_reserved>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ power-domains = <&scpsys 1>; //MT8189_POWER_DOMAIN_AUDIO
+ clocks = <&topckgen_clk 23>, //CLK_TOP_AUD_INTBUS_SEL
+ <&topckgen_clk 39>, //CLK_TOP_AUD_ENGEN1_SEL
+ <&topckgen_clk 40>, //CLK_TOP_AUD_ENGEN2_SEL
+ <&topckgen_clk 49>, //CLK_TOP_AUDIO_H_SEL
+ <&topckgen_clk 146>, //CLK_TOP_APLL1
+ <&topckgen_clk 151>, //CLK_TOP_APLL2
+ <&topckgen_clk 148>, //CLK_TOP_APLL1_D4
+ <&topckgen_clk 153>, //CLK_TOP_APLL2_D4
+ <&topckgen_clk 93>, //CLK_TOP_APLL12_CK_DIV_I2SIN0
+ <&topckgen_clk 94>, //CLK_TOP_APLL12_CK_DIV_I2SIN1
+ <&topckgen_clk 95>, //CLK_TOP_APLL12_CK_DIV_I2SOUT0
+ <&topckgen_clk 96>, //CLK_TOP_APLL12_CK_DIV_I2SOUT1
+ <&topckgen_clk 97>, //CLK_TOP_APLL12_CK_DIV_FMI2S
+ <&topckgen_clk 98>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_M
+ <&topckgen_clk 99>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_B
+ <&topckgen_clk 44>, //CLK_TOP_AUD_1_SEL
+ <&topckgen_clk 45>, //CLK_TOP_AUD_2_SEL
+ <&topckgen_clk 78>, //CLK_TOP_APLL_I2SIN0_MCK_SEL
+ <&topckgen_clk 79>, //CLK_TOP_APLL_I2SIN1_MCK_SEL
+ <&topckgen_clk 84>, //CLK_TOP_APLL_I2SOUT0_MCK_SEL
+ <&topckgen_clk 85>, //CLK_TOP_APLL_I2SOUT1_MCK_SEL
+ <&topckgen_clk 90>, //CLK_TOP_APLL_FMI2S_MCK_SEL
+ <&topckgen_clk 91>, //CLK_TOP_APLL_TDMOUT_MCK_SEL
+ <&topckgen_clk 191>, //CLK_TOP_TCK_26M_MX9
+ <&pericfg_ao_clk 77>, //CLK_PERAO_AUDIO0
+ <&pericfg_ao_clk 78>, //CLK_PERAO_AUDIO1
+ <&pericfg_ao_clk 79>; //CLK_PERAO_AUDIO2
+ clock-names = "top_aud_intbus",
+ "top_aud_eng1",
+ "top_aud_eng2",
+ "top_aud_h",
+ "apll1",
+ "apll2",
+ "apll1_d4",
+ "apll2_d4",
+ "apll12_div_i2sin0",
+ "apll12_div_i2sin1",
+ "apll12_div_i2sout0",
+ "apll12_div_i2sout1",
+ "apll12_div_fmi2s",
+ "apll12_div_tdmout_m",
+ "apll12_div_tdmout_b",
+ "top_apll1",
+ "top_apll2",
+ "top_i2sin0",
+ "top_i2sin1",
+ "top_i2sout0",
+ "top_i2sout1",
+ "top_fmi2s",
+ "top_dptx",
+ "clk26m",
+ "aud_slv_ck_peri",
+ "aud_mst_ck_peri",
+ "aud_intbus_ck_peri";
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8189-nau8825.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8189-nau8825.yaml
new file mode 100644
index 000000000000..dd9ee0a3b292
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8189-nau8825.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8189-nau8825.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT8189 ASoC sound card
+
+maintainers:
+ - Darren Ye <darren.ye@mediatek.com>
+ - Cyril Chao <cyril.chao@mediatek.com>
+
+allOf:
+ - $ref: sound-card-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt8189-nau8825
+ - mediatek,mt8189-rt5650
+ - mediatek,mt8189-rt5682s
+ - mediatek,mt8189-rt5682i
+ - mediatek,mt8189-es8326
+
+ mediatek,platform:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of MT8189 ASoC platform.
+
+patternProperties:
+ "^dai-link-[0-9]+$":
+ type: object
+ description:
+ Container for dai-link level properties and CODEC sub-nodes.
+
+ properties:
+ link-name:
+ description:
+ This property corresponds to the name of the BE dai-link to which
+ we are going to update parameters in this node.
+ enum:
+ - TDM_DPTX_BE
+ - I2SOUT0_BE
+ - I2SIN0_BE
+ - I2SOUT1_BE
+
+ codec:
+ description: Holds subnode which indicates codec dai.
+ type: object
+ additionalProperties: false
+
+ properties:
+ sound-dai:
+ minItems: 1
+ maxItems: 2
+ required:
+ - sound-dai
+
+ dai-format:
+ description: audio format.
+ enum:
+ - i2s
+ - right_j
+ - left_j
+ - dsp_a
+ - dsp_b
+
+ mediatek,clk-provider:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Indicates dai-link clock master.
+ enum:
+ - cpu
+ - codec
+
+ additionalProperties: false
+
+ required:
+ - link-name
+
+required:
+ - compatible
+ - mediatek,platform
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ sound {
+ compatible = "mediatek,mt8189-nau8825";
+ model = "mt8189_rt9123_8825";
+ mediatek,platform = <&afe>;
+ dai-link-0 {
+ link-name = "I2SOUT1_BE";
+ dai-format = "i2s";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&nau8825>;
+ };
+ };
+ };
+
+...
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 10ca8bccabdd..3a1e1fa3fe5c 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -246,6 +246,37 @@ config SND_SOC_MT8188_MT6359
Select Y if you have such device.
If unsure select "N".
+config SND_SOC_MT8189
+ tristate "ASoC support for Mediatek MT8189 chip"
+ depends on ARCH_MEDIATEK
+ select SND_SOC_MEDIATEK
+ help
+ This adds ASoC driver for Mediatek MT8189 boards
+ that can be used with other codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
+config SND_SOC_MT8189_NAU8825
+ tristate "ASoc Audio driver for MT8189 with NAU8825 and I2S codec"
+ depends on SND_SOC_MT8189
+ depends on I2C
+ select SND_SOC_DMIC
+ select SND_SOC_HDMI_CODEC
+ select SND_SOC_NAU8825
+ select SND_SOC_RT5645
+ select SND_SOC_RT9123P
+ select SND_SOC_RT1015P
+ select SND_SOC_RT5682S
+ select SND_SOC_RT5682_I2C
+ select SND_SOC_CS35L41_I2C
+ select SND_SOC_AW88081
+ select SND_SOC_ES8326
+ help
+ This adds support for ASoC machine driver for MediaTek MT8189
+ boards with the NAU8828 and other I2S audio codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
config SND_SOC_MT8192
tristate "ASoC support for Mediatek MT8192 chip"
depends on ARCH_MEDIATEK
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index 4b55434f2168..7cd67bce92e9 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_MT8188) += mt8188/
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
obj-$(CONFIG_SND_SOC_MT8365) += mt8365/
+obj-$(CONFIG_SND_SOC_MT8189) += mt8189/
diff --git a/sound/soc/mediatek/mt8189/Makefile b/sound/soc/mediatek/mt8189/Makefile
new file mode 100644
index 000000000000..83a033284182
--- /dev/null
+++ b/sound/soc/mediatek/mt8189/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# common include path
+subdir-ccflags-y += -I$(srctree)/sound/soc/mediatek/common
+
+# platform driver
+snd-soc-mt8189-afe-objs += \
+ mt8189-afe-pcm.o \
+ mt8189-afe-clk.o \
+ mt8189-dai-adda.o \
+ mt8189-dai-i2s.o \
+ mt8189-dai-pcm.o \
+ mt8189-dai-tdm.o
+
+obj-$(CONFIG_SND_SOC_MT8189) += snd-soc-mt8189-afe.o
+
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8189_NAU8825) += mt8189-nau8825.o
diff --git a/sound/soc/mediatek/mt8189/mt8189-afe-clk.c b/sound/soc/mediatek/mt8189/mt8189-afe-clk.c
new file mode 100644
index 000000000000..fc7a7a73b0cf
--- /dev/null
+++ b/sound/soc/mediatek/mt8189/mt8189-afe-clk.c
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8189-afe-clk.c -- Mediatek 8189 afe clock ctrl
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "mt8189-afe-common.h"
+#include "mt8189-afe-clk.h"
+
+/* mck */
+struct mt8189_mck_div {
+ int m_sel_id;
+ int div_clk_id;
+};
+
+static const struct mt8189_mck_div mck_div[MT8189_MCK_NUM] = {
+ [MT8189_I2SIN0_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_I2SIN0_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SIN0,
+ },
+ [MT8189_I2SIN1_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_I2SIN1_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SIN1,
+ },
+ [MT8189_I2SOUT0_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_I2SOUT0_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SOUT0,
+ },
+ [MT8189_I2SOUT1_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_I2SOUT1_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SOUT1,
+ },
+ [MT8189_FMI2S_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_FMI2S_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_FMI2S,
+ },
+ [MT8189_TDMOUT_MCK] = {
+ .m_sel_id = MT8189_CLK_TOP_TDMOUT_M_SEL,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M,
+ },
+ [MT8189_TDMOUT_BCK] = {
+ .m_sel_id = -1,
+ .div_clk_id = MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B,
+ },
+};
+
+static const char *aud_clks[MT8189_CLK_NUM] = {
+ [MT8189_CLK_TOP_MUX_AUDIOINTBUS] = "top_aud_intbus",
+ [MT8189_CLK_TOP_MUX_AUD_ENG1] = "top_aud_eng1",
+ [MT8189_CLK_TOP_MUX_AUD_ENG2] = "top_aud_eng2",
+ [MT8189_CLK_TOP_MUX_AUDIO_H] = "top_aud_h",
+ /* pll */
+ [MT8189_CLK_TOP_APLL1_CK] = "apll1",
+ [MT8189_CLK_TOP_APLL2_CK] = "apll2",
+ /* divider */
+ [MT8189_CLK_TOP_APLL1_D4] = "apll1_d4",
+ [MT8189_CLK_TOP_APLL2_D4] = "apll2_d4",
+ [MT8189_CLK_TOP_APLL12_DIV_I2SIN0] = "apll12_div_i2sin0",
+ [MT8189_CLK_TOP_APLL12_DIV_I2SIN1] = "apll12_div_i2sin1",
+ [MT8189_CLK_TOP_APLL12_DIV_I2SOUT0] = "apll12_div_i2sout0",
+ [MT8189_CLK_TOP_APLL12_DIV_I2SOUT1] = "apll12_div_i2sout1",
+ [MT8189_CLK_TOP_APLL12_DIV_FMI2S] = "apll12_div_fmi2s",
+ [MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M] = "apll12_div_tdmout_m",
+ [MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B] = "apll12_div_tdmout_b",
+ /* mux */
+ [MT8189_CLK_TOP_MUX_AUD_1] = "top_apll1",
+ [MT8189_CLK_TOP_MUX_AUD_2] = "top_apll2",
+ [MT8189_CLK_TOP_I2SIN0_M_SEL] = "top_i2sin0",
+ [MT8189_CLK_TOP_I2SIN1_M_SEL] = "top_i2sin1",
+ [MT8189_CLK_TOP_I2SOUT0_M_SEL] = "top_i2sout0",
+ [MT8189_CLK_TOP_I2SOUT1_M_SEL] = "top_i2sout1",
+ [MT8189_CLK_TOP_FMI2S_M_SEL] = "top_fmi2s",
+ [MT8189_CLK_TOP_TDMOUT_M_SEL] = "top_dptx",
+ /* top 26m*/
+ [MT8189_CLK_TOP_CLK26M] = "clk26m",
+ /* peri */
+ [MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI] = "aud_slv_ck_peri",
+ [MT8189_CLK_PERAO_AUDIO_MST_CK_PERI] = "aud_mst_ck_peri",
+ [MT8189_CLK_PERAO_INTBUS_CK_PERI] = "aud_intbus_ck_peri",
+};
+
+int mt8189_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ int ret;
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(afe->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt8189_afe_enable_clk);
+
+void mt8189_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ if (clk)
+ clk_disable_unprepare(clk);
+ else
+ dev_dbg(afe->dev, "NULL clk\n");
+}
+EXPORT_SYMBOL_GPL(mt8189_afe_disable_clk);
+
+static int mt8189_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+ unsigned int rate)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_set_rate(clk, rate);
+ if (ret) {
+ dev_err(afe->dev, "failed to set clk rate\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int mt8189_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+ struct clk *parent)
+{
+ int ret;
+
+ if (clk && parent) {
+ ret = clk_set_parent(clk, parent);
+ if (ret) {
+ dev_dbg(afe->dev, "failed to set clk parent %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int get_top_cg_reg(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8189_AUDIO_26M_EN_ON:
+ case MT8189_AUDIO_F3P25M_EN_ON:
+ case MT8189_AUDIO_APLL1_EN_ON:
+ case MT8189_AUDIO_APLL2_EN_ON:
+ return AUDIO_ENGEN_CON0;
+ case MT8189_CG_AUDIO_HOPPING_CK:
+ case MT8189_CG_AUDIO_F26M_CK:
+ case MT8189_CG_APLL1_CK:
+ case MT8189_CG_APLL2_CK:
+ case MT8189_PDN_APLL_TUNER2:
+ case MT8189_PDN_APLL_TUNER1:
+ return AUDIO_TOP_CON4;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_mask(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8189_AUDIO_26M_EN_ON:
+ return AUDIO_26M_EN_ON_MASK_SFT;
+ case MT8189_AUDIO_F3P25M_EN_ON:
+ return AUDIO_F3P25M_EN_ON_MASK_SFT;
+ case MT8189_AUDIO_APLL1_EN_ON:
+ return AUDIO_APLL1_EN_ON_MASK_SFT;
+ case MT8189_AUDIO_APLL2_EN_ON:
+ return AUDIO_APLL2_EN_ON_MASK_SFT;
+ case MT8189_CG_AUDIO_HOPPING_CK:
+ return CG_AUDIO_HOPPING_CK_MASK_SFT;
+ case MT8189_CG_AUDIO_F26M_CK:
+ return CG_AUDIO_F26M_CK_MASK_SFT;
+ case MT8189_CG_APLL1_CK:
+ return CG_APLL1_CK_MASK_SFT;
+ case MT8189_CG_APLL2_CK:
+ return CG_APLL2_CK_MASK_SFT;
+ case MT8189_PDN_APLL_TUNER2:
+ return PDN_APLL_TUNER2_MASK_SFT;
+ case MT8189_PDN_APLL_TUNER1:
+ return PDN_APLL_TUNER1_MASK_SFT;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_on_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8189_AUDIO_26M_EN_ON:
+ case MT8189_AUDIO_F3P25M_EN_ON:
+ case MT8189_AUDIO_APLL1_EN_ON:
+ case MT8189_AUDIO_APLL2_EN_ON:
+ return get_top_cg_mask(cg_type);
+ case MT8189_CG_AUDIO_HOPPING_CK:
+ case MT8189_CG_AUDIO_F26M_CK:
+ case MT8189_CG_APLL1_CK:
+ case MT8189_CG_APLL2_CK:
+ case MT8189_PDN_APLL_TUNER2:
+ case MT8189_PDN_APLL_TUNER1:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_off_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8189_AUDIO_26M_EN_ON:
+ case MT8189_AUDIO_F3P25M_EN_ON:
+ case MT8189_AUDIO_APLL1_EN_ON:
+ case MT8189_AUDIO_APLL2_EN_ON:
+ return 0;
+ case MT8189_CG_AUDIO_HOPPING_CK:
+ case MT8189_CG_AUDIO_F26M_CK:
+ case MT8189_CG_APLL1_CK:
+ case MT8189_CG_APLL2_CK:
+ case MT8189_PDN_APLL_TUNER2:
+ case MT8189_PDN_APLL_TUNER1:
+ return get_top_cg_mask(cg_type);
+ default:
+ return get_top_cg_mask(cg_type);
+ }
+}
+
+static int mt8189_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_on_val(cg_type);
+
+ if (!afe->regmap) {
+ dev_err(afe->dev, "afe regmap is null !!!\n");
+ return 0;
+ }
+
+ dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
+
+ return regmap_update_bits(afe->regmap, reg, mask, val);
+}
+
+static void mt8189_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_off_val(cg_type);
+
+ if (!afe->regmap) {
+ dev_warn(afe->dev, "skip regmap\n");
+ return;
+ }
+
+ dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
+ regmap_update_bits(afe->regmap, reg, mask, val);
+}
+
+static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+ struct mt8189_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ dev_dbg(afe->dev, "enable: %d\n", enable);
+
+ if (enable) {
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
+ afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
+ if (ret)
+ goto clk_ck_mux_aud1_parent_err;
+
+ /* 180.6336 / 4 = 45.1584MHz */
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
+ if (ret)
+ goto clk_ck_mux_eng1_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
+ afe_priv->clk[MT8189_CLK_TOP_APLL1_D4]);
+ if (ret)
+ goto clk_ck_mux_eng1_parent_err;
+
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+ if (ret)
+ goto clk_ck_mux_audio_h_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
+ afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
+ if (ret)
+ goto clk_ck_mux_audio_h_parent_err;
+ } else {
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
+
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+ }
+
+ return 0;
+
+clk_ck_mux_audio_h_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+clk_ck_mux_audio_h_err:
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+clk_ck_mux_eng1_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
+clk_ck_mux_eng1_err:
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+clk_ck_mux_aud1_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+
+ return ret;
+}
+
+static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+ struct mt8189_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ dev_dbg(afe->dev, "enable: %d\n", enable);
+
+ if (enable) {
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
+ afe_priv->clk[MT8189_CLK_TOP_APLL2_CK]);
+ if (ret)
+ goto clk_ck_mux_aud2_parent_err;
+
+ /* 196.608 / 4 = 49.152MHz */
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
+ if (ret)
+ goto clk_ck_mux_eng2_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
+ afe_priv->clk[MT8189_CLK_TOP_APLL2_D4]);
+ if (ret)
+ goto clk_ck_mux_eng2_parent_err;
+
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+ if (ret)
+ goto clk_ck_mux_audio_h_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
+ afe_priv->clk[MT8189_CLK_TOP_APLL2_CK]);
+ if (ret)
+ goto clk_ck_mux_audio_h_parent_err;
+ } else {
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
+
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+ }
+
+ return 0;
+
+clk_ck_mux_audio_h_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+clk_ck_mux_audio_h_err:
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+clk_ck_mux_eng2_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
+clk_ck_mux_eng2_err:
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+clk_ck_mux_aud2_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+
+ return ret;
+}
+
+static int mt8189_afe_disable_apll(struct mtk_base_afe *afe)
+{
+ struct mt8189_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+ if (ret)
+ goto clk_ck_mux_aud1_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+ if (ret)
+ goto clk_ck_mux_aud1_parent_err;
+
+ ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+ if (ret)
+ goto clk_ck_mux_aud2_err;
+
+ ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+ if (ret)
+ goto clk_ck_mux_aud2_parent_err;
+
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
+ afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+
+ return 0;
+
+clk_ck_mux_aud2_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
+clk_ck_mux_aud2_err:
+ mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
+ afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
+clk_ck_mux_aud1_parent_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
+clk_ck_mux_aud1_err:
+ mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
+
+ return ret;
+}
+
+int mt8189_apll1_enable(struct mtk_base_afe *afe)
+{
+ int ret;
+
+ /* setting for APLL */
+ ret = apll1_mux_setting(afe, true);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_CG_APLL1_CK);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_PDN_APLL_TUNER1);
+ if (ret)
+ return ret;
+
+ /* sel 44.1kHz:1, apll_div:7, upper bound:3 */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT |
+ UPPER_BOUND_MASK_SFT,
+ (0x1 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
+ (3 << UPPER_BOUND_SFT));
+
+ /* apll1 freq tuner enable */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x1 << FREQ_TUNER_EN_SFT);
+
+ /* audio apll1 on */
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_APLL1_EN_ON);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void mt8189_apll1_disable(struct mtk_base_afe *afe)
+{
+ /* audio apll1 off */
+ mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_APLL1_EN_ON);
+
+ /* apll1 freq tuner disable */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x0);
+
+ mt8189_afe_disable_top_cg(afe, MT8189_PDN_APLL_TUNER1);
+ mt8189_afe_disable_top_cg(afe, MT8189_CG_APLL1_CK);
+ apll1_mux_setting(afe, false);
+}
+
+int mt8189_apll2_enable(struct mtk_base_afe *afe)
+{
+ int ret;
+
+ /* setting for APLL */
+ ret = apll2_mux_setting(afe, true);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_CG_APLL2_CK);
+ if (ret)
+ return ret;
+
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_PDN_APLL_TUNER2);
+ if (ret)
+ return ret;
+
+ /* sel 48kHz: 2, apll_div: 7, upper bound: 3*/
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT |
+ UPPER_BOUND_MASK_SFT,
+ (0x2 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
+ (3 << UPPER_BOUND_SFT));
+
+ /* apll2 freq tuner enable */
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x1 << FREQ_TUNER_EN_SFT);
+
+ /* audio apll2 on */
+ ret = mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_APLL2_EN_ON);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void mt8189_apll2_disable(struct mtk_base_afe *afe)
+{
+ /* audio apll2 off */
+ mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_APLL2_EN_ON);
+
+ /* apll2 freq tuner disable */
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x0);
+
+ mt8189_afe_disable_top_cg(afe, MT8189_PDN_APLL_TUNER2);
+ mt8189_afe_disable_top_cg(afe, MT8189_CG_APLL2_CK);
+ apll2_mux_setting(afe, false);
+}
+
+int mt8189_get_apll_rate(struct mtk_base_afe *afe, int apll)
+{
+ struct mt8189_afe_private *afe_priv = afe->platform_priv;
+ int clk_id;
+
+ if (apll < MT8189_APLL1 || apll > MT8189_APLL2) {
+ dev_warn(afe->dev, "invalid clk id %d\n", apll);
+ return 0;
+ }
+
+ if (apll == MT8189_APLL1)
+ clk_id = MT8189_CLK_TOP_APLL1_CK;
+ else
+ clk_id = MT8189_CLK_TOP_APLL2_CK;
+
+ return clk_get_rate(afe_priv->clk[clk_id]);
+}
+
+int mt8189_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
+{
+ return (rate % 8000) ? MT8189_APLL1 : MT8189_APLL2;
+}
+
+int mt8189_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
+{
+ if (strcmp(name, APLL1_W_NAME) == 0)
+ return MT8189_APLL1;
+
+ return MT8189_APLL2;
+}
+
+