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.
This commit is contained in:
Mark Brown
2025-11-19 02:10:20 +00:00
16 changed files with 19755 additions and 0 deletions

View File

@@ -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";
};
};
...

View File

@@ -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>;
};
};
};
...

View File

@@ -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

View File

@@ -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/

View File

@@ -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

View File

@@ -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;
}
int mt8189_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
int apll = mt8189_get_apll_by_rate(afe, rate);
int apll_clk_id = apll == MT8189_APLL1 ?
MT8189_CLK_TOP_MUX_AUD_1 : MT8189_CLK_TOP_MUX_AUD_2;
int m_sel_id;
int div_clk_id;
int ret;
dev_dbg(afe->dev, "mck_id: %d, rate: %d\n", mck_id, rate);
if (mck_id >= MT8189_MCK_NUM || mck_id < 0)
return -EINVAL;
m_sel_id = mck_div[mck_id].m_sel_id;
div_clk_id = mck_div[mck_id].div_clk_id;
/* select apll */
if (m_sel_id >= 0) {
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[m_sel_id]);
if (ret)
return ret;
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[m_sel_id],
afe_priv->clk[apll_clk_id]);
if (ret)
return ret;
}
/* enable div, set rate */
if (div_clk_id < 0) {
dev_err(afe->dev, "invalid div_clk_id %d\n", div_clk_id);
return -EINVAL;
}
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[div_clk_id]);
if (ret)
return ret;
ret = mt8189_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], rate);
if (ret)
return ret;
return 0;
}
int mt8189_mck_disable(struct mtk_base_afe *afe, int mck_id)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
int m_sel_id;
int div_clk_id;
dev_dbg(afe->dev, "mck_id: %d.\n", mck_id);
if (mck_id < 0) {
dev_err(afe->dev, "mck_id = %d < 0\n", mck_id);
return -EINVAL;
}
m_sel_id = mck_div[mck_id].m_sel_id;
div_clk_id = mck_div[mck_id].div_clk_id;
if (div_clk_id < 0) {
dev_err(afe->dev, "div_clk_id = %d < 0\n",
div_clk_id);
return -EINVAL;
}
mt8189_afe_disable_clk(afe, afe_priv->clk[div_clk_id]);
if (m_sel_id >= 0)
mt8189_afe_disable_clk(afe, afe_priv->clk[m_sel_id]);
return 0;
}
int mt8189_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
/* bus clock for AFE internal access, like AFE SRAM */
mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS]);
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS],
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
/* enable audio clock source */
mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
return 0;
}
int mt8189_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS]);
return 0;
}
int mt8189_afe_enable_main_clock(struct mtk_base_afe *afe)
{
return mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_26M_EN_ON);
}
void mt8189_afe_disable_main_clock(struct mtk_base_afe *afe)
{
mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_26M_EN_ON);
}
static int mt8189_afe_enable_ao_clock(struct mtk_base_afe *afe)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
int ret;
/* Peri clock AO enable */
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_INTBUS_CK_PERI]);
if (ret)
return ret;
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI]);
if (ret)
goto err_clk_perao_slv;
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_MST_CK_PERI]);
if (ret)
goto err_clk_perao_mst;
return 0;
err_clk_perao_mst:
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI]);
err_clk_perao_slv:
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_INTBUS_CK_PERI]);
return ret;
}
int mt8189_init_clock(struct mtk_base_afe *afe)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
int ret;
int i;
afe_priv->clk = devm_kcalloc(afe->dev, MT8189_CLK_NUM, sizeof(*afe_priv->clk),
GFP_KERNEL);
if (!afe_priv->clk)
return -ENOMEM;
for (i = 0; i < MT8189_CLK_NUM; i++) {
afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
if (IS_ERR(afe_priv->clk[i])) {
dev_err(afe->dev, "devm_clk_get %s fail\n", aud_clks[i]);
return PTR_ERR(afe_priv->clk[i]);
}
}
ret = mt8189_afe_disable_apll(afe);
if (ret)
return ret;
ret = mt8189_afe_enable_ao_clock(afe);
if (ret)
return ret;
return 0;
}

View File

@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* mt8189-afe-clk.h -- Mediatek 8189 afe clock ctrl definition
*
* Copyright (c) 2025 MediaTek Inc.
* Author: Darren Ye <darren.ye@mediatek.com>
*/
#ifndef _MT8189_AFE_CLOCK_CTRL_H_
#define _MT8189_AFE_CLOCK_CTRL_H_
/* APLL */
#define APLL1_W_NAME "APLL1"
#define APLL2_W_NAME "APLL2"
enum {
MT8189_APLL1,
MT8189_APLL2,
};
enum {
MT8189_CLK_TOP_MUX_AUDIOINTBUS,
MT8189_CLK_TOP_MUX_AUD_ENG1,
MT8189_CLK_TOP_MUX_AUD_ENG2,
MT8189_CLK_TOP_MUX_AUDIO_H,
/* pll */
MT8189_CLK_TOP_APLL1_CK,
MT8189_CLK_TOP_APLL2_CK,
/* divider */
MT8189_CLK_TOP_APLL1_D4,
MT8189_CLK_TOP_APLL2_D4,
MT8189_CLK_TOP_APLL12_DIV_I2SIN0,
MT8189_CLK_TOP_APLL12_DIV_I2SIN1,
MT8189_CLK_TOP_APLL12_DIV_I2SOUT0,
MT8189_CLK_TOP_APLL12_DIV_I2SOUT1,
MT8189_CLK_TOP_APLL12_DIV_FMI2S,
MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M,
MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B,
/* mux */
MT8189_CLK_TOP_MUX_AUD_1,
MT8189_CLK_TOP_MUX_AUD_2,
MT8189_CLK_TOP_I2SIN0_M_SEL,
MT8189_CLK_TOP_I2SIN1_M_SEL,
MT8189_CLK_TOP_I2SOUT0_M_SEL,
MT8189_CLK_TOP_I2SOUT1_M_SEL,
MT8189_CLK_TOP_FMI2S_M_SEL,
MT8189_CLK_TOP_TDMOUT_M_SEL,
/* top 26m */
MT8189_CLK_TOP_CLK26M,
/* peri */
MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI,
MT8189_CLK_PERAO_AUDIO_MST_CK_PERI,
MT8189_CLK_PERAO_INTBUS_CK_PERI,
MT8189_CLK_NUM,
};
struct mtk_base_afe;
int mt8189_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
int mt8189_mck_disable(struct mtk_base_afe *afe, int mck_id);
int mt8189_get_apll_rate(struct mtk_base_afe *afe, int apll);
int mt8189_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
int mt8189_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
int mt8189_init_clock(struct mtk_base_afe *afe);
int mt8189_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
void mt8189_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
int mt8189_apll1_enable(struct mtk_base_afe *afe);
void mt8189_apll1_disable(struct mtk_base_afe *afe);
int mt8189_apll2_enable(struct mtk_base_afe *afe);
void mt8189_apll2_disable(struct mtk_base_afe *afe);
int mt8189_afe_enable_main_clock(struct mtk_base_afe *afe);
void mt8189_afe_disable_main_clock(struct mtk_base_afe *afe);
int mt8189_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
int mt8189_afe_disable_reg_rw_clk(struct mtk_base_afe *afe);
#endif

View File

@@ -0,0 +1,240 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* mt8189-afe-common.h -- Mediatek 8189 audio driver definitions
*
* Copyright (c) 2025 MediaTek Inc.
* Author: Darren Ye <darren.ye@mediatek.com>
*/
#ifndef _MT_8189_AFE_COMMON_H_
#define _MT_8189_AFE_COMMON_H_
#include <linux/regmap.h>
#include <sound/soc.h>
#include "mt8189-reg.h"
#include "../common/mtk-base-afe.h"
enum {
MTK_AFE_RATE_8K,
MTK_AFE_RATE_11K,
MTK_AFE_RATE_12K,
MTK_AFE_RATE_384K,
MTK_AFE_RATE_16K,
MTK_AFE_RATE_22K,
MTK_AFE_RATE_24K,
MTK_AFE_RATE_352K,
MTK_AFE_RATE_32K,
MTK_AFE_RATE_44K,
MTK_AFE_RATE_48K,
MTK_AFE_RATE_88K,
MTK_AFE_RATE_96K,
MTK_AFE_RATE_176K,
MTK_AFE_RATE_192K,
MTK_AFE_RATE_260K,
};
/* HW IPM 2.0 */
enum {
MTK_AFE_IPM2P0_RATE_8K = 0x0,
MTK_AFE_IPM2P0_RATE_11K = 0x1,
MTK_AFE_IPM2P0_RATE_12K = 0x2,
MTK_AFE_IPM2P0_RATE_16K = 0x4,
MTK_AFE_IPM2P0_RATE_22K = 0x5,
MTK_AFE_IPM2P0_RATE_24K = 0x6,
MTK_AFE_IPM2P0_RATE_32K = 0x8,
MTK_AFE_IPM2P0_RATE_44K = 0x9,
MTK_AFE_IPM2P0_RATE_48K = 0xa,
MTK_AFE_IPM2P0_RATE_88K = 0xd,
MTK_AFE_IPM2P0_RATE_96K = 0xe,
MTK_AFE_IPM2P0_RATE_176K = 0x11,
MTK_AFE_IPM2P0_RATE_192K = 0x12,
MTK_AFE_IPM2P0_RATE_352K = 0x15,
MTK_AFE_IPM2P0_RATE_384K = 0x16,
};
enum {
MTK_AFE_DAI_MEMIF_RATE_8K,
MTK_AFE_DAI_MEMIF_RATE_16K,
MTK_AFE_DAI_MEMIF_RATE_32K,
MTK_AFE_DAI_MEMIF_RATE_48K,
};
enum {
MTK_AFE_PCM_RATE_8K,
MTK_AFE_PCM_RATE_16K,
MTK_AFE_PCM_RATE_32K,
MTK_AFE_PCM_RATE_48K,
};
enum {
MTKAIF_PROTOCOL_1,
MTKAIF_PROTOCOL_2,
MTKAIF_PROTOCOL_2_CLK_P2,
};
enum {
MT8189_MEMIF_DL0,
MT8189_MEMIF_DL1,
MT8189_MEMIF_DL2,
MT8189_MEMIF_DL3,
MT8189_MEMIF_DL4,
MT8189_MEMIF_DL5,
MT8189_MEMIF_DL6,
MT8189_MEMIF_DL7,
MT8189_MEMIF_DL8,
MT8189_MEMIF_DL23,
MT8189_MEMIF_DL24,
MT8189_MEMIF_DL25,
MT8189_MEMIF_DL_24CH,
MT8189_MEMIF_VUL0,
MT8189_MEMIF_VUL1,
MT8189_MEMIF_VUL2,
MT8189_MEMIF_VUL3,
MT8189_MEMIF_VUL4,
MT8189_MEMIF_VUL5,
MT8189_MEMIF_VUL6,
MT8189_MEMIF_VUL7,
MT8189_MEMIF_VUL8,
MT8189_MEMIF_VUL9,
MT8189_MEMIF_VUL10,
MT8189_MEMIF_VUL24,
MT8189_MEMIF_VUL25,
MT8189_MEMIF_VUL_CM0,
MT8189_MEMIF_VUL_CM1,
MT8189_MEMIF_ETDM_IN0,
MT8189_MEMIF_ETDM_IN1,
MT8189_MEMIF_HDMI,
MT8189_MEMIF_NUM,
MT8189_DAI_ADDA = MT8189_MEMIF_NUM,
MT8189_DAI_ADDA_CH34,
MT8189_DAI_ADDA_CH56,
MT8189_DAI_AP_DMIC,
MT8189_DAI_AP_DMIC_CH34,
MT8189_DAI_I2S_IN0,
MT8189_DAI_I2S_IN1,
MT8189_DAI_I2S_OUT0,
MT8189_DAI_I2S_OUT1,
MT8189_DAI_I2S_OUT4,
MT8189_DAI_PCM_0,
MT8189_DAI_TDM,
MT8189_DAI_TDM_DPTX,
MT8189_DAI_NUM,
};
/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
enum {
MT8189_IRQ_0,
MT8189_IRQ_1,
MT8189_IRQ_2,
MT8189_IRQ_3,
MT8189_IRQ_4,
MT8189_IRQ_5,
MT8189_IRQ_6,
MT8189_IRQ_7,
MT8189_IRQ_8,
MT8189_IRQ_9,
MT8189_IRQ_10,
MT8189_IRQ_11,
MT8189_IRQ_12,
MT8189_IRQ_13,
MT8189_IRQ_14,
MT8189_IRQ_15,
MT8189_IRQ_16,
MT8189_IRQ_17,
MT8189_IRQ_18,
MT8189_IRQ_19,
MT8189_IRQ_20,
MT8189_IRQ_21,
MT8189_IRQ_22,
MT8189_IRQ_23,
MT8189_IRQ_24,
MT8189_IRQ_25,
MT8189_IRQ_26,
MT8189_IRQ_31,
MT8189_IRQ_NUM,
};
/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
enum {
MT8189_CUS_IRQ_TDM, /* used only for TDM */
MT8189_CUS_IRQ_NUM,
};
enum {
/* AUDIO_ENGEN_CON0 */
MT8189_AUDIO_26M_EN_ON,
MT8189_AUDIO_F3P25M_EN_ON,
MT8189_AUDIO_APLL1_EN_ON,
MT8189_AUDIO_APLL2_EN_ON,
MT8189_AUDIO_F26M_EN_RST,
MT8189_MULTI_USER_RST,
MT8189_MULTI_USER_BYPASS,
/* AUDIO_TOP_CON4 */
MT8189_CG_AUDIO_HOPPING_CK,
MT8189_CG_AUDIO_F26M_CK,
MT8189_CG_APLL1_CK,
MT8189_CG_APLL2_CK,
MT8189_PDN_APLL_TUNER2,
MT8189_PDN_APLL_TUNER1,
MT8189_AUDIO_CG_NUM,
};
/* MCLK */
enum {
MT8189_I2SIN0_MCK,
MT8189_I2SIN1_MCK,
MT8189_I2SOUT0_MCK,
MT8189_I2SOUT1_MCK,
MT8189_FMI2S_MCK,
MT8189_TDMOUT_MCK,
MT8189_TDMOUT_BCK,
MT8189_MCK_NUM,
};
enum {
CM0,
CM1,
CM_NUM,
};
struct clk;
struct mt8189_afe_private {
struct clk **clk;
struct regmap *pmic_regmap;
/* dai */
void *dai_priv[MT8189_DAI_NUM];
/* adda */
int mtkaif_protocol;
int mtkaif_chosen_phase[4];
int mtkaif_phase_cycle[4];
int mtkaif_calibration_num_phase;
int mtkaif_dmic;
int mtkaif_dmic_ch34;
/* add for vs1 voter */
bool is_adda_dl_on;
bool is_adda_ul_on;
/* adda dl vol idx is at maximum */
bool is_adda_dl_max_vol;
/* current vote status of vs1 */
bool is_mt6363_vote;
/* mck */
int mck_rate[MT8189_MCK_NUM];
/* channel merge */
unsigned int cm_rate[CM_NUM];
unsigned int cm_channels;
};
int mt8189_dai_adda_register(struct mtk_base_afe *afe);
int mt8189_dai_i2s_register(struct mtk_base_afe *afe);
int mt8189_dai_pcm_register(struct mtk_base_afe *afe);
int mt8189_dai_tdm_register(struct mtk_base_afe *afe);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,332 @@
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek ALSA SoC Audio DAI I2S Control
*
* Copyright (c) 2025 MediaTek Inc.
* Author: Darren Ye <darren.ye@mediatek.com>
*/
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8189-afe-common.h"
#include "mt8189-interconnection.h"
#include "mt8189-afe-clk.h"
enum AUD_TX_LCH_RPT {
AUD_TX_LCH_RPT_NO_REPEAT,
AUD_TX_LCH_RPT_REPEAT
};
enum AUD_VBT_16K_MODE {
AUD_VBT_16K_MODE_DISABLE,
AUD_VBT_16K_MODE_ENABLE
};
enum AUD_EXT_MODEM {
AUD_EXT_MODEM_SELECT_INTERNAL,
AUD_EXT_MODEM_SELECT_EXTERNAL
};
enum AUD_PCM_SYNC_TYPE {
/* bck sync length = 1 */
AUD_PCM_ONE_BCK_CYCLE_SYNC,
/* bck sync length = PCM_INTF_CON1[9:13] */
AUD_PCM_EXTENDED_BCK_CYCLE_SYNC
};
enum AUD_BT_MODE {
AUD_BT_MODE_DUAL_MIC_ON_TX,
AUD_BT_MODE_SINGLE_MIC_ON_TX
};
enum AUD_PCM_AFIFO_SRC {
/* slave mode & external modem uses different crystal */
AUD_PCM_AFIFO_ASRC,
/* slave mode & external modem uses the same crystal */
AUD_PCM_AFIFO_AFIFO
};
enum AUD_PCM_CLOCK_SOURCE {
AUD_PCM_CLOCK_MASTER_MODE,
AUD_PCM_CLOCK_SLAVE_MODE
};
enum AUD_PCM_WLEN {
AUD_PCM_WLEN_PCM_32_BCK_CYCLES,
AUD_PCM_WLEN_PCM_64_BCK_CYCLES
};
enum AUD_PCM_MODE {
AUD_PCM_MODE_PCM_MODE_8K,
AUD_PCM_MODE_PCM_MODE_16K,
AUD_PCM_MODE_PCM_MODE_32K,
AUD_PCM_MODE_PCM_MODE_48K
};
enum AUD_PCM_FMT {
AUD_PCM_FMT_I2S,
AUD_PCM_FMT_EIAJ,
AUD_PCM_FMT_PCM_MODE_A,
AUD_PCM_FMT_PCM_MODE_B
};
enum AUD_BCLK_OUT_INV {
AUD_BCLK_OUT_INV_NO_INVERSE,
AUD_BCLK_OUT_INV_INVERSE
};
enum AUD_PCM_EN {
AUD_PCM_EN_DISABLE,
AUD_PCM_EN_ENABLE
};
enum AUD_PCM1_1X_EN_DOMAIN {
HOPPING_26M,
APLL,
SLAVE = 6
};
enum AUD_PCM1_1X_EN_SLAVE_MODE {
PCM0_SLAVE_1X_EN,
PCM1_SLAVE_1X_EN
};
enum {
PCM_8K,
PCM_16K = 4,
PCM_32K = 8,
PCM_48K = 10
};
static unsigned int pcm_1x_rate_transform(struct device *dev,
unsigned int rate)
{
switch (rate) {
case 8000:
return PCM_8K;
case 16000:
return PCM_16K;
case 32000:
return PCM_32K;
case 48000:
return PCM_48K;
default:
dev_warn(dev, "rate %u invalid, use %d!!!\n",
rate, PCM_48K);
return PCM_48K;
}
}
static unsigned int pcm_rate_transform(struct device *dev,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_PCM_RATE_8K;
case 16000:
return MTK_AFE_PCM_RATE_16K;
case 32000:
return MTK_AFE_PCM_RATE_32K;
case 48000:
return MTK_AFE_PCM_RATE_48K;
default:
dev_warn(dev, "rate %u invalid, use %d\n",
rate, MTK_AFE_PCM_RATE_48K);
return MTK_AFE_PCM_RATE_48K;
}
}
/* dai component */
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN096_0,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN096_1,
I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN096_1,
I_DL_24CH_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN097_0,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN097_1,
I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN097_1,
I_DL_24CH_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch4_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH1", AFE_CONN099_4,
I_I2SIN1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH2", AFE_CONN099_4,
I_I2SIN1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN099_1,
I_DL0_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN099_1,
I_DL_24CH_CH1, 1, 0),
};
static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("PCM_0_PB_CH1", SND_SOC_NOPM, 0, 0,
mtk_pcm_0_playback_ch1_mix,
ARRAY_SIZE(mtk_pcm_0_playback_ch1_mix)),
SND_SOC_DAPM_MIXER("PCM_0_PB_CH2", SND_SOC_NOPM, 0, 0,
mtk_pcm_0_playback_ch2_mix,
ARRAY_SIZE(mtk_pcm_0_playback_ch2_mix)),
SND_SOC_DAPM_MIXER("PCM_0_PB_CH4", SND_SOC_NOPM, 0, 0,
mtk_pcm_0_playback_ch4_mix,
ARRAY_SIZE(mtk_pcm_0_playback_ch4_mix)),
SND_SOC_DAPM_SUPPLY("PCM_0_EN",
AFE_PCM0_INTF_CON0, PCM0_EN_SFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("PCM0_CG", AUDIO_TOP_CON0, PDN_PCM0_SFT, 1,
NULL, 0),
SND_SOC_DAPM_INPUT("AFE_PCM_INPUT"),
SND_SOC_DAPM_OUTPUT("AFE_PCM_OUTPUT"),
};
static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
{"PCM 0 Playback", NULL, "PCM_0_PB_CH1"},
{"PCM 0 Playback", NULL, "PCM_0_PB_CH2"},
{"PCM 0 Playback", NULL, "PCM_0_PB_CH4"},
{"PCM 0 Playback", NULL, "PCM_0_EN"},
{"PCM 0 Capture", NULL, "PCM_0_EN"},
{"PCM 0 Playback", NULL, "PCM0_CG"},
{"PCM 0 Capture", NULL, "PCM0_CG"},
{"AFE_PCM_OUTPUT", NULL, "PCM 0 Playback"},
{"PCM 0 Capture", NULL, "AFE_PCM_INPUT"},
{"PCM_0_PB_CH1", "DL2_CH1", "DL2"},
{"PCM_0_PB_CH2", "DL2_CH2", "DL2"},
{"PCM_0_PB_CH4", "DL0_CH1", "DL0"},
{"PCM_0_PB_CH1", "DL_24CH_CH1", "DL_24CH"},
{"PCM_0_PB_CH2", "DL_24CH_CH2", "DL_24CH"},
{"PCM_0_PB_CH4", "DL_24CH_CH1", "DL_24CH"},
};
/* 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);
unsigned int rate = params_rate(params);
unsigned int rate_reg = pcm_rate_transform(afe->dev, rate);
unsigned int x_rate_reg = pcm_1x_rate_transform(afe->dev, rate);
unsigned int pcm_con0;
unsigned int pcm_con1;
unsigned int playback_active = 0;
unsigned int capture_active = 0;
struct snd_soc_dapm_widget *playback_widget =
snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_PLAYBACK);
struct snd_soc_dapm_widget *capture_widget =
snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_CAPTURE);
if (playback_widget)
playback_active = playback_widget->active;
if (capture_widget)
capture_active = capture_widget->active;
dev_dbg(afe->dev,
"id %d, stream %d, rate %d, rate_reg %d, active p %d, c %d\n",
dai->id, substream->stream, rate, rate_reg,
playback_active, capture_active);
if (playback_active || capture_active)
return 0;
switch (dai->id) {
case MT8189_DAI_PCM_0:
pcm_con0 = AUD_BCLK_OUT_INV_NO_INVERSE << PCM0_BCLK_OUT_INV_SFT;
pcm_con0 |= AUD_TX_LCH_RPT_NO_REPEAT << PCM0_TX_LCH_RPT_SFT;
pcm_con0 |= AUD_VBT_16K_MODE_DISABLE << PCM0_VBT_16K_MODE_SFT;
pcm_con0 |= 0 << PCM0_SYNC_LENGTH_SFT;
pcm_con0 |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM0_SYNC_TYPE_SFT;
pcm_con0 |= AUD_PCM_AFIFO_AFIFO << PCM0_BYP_ASRC_SFT;
pcm_con0 |= AUD_PCM_CLOCK_MASTER_MODE << PCM0_SLAVE_SFT;
pcm_con0 |= rate_reg << PCM0_MODE_SFT;
pcm_con0 |= AUD_PCM_FMT_I2S << PCM0_FMT_SFT;
pcm_con1 = AUD_EXT_MODEM_SELECT_INTERNAL << PCM0_EXT_MODEM_SFT;
pcm_con1 |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM0_BT_MODE_SFT;
pcm_con1 |= HOPPING_26M << PCM0_1X_EN_DOMAIN_SFT;
pcm_con1 |= x_rate_reg << PCM0_1X_EN_MODE_SFT;
regmap_update_bits(afe->regmap, AFE_PCM0_INTF_CON0,
~(unsigned int)PCM0_EN_MASK_SFT, pcm_con0);
regmap_update_bits(afe->regmap, AFE_PCM0_INTF_CON1,
AFE_PCM0_INTF_CON1_MASK_MON_MASK_SFT,
pcm_con1);
break;
default:
dev_err(afe->dev, "%s(), id %d not support\n",
__func__, dai->id);
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
.hw_params = mtk_dai_pcm_hw_params,
};
/* 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 0",
.id = MT8189_DAI_PCM_0,
.playback = {
.stream_name = "PCM 0 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.capture = {
.stream_name = "PCM 0 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,
},
};
int mt8189_dai_pcm_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;
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);
list_add(&dai->list, &afe->sub_dais);
return 0;
}

View File

@@ -0,0 +1,672 @@
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek ALSA SoC Audio DAI TDM Control
*
* Copyright (c) 2025 MediaTek Inc.
* Author: Darren Ye <darren.ye@mediatek.com>
*/
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8189-afe-clk.h"
#include "mt8189-afe-common.h"
#include "mt8189-interconnection.h"
#define DPTX_CH_EN_MASK_2CH (0x3)
#define DPTX_CH_EN_MASK_4CH (0xf)
#define DPTX_CH_EN_MASK_6CH (0x3f)
#define DPTX_CH_EN_MASK_8CH (0xff)
enum {
SUPPLY_SEQ_APLL,
SUPPLY_SEQ_TDM_MCK_EN,
SUPPLY_SEQ_TDM_BCK_EN,
SUPPLY_SEQ_TDM_DPTX_MCK_EN,
SUPPLY_SEQ_TDM_DPTX_BCK_EN,
SUPPLY_SEQ_TDM_CG_EN,
};
enum {
TDM_WLEN_8_BIT,
TDM_WLEN_16_BIT,
TDM_WLEN_24_BIT,
TDM_WLEN_32_BIT,
};
enum {
TDM_CHANNEL_BCK_16,
TDM_CHANNEL_BCK_24,
TDM_CHANNEL_BCK_32
};
enum {
TDM_CHANNEL_NUM_2,
TDM_CHANNEL_NUM_4,
TDM_CHANNEL_NUM_8
};
enum {
TDM_CH_START_O30_O31,
TDM_CH_START_O32_O33,
TDM_CH_START_O34_O35,
TDM_CH_START_O36_O37,
TDM_CH_ZERO,
};
enum {
DPTX_CHANNEL_2,
DPTX_CHANNEL_8,
};
enum {
DPTX_WLEN_24_BIT,
DPTX_WLEN_16_BIT,
};
struct mtk_afe_tdm_priv {
int bck_id;
int bck_rate;
int mclk_id;
int mclk_multiple; /* according to sample rate */
int mclk_rate;
int mclk_apll;
};
static unsigned int get_tdm_wlen(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
}
static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
}
static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) - 1;
}
static unsigned int get_tdm_ch(unsigned int ch)
{
switch (ch) {
case 1:
case 2:
return TDM_CHANNEL_NUM_2;
case 3:
case 4:
return TDM_CHANNEL_NUM_4;
case 5:
case 6:
case 7:
case 8:
default:
return TDM_CHANNEL_NUM_8;
}
}
static unsigned int get_dptx_ch_enable_mask(unsigned int ch)
{
switch (ch) {
case 1:
case 2:
return DPTX_CH_EN_MASK_2CH;
case 3:
case 4:
return DPTX_CH_EN_MASK_4CH;
case 5:
case 6:
return DPTX_CH_EN_MASK_6CH;
case 7:
case 8:
return DPTX_CH_EN_MASK_8CH;
default:
return DPTX_CH_EN_MASK_2CH;
}
}
static unsigned int get_dptx_ch(unsigned int ch)
{
if (ch == 2)
return DPTX_CHANNEL_2;
return DPTX_CHANNEL_8;
}
static unsigned int get_dptx_wlen(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT;
}
/* interconnection */
enum {
HDMI_CONN_CH0,
HDMI_CONN_CH1,
HDMI_CONN_CH2,
HDMI_CONN_CH3,
HDMI_CONN_CH4,
HDMI_CONN_CH5,
HDMI_CONN_CH6,
HDMI_CONN_CH7,
};
static const char *const hdmi_conn_mux_map[] = {
"CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
};
static int hdmi_conn_mux_map_value[] = {
HDMI_CONN_CH0, HDMI_CONN_CH1, HDMI_CONN_CH2, HDMI_CONN_CH3,
HDMI_CONN_CH4, HDMI_CONN_CH5, HDMI_CONN_CH6, HDMI_CONN_CH7,
};
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_0_SFT,
HDMI_O_0_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_1_SFT,
HDMI_O_1_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_2_SFT,
HDMI_O_2_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_3_SFT,
HDMI_O_3_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_4_SFT,
HDMI_O_4_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_5_SFT,
HDMI_O_5_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_6_SFT,
HDMI_O_6_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_7_SFT,
HDMI_O_7_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
SOC_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum),
SOC_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum),
SOC_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum),
SOC_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum),
SOC_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum),
SOC_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum),
SOC_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum),
SOC_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum),
};
static const char *const tdm_out_demux_texts[] = {
"NONE", "TDMOUT", "DPTXOUT",
};
static SOC_ENUM_SINGLE_DECL(tdm_out_demux_enum,
SND_SOC_NOPM,
0,
tdm_out_demux_texts);
static const struct snd_kcontrol_new tdm_out_demux_control =
SOC_DAPM_ENUM("TDM Playback Route", tdm_out_demux_enum);
static int get_tdm_id_by_name(const char *name)
{
if (strstr(name, "DPTX"))
return MT8189_DAI_TDM_DPTX;
return MT8189_DAI_TDM;
}
static int mtk_tdm_bck_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 mt8189_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];
dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, bck: %d\n",
w->name, event, dai_id, tdm_priv->bck_rate);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8189_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
break;
case SND_SOC_DAPM_POST_PMD:
mt8189_mck_disable(afe, tdm_priv->bck_id);
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 mt8189_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];
dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, mclk %d\n",
w->name, event, dai_id, tdm_priv->mclk_rate);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8189_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
break;
case SND_SOC_DAPM_POST_PMD:
tdm_priv->mclk_rate = 0;
mt8189_mck_disable(afe, tdm_priv->mclk_id);
break;
default:
break;
}
return 0;
}
static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
SND_SOC_DAPM_DEMUX("TDM Playback Route", SND_SOC_NOPM, 0, 0,
&tdm_out_demux_control),
SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
SND_SOC_NOPM, 0, 0,
mtk_tdm_bck_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("TDM_MCK", 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_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN,
SND_SOC_NOPM, 0, 0,
mtk_tdm_bck_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_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_SUPPLY_S("TDM_CG", SUPPLY_SEQ_TDM_CG_EN,
AUDIO_TOP_CON2, PDN_TDM_OUT_SFT, 1,
NULL, 0),
};
static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8189_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_tdm_id_by_name(sink->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
int cur_apll;
/* which apll */
cur_apll = mt8189_get_apll_by_name(afe, source->name);
return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
}
static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
{"TDM Playback Route", NULL, "HDMI"},
{"TDM", "TDMOUT", "TDM Playback Route"},
{"TDM", NULL, "TDM_BCK"},
{"TDM", NULL, "TDM_CG"},
{"TDM_DPTX", "DPTXOUT", "TDM Playback Route"},
{"TDM_DPTX", NULL, "TDM_DPTX_BCK"},
{"TDM_DPTX", NULL, "TDM_CG"},
{"TDM_BCK", NULL, "TDM_MCK"},
{"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"},
{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
{"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
{"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
};
/* 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 = mt8189_get_apll_by_rate(afe, freq);
apll_rate = mt8189_get_apll_rate(afe, apll);
if (freq > apll_rate)
return -EINVAL;
if (apll_rate % freq != 0)
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 mt8189_afe_private *afe_priv = afe->platform_priv;
int tdm_id = dai->id;
struct mtk_afe_tdm_priv *tdm_priv;
unsigned int rate = params_rate(params);
unsigned int channels = params_channels(params);
snd_pcm_format_t format = params_format(params);
unsigned int tdm_con;
if (tdm_id >= MT8189_DAI_NUM || tdm_id < 0)
return -EINVAL;
tdm_priv = afe_priv->dai_priv[tdm_id];
/* 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);
}
/* calculate bck */
tdm_priv->bck_rate = rate *
channels *
snd_pcm_format_physical_width(format);
if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
return -EINVAL;
if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
return -EINVAL;
dev_dbg(afe->dev, "id %d, rate %d, ch %d, fmt %d, mclk %d, bck %d\n",
tdm_id, rate, channels, format,
tdm_priv->mclk_rate, tdm_priv->bck_rate);
/* set tdm */
tdm_con = 1 << LEFT_ALIGN_SFT;
tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT;
tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
/* set dptx */
if (tdm_id == MT8189_DAI_TDM_DPTX) {
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
DPTX_CHANNEL_ENABLE_MASK_SFT,
get_dptx_ch_enable_mask(channels) <<
DPTX_CHANNEL_ENABLE_SFT);
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
DPTX_CHANNEL_NUMBER_MASK_SFT,
get_dptx_ch(channels) <<
DPTX_CHANNEL_NUMBER_SFT);
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
DPTX_16BIT_MASK_SFT,
get_dptx_wlen(format) << DPTX_16BIT_SFT);
}
switch (channels) {
case 1:
case 2:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 3:
case 4:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 5:
case 6:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 7:
case 8:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
break;
default:
tdm_con = 0;
}
regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
HDMI_CH_NUM_MASK_SFT,
channels << HDMI_CH_NUM_SFT);
return 0;
}
static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
int cmd,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int tdm_id = dai->id;
dev_dbg(afe->dev, "%s(), cmd %d, tdm_id %d\n", __func__, cmd, tdm_id);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
/* enable Out control */
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
HDMI_OUT_ON_MASK_SFT,
0x1 << HDMI_OUT_ON_SFT);
/* enable dptx */
if (tdm_id == MT8189_DAI_TDM_DPTX) {
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
DPTX_ON_MASK_SFT, 0x1 <<
DPTX_ON_SFT);
}
/* enable tdm */
regmap_update_bits(afe->regmap, AFE_TDM_CON1,
TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
/* disable tdm */
regmap_update_bits(afe->regmap, AFE_TDM_CON1,
TDM_EN_MASK_SFT, 0);
/* disable dptx */
if (tdm_id == MT8189_DAI_TDM_DPTX) {
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
DPTX_ON_MASK_SFT, 0);
}
/* disable Out control */
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
HDMI_OUT_ON_MASK_SFT, 0);
break;
default:
return -EINVAL;
}
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 mt8189_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv;
if (dai->id >= MT8189_DAI_NUM || dai->id < 0)
return -EINVAL;
tdm_priv = afe_priv->dai_priv[dai->id];
if (!tdm_priv)
return -EINVAL;
if (dir != SND_SOC_CLOCK_OUT)
return -EINVAL;
dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);
return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
}
static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
.hw_params = mtk_dai_tdm_hw_params,
.trigger = mtk_dai_tdm_trigger,
.set_sysclk = mtk_dai_tdm_set_sysclk,
};
/* 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",
.id = MT8189_DAI_TDM,
.playback = {
.stream_name = "TDM",
.channels_min = 2,
.channels_max = 8,
.rates = MTK_TDM_RATES,
.formats = MTK_TDM_FORMATS,
},
.ops = &mtk_dai_tdm_ops,
},
{
.name = "TDM_DPTX",
.id = MT8189_DAI_TDM_DPTX,
.playback = {
.stream_name = "TDM_DPTX",
.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,
int id)
{
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;
if (id == MT8189_DAI_TDM_DPTX)
tdm_priv->mclk_multiple = 256;
else
tdm_priv->mclk_multiple = 128;
tdm_priv->bck_id = MT8189_TDMOUT_BCK;
tdm_priv->mclk_id = MT8189_TDMOUT_MCK;
return tdm_priv;
}
int mt8189_dai_tdm_register(struct mtk_base_afe *afe)
{
struct mt8189_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv;
struct mtk_base_afe_dai *dai;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
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, MT8189_DAI_TDM);
if (!tdm_priv)
return -ENOMEM;
tdm_dptx_priv = init_tdm_priv_data(afe, MT8189_DAI_TDM_DPTX);
if (!tdm_dptx_priv)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
afe_priv->dai_priv[MT8189_DAI_TDM] = tdm_priv;
afe_priv->dai_priv[MT8189_DAI_TDM_DPTX] = tdm_dptx_priv;
return 0;
}

View File

@@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Mediatek MT8189 audio driver interconnection definition
*
* Copyright (c) 2025 MediaTek Inc.
* Author: Darren Ye <darren.ye@mediatek.com>
*/
#ifndef _MT8189_INTERCONNECTION_H_
#define _MT8189_INTERCONNECTION_H_
/* in port define */
#define I_CONNSYS_I2S_CH1 0
#define I_CONNSYS_I2S_CH2 1
#define I_GAIN0_OUT_CH1 6
#define I_GAIN0_OUT_CH2 7
#define I_GAIN1_OUT_CH1 8
#define I_GAIN1_OUT_CH2 9
#define I_GAIN2_OUT_CH1 10
#define I_GAIN2_OUT_CH2 11
#define I_GAIN3_OUT_CH1 12
#define I_GAIN3_OUT_CH2 13
#define I_STF_CH1 14
#define I_ADDA_UL_CH1 16
#define I_ADDA_UL_CH2 17
#define I_ADDA_UL_CH3 18
#define I_ADDA_UL_CH4 19
#define I_UL_PROX_CH1 20
#define I_UL_PROX_CH2 21
#define I_ADDA_UL_CH5 24
#define I_ADDA_UL_CH6 25
#define I_DMIC0_CH1 28
#define I_DMIC0_CH2 29
#define I_DMIC1_CH1 30
#define I_DMIC1_CH2 31
/* in port define >= 32 */
#define I_32_OFFSET 32
#define I_DL0_CH1 (32 - I_32_OFFSET)
#define I_DL0_CH2 (33 - I_32_OFFSET)
#define I_DL1_CH1 (34 - I_32_OFFSET)
#define I_DL1_CH2 (35 - I_32_OFFSET)
#define I_DL2_CH1 (36 - I_32_OFFSET)
#define I_DL2_CH2 (37 - I_32_OFFSET)
#define I_DL3_CH1 (38 - I_32_OFFSET)
#define I_DL3_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_DL_24CH_CH1 (54 - I_32_OFFSET)
#define I_DL_24CH_CH2 (55 - I_32_OFFSET)
#define I_DL_24CH_CH3 (56 - I_32_OFFSET)
#define I_DL_24CH_CH4 (57 - I_32_OFFSET)
#define I_DL_24CH_CH5 (58 - I_32_OFFSET)
#define I_DL_24CH_CH6 (59 - I_32_OFFSET)
#define I_DL_24CH_CH7 (60 - I_32_OFFSET)
#define I_DL_24CH_CH8 (61 - I_32_OFFSET)
/* in port define >= 64 */
#define I_64_OFFSET 64
#define I_DL23_CH1 (78 - I_64_OFFSET)
#define I_DL23_CH2 (79 - I_64_OFFSET)
#define I_DL24_CH1 (80 - I_64_OFFSET)
#define I_DL24_CH2 (81 - I_64_OFFSET)
#define I_DL25_CH1 (82 - I_64_OFFSET)
#define I_DL25_CH2 (83 - I_64_OFFSET)
/* in port define >= 128 */
#define I_128_OFFSET 128
#define I_PCM_0_CAP_CH1 (130 - I_128_OFFSET)
#define I_PCM_0_CAP_CH2 (131 - I_128_OFFSET)
#define I_I2SIN0_CH1 (134 - I_128_OFFSET)
#define I_I2SIN0_CH2 (135 - I_128_OFFSET)
#define I_I2SIN1_CH1 (136 - I_128_OFFSET)
#define I_I2SIN1_CH2 (137 - I_128_OFFSET)
/* in port define >= 192 */
#define I_192_OFFSET 192
#define I_SRC_0_OUT_CH1 (198 - I_192_OFFSET)
#define I_SRC_0_OUT_CH2 (199 - I_192_OFFSET)
#define I_SRC_1_OUT_CH1 (200 - I_192_OFFSET)
#define I_SRC_1_OUT_CH2 (201 - I_192_OFFSET)
#define I_SRC_2_OUT_CH1 (202 - I_192_OFFSET)
#define I_SRC_2_OUT_CH2 (203 - I_192_OFFSET)
#define I_SRC_3_OUT_CH1 (204 - I_192_OFFSET)
#define I_SRC_3_OUT_CH2 (205 - I_192_OFFSET)
#define I_SRC_4_OUT_CH1 (206 - I_192_OFFSET)
#define I_SRC_4_OUT_CH2 (207 - I_192_OFFSET)
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff