diff options
| author | Mark Brown <broonie@kernel.org> | 2025-11-19 02:10:20 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2025-11-19 02:10:20 +0000 |
| commit | 683c03b95c2ae95ff05ebf0dcc040bf3db633135 (patch) | |
| tree | 467cb93969d50a0aac9c35e5a89450c63dc4b603 | |
| parent | e45979641a9a9dbb48fc77c5b36a5091a92e7227 (diff) | |
| parent | d218ea171430e49412804efb794942dd121a8032 (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.yaml | 178 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/sound/mediatek,mt8189-nau8825.yaml | 101 | ||||
| -rw-r--r-- | sound/soc/mediatek/Kconfig | 31 | ||||
| -rw-r--r-- | sound/soc/mediatek/Makefile | 1 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/Makefile | 18 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-afe-clk.c | 750 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-afe-clk.h | 76 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-afe-common.h | 240 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-afe-pcm.c | 2617 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-dai-adda.c | 1228 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-dai-i2s.c | 1463 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-dai-pcm.c | 332 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-dai-tdm.c | 672 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-interconnection.h | 97 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-nau8825.c | 1178 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8189/mt8189-reg.h | 10773 |
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; +} + + |
