Commit 9a029545 authored by Mark Brown's avatar Mark Brown

Add audio support for the MediaTek Genio 350-evk

Merge series from Alexandre Mergnat <amergnat@baylibre.com>:

This serie aim to add the following audio support for the Genio 350-evk:
- Playback
  - 2ch Headset Jack (Earphone)
  - 1ch Line-out Jack (Speaker)
  - 8ch HDMI Tx
- Capture
  - 1ch DMIC (On-board Digital Microphone)
  - 1ch AMIC (On-board Analogic Microphone)
  - 1ch Headset Jack (External Analogic Microphone)

Of course, HDMI playback need the MT8365 display patches [1] and a DTS
change documented in "mediatek,mt8365-mt6357.yaml".

Applied patch:
- mfd: mt6397-core: register mt6357 sound codec

Test passed:
- mixer-test log: [3]
- pcm-test log: [4]

[1]: https://lore.kernel.org/all/20231023-display-support-v1-0-5c860ed5c33b@baylibre.com/
[2]: https://lore.kernel.org/all/20240313110147.1267793-1-angelogioacchino.delregno@collabora.com/
[3]: https://pastebin.com/pc43AVrT
[4]: https://pastebin.com/cCtGhDpg
[5]: https://gitlab.baylibre.com/baylibre/mediatek/bsp/linux/-/commits/sound/for-next/add-i350-audio-support
parents 97688a9c e1991d10
......@@ -37,6 +37,24 @@ properties:
"#interrupt-cells":
const: 2
mediatek,hp-pull-down:
description:
Earphone driver positive output stage short to
the audio reference ground.
type: boolean
mediatek,micbias0-microvolt:
description: Selects MIC Bias 0 output voltage.
enum: [1700000, 1800000, 1900000, 2000000,
2100000, 2500000, 2600000, 2700000]
default: 1700000
mediatek,micbias1-microvolt:
description: Selects MIC Bias 1 output voltage.
enum: [1700000, 1800000, 1900000, 2000000,
2100000, 2500000, 2600000, 2700000]
default: 1700000
regulators:
type: object
$ref: /schemas/regulator/mediatek,mt6357-regulator.yaml
......@@ -83,6 +101,9 @@ examples:
interrupt-controller;
#interrupt-cells = <2>;
mediatek,micbias0-microvolt = <1700000>;
mediatek,micbias1-microvolt = <1700000>;
regulators {
mt6357_vproc_reg: buck-vproc {
regulator-name = "vproc";
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8365-afe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Audio Front End PCM controller for MT8365
maintainers:
- Alexandre Mergnat <amergnat@baylibre.com>
properties:
compatible:
const: mediatek,mt8365-afe-pcm
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
items:
- description: 26M clock
- description: mux for audio clock
- description: audio i2s0 mck
- description: audio i2s1 mck
- description: audio i2s2 mck
- description: audio i2s3 mck
- description: engen 1 clock
- description: engen 2 clock
- description: audio 1 clock
- description: audio 2 clock
- description: mux for i2s0
- description: mux for i2s1
- description: mux for i2s2
- description: mux for i2s3
clock-names:
items:
- const: top_clk26m_clk
- const: top_audio_sel
- const: audio_i2s0_m
- const: audio_i2s1_m
- const: audio_i2s2_m
- const: audio_i2s3_m
- const: engen1
- const: engen2
- const: aud1
- const: aud2
- const: i2s0_m_sel
- const: i2s1_m_sel
- const: i2s2_m_sel
- const: i2s3_m_sel
interrupts:
maxItems: 1
power-domains:
maxItems: 1
mediatek,dmic-mode:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Indicates how many data pins are used to transmit two channels of PDM
signal. 1 means two wires, 0 means one wire. Default value is 0.
enum:
- 0 # one wire
- 1 # two wires
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- power-domains
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mediatek,mt8365-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/mediatek,mt8365-power.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
audio-controller@11220000 {
compatible = "mediatek,mt8365-afe-pcm";
reg = <0 0x11220000 0 0x1000>;
#sound-dai-cells = <0>;
clocks = <&clk26m>,
<&topckgen CLK_TOP_AUDIO_SEL>,
<&topckgen CLK_TOP_AUD_I2S0_M>,
<&topckgen CLK_TOP_AUD_I2S1_M>,
<&topckgen CLK_TOP_AUD_I2S2_M>,
<&topckgen CLK_TOP_AUD_I2S3_M>,
<&topckgen CLK_TOP_AUD_ENGEN1_SEL>,
<&topckgen CLK_TOP_AUD_ENGEN2_SEL>,
<&topckgen CLK_TOP_AUD_1_SEL>,
<&topckgen CLK_TOP_AUD_2_SEL>,
<&topckgen CLK_TOP_APLL_I2S0_SEL>,
<&topckgen CLK_TOP_APLL_I2S1_SEL>,
<&topckgen CLK_TOP_APLL_I2S2_SEL>,
<&topckgen CLK_TOP_APLL_I2S3_SEL>;
clock-names = "top_clk26m_clk",
"top_audio_sel",
"audio_i2s0_m",
"audio_i2s1_m",
"audio_i2s2_m",
"audio_i2s3_m",
"engen1",
"engen2",
"aud1",
"aud2",
"i2s0_m_sel",
"i2s1_m_sel",
"i2s2_m_sel",
"i2s3_m_sel";
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&spm MT8365_POWER_DOMAIN_AUDIO>;
mediatek,dmic-mode = <1>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8365-mt6357.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8365 ASoC sound card
maintainers:
- Alexandre Mergnat <amergnat@baylibre.com>
properties:
compatible:
const: mediatek,mt8365-mt6357
pinctrl-names:
minItems: 1
items:
- const: default
- const: dmic
- const: miso_off
- const: miso_on
- const: mosi_off
- const: mosi_on
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8365 ASoC platform.
patternProperties:
"^dai-link-[0-9]+$":
type: object
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
codec:
type: object
description: Holds subnode which indicates codec dai.
properties:
sound-dai:
maxItems: 1
description: phandle of the codec DAI
additionalProperties: false
link-name:
description: Indicates dai-link name and PCM stream name
enum:
- I2S_IN_BE
- I2S_OUT_BE
- PCM1_BE
- PDM1_BE
- PDM2_BE
- PDM3_BE
- PDM4_BE
- SPDIF_IN_BE
- SPDIF_OUT_BE
- TDM_IN_BE
- TDM_OUT_BE
sound-dai:
maxItems: 1
description: phandle of the CPU DAI
required:
- link-name
- sound-dai
additionalProperties: false
required:
- compatible
- pinctrl-names
- mediatek,platform
additionalProperties: false
examples:
- |
sound {
compatible = "mediatek,mt8365-mt6357";
pinctrl-names = "default",
"dmic",
"miso_off",
"miso_on",
"mosi_off",
"mosi_on";
pinctrl-0 = <&aud_default_pins>;
pinctrl-1 = <&aud_dmic_pins>;
pinctrl-2 = <&aud_miso_off_pins>;
pinctrl-3 = <&aud_miso_on_pins>;
pinctrl-4 = <&aud_mosi_off_pins>;
pinctrl-5 = <&aud_mosi_on_pins>;
mediatek,platform = <&afe>;
/* hdmi interface */
dai-link-0 {
link-name = "I2S_OUT_BE";
sound-dai = <&afe>;
codec {
sound-dai = <&it66121hdmitx>;
};
};
};
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 AFE clock control
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"
#include "mt8365-reg.h"
#include "../common/mtk-base-afe.h"
#include <linux/device.h>
#include <linux/mfd/syscon.h>
static const char *aud_clks[MT8365_CLK_NUM] = {
[MT8365_CLK_TOP_AUD_SEL] = "top_audio_sel",
[MT8365_CLK_AUD_I2S0_M] = "audio_i2s0_m",
[MT8365_CLK_AUD_I2S1_M] = "audio_i2s1_m",
[MT8365_CLK_AUD_I2S2_M] = "audio_i2s2_m",
[MT8365_CLK_AUD_I2S3_M] = "audio_i2s3_m",
[MT8365_CLK_ENGEN1] = "engen1",
[MT8365_CLK_ENGEN2] = "engen2",
[MT8365_CLK_AUD1] = "aud1",
[MT8365_CLK_AUD2] = "aud2",
[MT8365_CLK_I2S0_M_SEL] = "i2s0_m_sel",
[MT8365_CLK_I2S1_M_SEL] = "i2s1_m_sel",
[MT8365_CLK_I2S2_M_SEL] = "i2s2_m_sel",
[MT8365_CLK_I2S3_M_SEL] = "i2s3_m_sel",
[MT8365_CLK_CLK26M] = "top_clk26m_clk",
};
int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe)
{
size_t i;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
if (IS_ERR(afe_priv->clocks[i])) {
dev_err(afe->dev, "%s devm_clk_get %s fail\n",
__func__, aud_clks[i]);
return PTR_ERR(afe_priv->clocks[i]);
}
}
return 0;
}
void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
{
if (clk)
clk_disable_unprepare(clk);
}
int mt8365_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 rate\n");
return ret;
}
}
return 0;
}
int mt8365_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_err(afe->dev, "Failed to set parent\n");
return ret;
}
}
return 0;
}
static unsigned int get_top_cg_reg(unsigned int cg_type)
{
switch (cg_type) {
case MT8365_TOP_CG_AFE:
case MT8365_TOP_CG_I2S_IN:
case MT8365_TOP_CG_22M:
case MT8365_TOP_CG_24M:
case MT8365_TOP_CG_INTDIR_CK:
case MT8365_TOP_CG_APLL2_TUNER:
case MT8365_TOP_CG_APLL_TUNER:
case MT8365_TOP_CG_SPDIF:
case MT8365_TOP_CG_TDM_OUT:
case MT8365_TOP_CG_TDM_IN:
case MT8365_TOP_CG_ADC:
case MT8365_TOP_CG_DAC:
case MT8365_TOP_CG_DAC_PREDIS:
case MT8365_TOP_CG_TML:
return AUDIO_TOP_CON0;
case MT8365_TOP_CG_I2S1_BCLK:
case MT8365_TOP_CG_I2S2_BCLK:
case MT8365_TOP_CG_I2S3_BCLK:
case MT8365_TOP_CG_I2S4_BCLK:
case MT8365_TOP_CG_DMIC0_ADC:
case MT8365_TOP_CG_DMIC1_ADC:
case MT8365_TOP_CG_DMIC2_ADC:
case MT8365_TOP_CG_DMIC3_ADC:
case MT8365_TOP_CG_CONNSYS_I2S_ASRC:
case MT8365_TOP_CG_GENERAL1_ASRC:
case MT8365_TOP_CG_GENERAL2_ASRC:
case MT8365_TOP_CG_TDM_ASRC:
return AUDIO_TOP_CON1;
default:
return 0;
}
}
static unsigned int get_top_cg_mask(unsigned int cg_type)
{
switch (cg_type) {
case MT8365_TOP_CG_AFE:
return AUD_TCON0_PDN_AFE;
case MT8365_TOP_CG_I2S_IN:
return AUD_TCON0_PDN_I2S_IN;
case MT8365_TOP_CG_22M:
return AUD_TCON0_PDN_22M;
case MT8365_TOP_CG_24M:
return AUD_TCON0_PDN_24M;
case MT8365_TOP_CG_INTDIR_CK:
return AUD_TCON0_PDN_INTDIR;
case MT8365_TOP_CG_APLL2_TUNER:
return AUD_TCON0_PDN_APLL2_TUNER;
case MT8365_TOP_CG_APLL_TUNER:
return AUD_TCON0_PDN_APLL_TUNER;
case MT8365_TOP_CG_SPDIF:
return AUD_TCON0_PDN_SPDIF;
case MT8365_TOP_CG_TDM_OUT:
return AUD_TCON0_PDN_TDM_OUT;
case MT8365_TOP_CG_TDM_IN:
return AUD_TCON0_PDN_TDM_IN;
case MT8365_TOP_CG_ADC:
return AUD_TCON0_PDN_ADC;
case MT8365_TOP_CG_DAC:
return AUD_TCON0_PDN_DAC;
case MT8365_TOP_CG_DAC_PREDIS:
return AUD_TCON0_PDN_DAC_PREDIS;
case MT8365_TOP_CG_TML:
return AUD_TCON0_PDN_TML;
case MT8365_TOP_CG_I2S1_BCLK:
return AUD_TCON1_PDN_I2S1_BCLK;
case MT8365_TOP_CG_I2S2_BCLK:
return AUD_TCON1_PDN_I2S2_BCLK;
case MT8365_TOP_CG_I2S3_BCLK:
return AUD_TCON1_PDN_I2S3_BCLK;
case MT8365_TOP_CG_I2S4_BCLK:
return AUD_TCON1_PDN_I2S4_BCLK;
case MT8365_TOP_CG_DMIC0_ADC:
return AUD_TCON1_PDN_DMIC0_ADC;
case MT8365_TOP_CG_DMIC1_ADC:
return AUD_TCON1_PDN_DMIC1_ADC;
case MT8365_TOP_CG_DMIC2_ADC:
return AUD_TCON1_PDN_DMIC2_ADC;
case MT8365_TOP_CG_DMIC3_ADC:
return AUD_TCON1_PDN_DMIC3_ADC;
case MT8365_TOP_CG_CONNSYS_I2S_ASRC:
return AUD_TCON1_PDN_CONNSYS_I2S_ASRC;
case MT8365_TOP_CG_GENERAL1_ASRC:
return AUD_TCON1_PDN_GENERAL1_ASRC;
case MT8365_TOP_CG_GENERAL2_ASRC:
return AUD_TCON1_PDN_GENERAL2_ASRC;
case MT8365_TOP_CG_TDM_ASRC:
return AUD_TCON1_PDN_TDM_ASRC;
default:
return 0;
}
}
static unsigned int get_top_cg_on_val(unsigned int cg_type)
{
return 0;
}
static unsigned int get_top_cg_off_val(unsigned int cg_type)
{
return get_top_cg_mask(cg_type);
}
int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
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);
unsigned long flags;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->top_cg_ref_cnt[cg_type]++;
if (afe_priv->top_cg_ref_cnt[cg_type] == 1)
regmap_update_bits(afe->regmap, reg, mask, val);
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
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);
unsigned long flags;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->top_cg_ref_cnt[cg_type]--;
if (afe_priv->top_cg_ref_cnt[cg_type] == 0)
regmap_update_bits(afe->regmap, reg, mask, val);
else if (afe_priv->top_cg_ref_cnt[cg_type] < 0)
afe_priv->top_cg_ref_cnt[cg_type] = 0;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
clk_prepare_enable(afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE);
mt8365_afe_enable_afe_on(afe);
return 0;
}
int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
mt8365_afe_disable_afe_on(afe);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE);
mt8365_afe_disable_clk(afe, afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]);
return 0;
}
int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe)
{
return 0;
}
int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe)
{
return 0;
}
int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
unsigned long flags;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->afe_on_ref_cnt++;
if (afe_priv->afe_on_ref_cnt == 1)
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
unsigned long flags;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->afe_on_ref_cnt--;
if (afe_priv->afe_on_ref_cnt == 0)
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
else if (afe_priv->afe_on_ref_cnt < 0)
afe_priv->afe_on_ref_cnt = 0;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
int mt8365_afe_hd_engen_enable(struct mtk_base_afe *afe, bool apll1)
{
if (apll1)
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_22M_PLL_EN, AFE_22M_PLL_EN);
else
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_24M_PLL_EN, AFE_24M_PLL_EN);
return 0;
}
int mt8365_afe_hd_engen_disable(struct mtk_base_afe *afe, bool apll1)
{
if (apll1)
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_22M_PLL_EN, ~AFE_22M_PLL_EN);
else
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_24M_PLL_EN, ~AFE_24M_PLL_EN);
return 0;
}
int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
mutex_lock(&afe_priv->afe_clk_mutex);
afe_priv->apll_tuner_ref_cnt[apll]++;
if (afe_priv->apll_tuner_ref_cnt[apll] != 1) {
mutex_unlock(&afe_priv->afe_clk_mutex);
return 0;
}
if (apll == MT8365_AFE_APLL1) {
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
AFE_APLL_TUNER_CFG_MASK, 0x432);
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
AFE_APLL_TUNER_CFG_EN_MASK, 0x1);
} else {
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
AFE_APLL_TUNER_CFG1_MASK, 0x434);
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
AFE_APLL_TUNER_CFG1_EN_MASK, 0x1);
}
mutex_unlock(&afe_priv->afe_clk_mutex);
return 0;
}
int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
mutex_lock(&afe_priv->afe_clk_mutex);
afe_priv->apll_tuner_ref_cnt[apll]--;
if (afe_priv->apll_tuner_ref_cnt[apll] == 0) {
if (apll == MT8365_AFE_APLL1)
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
AFE_APLL_TUNER_CFG_EN_MASK, 0x0);
else
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
AFE_APLL_TUNER_CFG1_EN_MASK, 0x0);
} else if (afe_priv->apll_tuner_ref_cnt[apll] < 0) {
afe_priv->apll_tuner_ref_cnt[apll] = 0;
}
mutex_unlock(&afe_priv->afe_clk_mutex);
return 0;
}
int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
if (apll == MT8365_AFE_APLL1) {
if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN1])) {
dev_info(afe->dev, "%s Failed to enable ENGEN1 clk\n",
__func__);
return 0;
}
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_22M);
mt8365_afe_hd_engen_enable(afe, true);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER);
mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL1);
} else {
if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN2])) {
dev_info(afe->dev, "%s Failed to enable ENGEN2 clk\n",
__func__);
return 0;
}
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_24M);
mt8365_afe_hd_engen_enable(afe, false);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER);
mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL2);
}
return 0;
}
int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
if (apll == MT8365_AFE_APLL1) {
mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL1);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER);
mt8365_afe_hd_engen_disable(afe, true);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_22M);
clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN1]);
} else {
mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL2);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER);
mt8365_afe_hd_engen_disable(afe, false);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_24M);
clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN2]);
}
return 0;
}
/* SPDX-License-Identifier: GPL-2.0
*
* MediaTek 8365 AFE clock control definitions
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#ifndef _MT8365_AFE_UTILS_H_
#define _MT8365_AFE_UTILS_H_
struct mtk_base_afe;
struct clk;
int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe);
void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, unsigned int rate);
int mt8365_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, struct clk *parent);
int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type);
int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type);
int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe);
int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe);
int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe);
int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe);
int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe);
int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe);
int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll);
int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll);
int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll);
int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll);
#endif
/* SPDX-License-Identifier: GPL-2.0
*
* MediaTek 8365 audio driver common definitions
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#ifndef _MT8365_AFE_COMMON_H_
#define _MT8365_AFE_COMMON_H_
#include <linux/clk.h>
#include <linux/list.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/asound.h>
#include "../common/mtk-base-afe.h"
#include "mt8365-reg.h"
enum {
MT8365_AFE_MEMIF_DL1,
MT8365_AFE_MEMIF_DL2,
MT8365_AFE_MEMIF_TDM_OUT,
/*
* MT8365_AFE_MEMIF_SPDIF_OUT,
*/
MT8365_AFE_MEMIF_AWB,
MT8365_AFE_MEMIF_VUL,
MT8365_AFE_MEMIF_VUL2,
MT8365_AFE_MEMIF_VUL3,
MT8365_AFE_MEMIF_TDM_IN,
/*
* MT8365_AFE_MEMIF_SPDIF_IN,
*/
MT8365_AFE_MEMIF_NUM,
MT8365_AFE_BACKEND_BASE = MT8365_AFE_MEMIF_NUM,
MT8365_AFE_IO_TDM_OUT = MT8365_AFE_BACKEND_BASE,
MT8365_AFE_IO_TDM_IN,
MT8365_AFE_IO_I2S,
MT8365_AFE_IO_2ND_I2S,
MT8365_AFE_IO_PCM1,
MT8365_AFE_IO_VIRTUAL_DL_SRC,
MT8365_AFE_IO_VIRTUAL_TDM_OUT_SRC,
MT8365_AFE_IO_VIRTUAL_FM,
MT8365_AFE_IO_DMIC,
MT8365_AFE_IO_INT_ADDA,
MT8365_AFE_IO_GASRC1,
MT8365_AFE_IO_GASRC2,
MT8365_AFE_IO_TDM_ASRC,
MT8365_AFE_IO_HW_GAIN1,
MT8365_AFE_IO_HW_GAIN2,
MT8365_AFE_BACKEND_END,
MT8365_AFE_BACKEND_NUM = (MT8365_AFE_BACKEND_END -
MT8365_AFE_BACKEND_BASE),
};
enum {
MT8365_AFE_IRQ1,
MT8365_AFE_IRQ2,
MT8365_AFE_IRQ3,
MT8365_AFE_IRQ4,
MT8365_AFE_IRQ5,
MT8365_AFE_IRQ6,
MT8365_AFE_IRQ7,
MT8365_AFE_IRQ8,
MT8365_AFE_IRQ9,
MT8365_AFE_IRQ10,
MT8365_AFE_IRQ_NUM,
};
enum {
MT8365_TOP_CG_AFE,
MT8365_TOP_CG_I2S_IN,
MT8365_TOP_CG_22M,
MT8365_TOP_CG_24M,
MT8365_TOP_CG_INTDIR_CK,
MT8365_TOP_CG_APLL2_TUNER,
MT8365_TOP_CG_APLL_TUNER,
MT8365_TOP_CG_SPDIF,
MT8365_TOP_CG_TDM_OUT,
MT8365_TOP_CG_TDM_IN,
MT8365_TOP_CG_ADC,
MT8365_TOP_CG_DAC,
MT8365_TOP_CG_DAC_PREDIS,
MT8365_TOP_CG_TML,
MT8365_TOP_CG_I2S1_BCLK,
MT8365_TOP_CG_I2S2_BCLK,
MT8365_TOP_CG_I2S3_BCLK,
MT8365_TOP_CG_I2S4_BCLK,
MT8365_TOP_CG_DMIC0_ADC,
MT8365_TOP_CG_DMIC1_ADC,
MT8365_TOP_CG_DMIC2_ADC,
MT8365_TOP_CG_DMIC3_ADC,
MT8365_TOP_CG_CONNSYS_I2S_ASRC,
MT8365_TOP_CG_GENERAL1_ASRC,
MT8365_TOP_CG_GENERAL2_ASRC,
MT8365_TOP_CG_TDM_ASRC,
MT8365_TOP_CG_NUM
};
enum {
MT8365_CLK_TOP_AUD_SEL,
MT8365_CLK_AUD_I2S0_M,
MT8365_CLK_AUD_I2S1_M,
MT8365_CLK_AUD_I2S2_M,
MT8365_CLK_AUD_I2S3_M,
MT8365_CLK_ENGEN1,
MT8365_CLK_ENGEN2,
MT8365_CLK_AUD1,
MT8365_CLK_AUD2,
MT8365_CLK_I2S0_M_SEL,
MT8365_CLK_I2S1_M_SEL,
MT8365_CLK_I2S2_M_SEL,
MT8365_CLK_I2S3_M_SEL,
MT8365_CLK_CLK26M,
MT8365_CLK_NUM
};
enum {
MT8365_AFE_APLL1 = 0,
MT8365_AFE_APLL2,
MT8365_AFE_APLL_NUM,
};
enum {
MT8365_AFE_1ST_I2S = 0,
MT8365_AFE_2ND_I2S,
MT8365_AFE_I2S_SETS,
};
enum {
MT8365_AFE_I2S_SEPARATE_CLOCK = 0,
MT8365_AFE_I2S_SHARED_CLOCK,
};
enum {
MT8365_AFE_TDM_OUT_I2S = 0,
MT8365_AFE_TDM_OUT_TDM,
MT8365_AFE_TDM_OUT_I2S_32BITS,
};
enum mt8365_afe_tdm_ch_start {
AFE_TDM_CH_START_O28_O29 = 0,
AFE_TDM_CH_START_O30_O31,
AFE_TDM_CH_START_O32_O33,
AFE_TDM_CH_START_O34_O35,
AFE_TDM_CH_ZERO,
};
enum {
MT8365_PCM_FORMAT_I2S = 0,
MT8365_PCM_FORMAT_EIAJ,
MT8365_PCM_FORMAT_PCMA,
MT8365_PCM_FORMAT_PCMB,
};
enum {
MT8365_FS_8K = 0,
MT8365_FS_11D025K,
MT8365_FS_12K,
MT8365_FS_384K,
MT8365_FS_16K,
MT8365_FS_22D05K,
MT8365_FS_24K,
MT8365_FS_130K,
MT8365_FS_32K,
MT8365_FS_44D1K,
MT8365_FS_48K,
MT8365_FS_88D2K,
MT8365_FS_96K,
MT8365_FS_176D4K,
MT8365_FS_192K,
};
enum {
FS_8000HZ = 0, /* 0000b */
FS_11025HZ = 1, /* 0001b */
FS_12000HZ = 2, /* 0010b */
FS_384000HZ = 3, /* 0011b */
FS_16000HZ = 4, /* 0100b */
FS_22050HZ = 5, /* 0101b */
FS_24000HZ = 6, /* 0110b */
FS_130000HZ = 7, /* 0111b */
FS_32000HZ = 8, /* 1000b */
FS_44100HZ = 9, /* 1001b */
FS_48000HZ = 10, /* 1010b */
FS_88200HZ = 11, /* 1011b */
FS_96000HZ = 12, /* 1100b */
FS_176400HZ = 13, /* 1101b */
FS_192000HZ = 14, /* 1110b */
FS_260000HZ = 15, /* 1111b */
};
enum {
MT8365_AFE_DEBUGFS_AFE,
MT8365_AFE_DEBUGFS_MEMIF,
MT8365_AFE_DEBUGFS_IRQ,
MT8365_AFE_DEBUGFS_CONN,
MT8365_AFE_DEBUGFS_DBG,
MT8365_AFE_DEBUGFS_NUM,
};
enum {
MT8365_AFE_IRQ_DIR_MCU = 0,
MT8365_AFE_IRQ_DIR_DSP,
MT8365_AFE_IRQ_DIR_BOTH,
};
/* MCLK */
enum {
MT8365_I2S0_MCK = 0,
MT8365_I2S3_MCK,
MT8365_MCK_NUM,
};
struct mt8365_fe_dai_data {
bool use_sram;
unsigned int sram_phy_addr;
void __iomem *sram_vir_addr;
unsigned int sram_size;
};
struct mt8365_be_dai_data {
bool prepared[SNDRV_PCM_STREAM_LAST + 1];
unsigned int fmt_mode;
};
#define MT8365_CLK_26M 26000000
#define MT8365_CLK_24M 24000000
#define MT8365_CLK_22M 22000000
#define MT8365_CM_UPDATA_CNT_SET 8
enum mt8365_cm_num {
MT8365_CM1 = 0,
MT8365_CM2,
MT8365_CM_NUM,
};
enum mt8365_cm2_mux_in {
MT8365_FROM_GASRC1 = 1,
MT8365_FROM_GASRC2,
MT8365_FROM_TDM_ASRC,
MT8365_CM_MUX_NUM,
};
enum cm2_mux_conn_in {
GENERAL2_ASRC_OUT_LCH = 0,
GENERAL2_ASRC_OUT_RCH = 1,
TDM_IN_CH0 = 2,
TDM_IN_CH1 = 3,
TDM_IN_CH2 = 4,
TDM_IN_CH3 = 5,
TDM_IN_CH4 = 6,
TDM_IN_CH5 = 7,
TDM_IN_CH6 = 8,
TDM_IN_CH7 = 9,
GENERAL1_ASRC_OUT_LCH = 10,
GENERAL1_ASRC_OUT_RCH = 11,
TDM_OUT_ASRC_CH0 = 12,
TDM_OUT_ASRC_CH1 = 13,
TDM_OUT_ASRC_CH2 = 14,
TDM_OUT_ASRC_CH3 = 15,
TDM_OUT_ASRC_CH4 = 16,
TDM_OUT_ASRC_CH5 = 17,
TDM_OUT_ASRC_CH6 = 18,
TDM_OUT_ASRC_CH7 = 19
};
struct mt8365_cm_ctrl_reg {
unsigned int con0;
unsigned int con1;
unsigned int con2;
unsigned int con3;
unsigned int con4;
};
struct mt8365_control_data {
bool bypass_cm1;
bool bypass_cm2;
unsigned int loopback_type;
};
enum dmic_input_mode {
DMIC_MODE_3P25M = 0,
DMIC_MODE_1P625M,
DMIC_MODE_812P5K,
DMIC_MODE_406P25K,
};
enum iir_mode {
IIR_MODE0 = 0,
IIR_MODE1,
IIR_MODE2,
IIR_MODE3,
IIR_MODE4,
IIR_MODE5,
};
enum {
MT8365_GASRC1 = 0,
MT8365_GASRC2,
MT8365_GASRC_NUM,
MT8365_TDM_ASRC1 = MT8365_GASRC_NUM,
MT8365_TDM_ASRC2,
MT8365_TDM_ASRC3,
MT8365_TDM_ASRC4,
MT8365_TDM_ASRC_NUM,
};
struct mt8365_gasrc_ctrl_reg {
unsigned int con0;
unsigned int con2;
unsigned int con3;
unsigned int con4;
unsigned int con5;
unsigned int con6;
unsigned int con9;
unsigned int con10;
unsigned int con12;
unsigned int con13;
};
struct mt8365_gasrc_data {
bool duplex;
bool tx_mode;
bool cali_on;
bool tdm_asrc_out_cm2;
bool iir_on;
};
struct mt8365_afe_private {
struct clk *clocks[MT8365_CLK_NUM];
struct regmap *topckgen;
struct mt8365_fe_dai_data fe_data[MT8365_AFE_MEMIF_NUM];
struct mt8365_be_dai_data be_data[MT8365_AFE_BACKEND_NUM];
struct mt8365_control_data ctrl_data;
struct mt8365_gasrc_data gasrc_data[MT8365_TDM_ASRC_NUM];
int afe_on_ref_cnt;
int top_cg_ref_cnt[MT8365_TOP_CG_NUM];
void __iomem *afe_sram_vir_addr;
unsigned int afe_sram_phy_addr;
unsigned int afe_sram_size;
/* locks */
spinlock_t afe_ctrl_lock;
struct mutex afe_clk_mutex; /* Protect & sync APLL TUNER registers access*/
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_dentry[MT8365_AFE_DEBUGFS_NUM];
#endif
int apll_tuner_ref_cnt[MT8365_AFE_APLL_NUM];
unsigned int tdm_out_mode;
unsigned int cm2_mux_input;
/* dai */
bool dai_on[MT8365_AFE_BACKEND_END];
void *dai_priv[MT8365_AFE_BACKEND_END];
};
static inline u32 rx_frequency_palette(unsigned int fs)
{
/* *
* A = (26M / fs) * 64
* B = 8125 / A
* return = DEC2HEX(B * 2^23)
*/
switch (fs) {
case FS_8000HZ: return 0x050000;
case FS_11025HZ: return 0x06E400;
case FS_12000HZ: return 0x078000;
case FS_16000HZ: return 0x0A0000;
case FS_22050HZ: return 0x0DC800;
case FS_24000HZ: return 0x0F0000;
case FS_32000HZ: return 0x140000;
case FS_44100HZ: return 0x1B9000;
case FS_48000HZ: return 0x1E0000;
case FS_88200HZ: return 0x372000;
case FS_96000HZ: return 0x3C0000;
case FS_176400HZ: return 0x6E4000;
case FS_192000HZ: return 0x780000;
default: return 0x0;
}
}
static inline u32 AutoRstThHi(unsigned int fs)
{
switch (fs) {
case FS_8000HZ: return 0x36000;
case FS_11025HZ: return 0x27000;
case FS_12000HZ: return 0x24000;
case FS_16000HZ: return 0x1B000;
case FS_22050HZ: return 0x14000;
case FS_24000HZ: return 0x12000;
case FS_32000HZ: return 0x0D800;
case FS_44100HZ: return 0x09D00;
case FS_48000HZ: return 0x08E00;
case FS_88200HZ: return 0x04E00;
case FS_96000HZ: return 0x04800;
case FS_176400HZ: return 0x02700;
case FS_192000HZ: return 0x02400;
default: return 0x0;
}
}
static inline u32 AutoRstThLo(unsigned int fs)
{
switch (fs) {
case FS_8000HZ: return 0x30000;
case FS_11025HZ: return 0x23000;
case FS_12000HZ: return 0x20000;
case FS_16000HZ: return 0x18000;
case FS_22050HZ: return 0x11000;
case FS_24000HZ: return 0x0FE00;
case FS_32000HZ: return 0x0BE00;
case FS_44100HZ: return 0x08A00;
case FS_48000HZ: return 0x07F00;
case FS_88200HZ: return 0x04500;
case FS_96000HZ: return 0x04000;
case FS_176400HZ: return 0x02300;
case FS_192000HZ: return 0x02000;
default: return 0x0;
}
}
bool mt8365_afe_clk_group_48k(int sample_rate);
bool mt8365_afe_rate_supported(unsigned int rate, unsigned int id);
bool mt8365_afe_channel_supported(unsigned int channel, unsigned int id);
int mt8365_dai_i2s_register(struct mtk_base_afe *afe);
int mt8365_dai_set_priv(struct mtk_base_afe *afe,
int id,
int priv_size,
const void *priv_data);
int mt8365_afe_fs_timing(unsigned int rate);
void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable);
int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe, unsigned int rate, int bit_width);
int mt8365_dai_adda_register(struct mtk_base_afe *afe);
int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe);
int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe);
int mt8365_dai_dmic_register(struct mtk_base_afe *afe);
int mt8365_dai_pcm_register(struct mtk_base_afe *afe);
int mt8365_dai_tdm_register(struct mtk_base_afe *afe);
#endif
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 ALSA SoC AFE platform driver
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-common.h"
#include "mt8365-afe-clk.h"
#include "mt8365-reg.h"
#include "../common/mtk-base-afe.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-afe-fe-dai.h"
#define AFE_BASE_END_OFFSET 8
static unsigned int mCM2Input;
static const unsigned int mt8365_afe_backup_list[] = {
AUDIO_TOP_CON0,
AFE_CONN0,
AFE_CONN1,
AFE_CONN3,
AFE_CONN4,
AFE_CONN5,
AFE_CONN6,
AFE_CONN7,
AFE_CONN8,
AFE_CONN9,
AFE_CONN10,
AFE_CONN11,
AFE_CONN12,
AFE_CONN13,
AFE_CONN14,
AFE_CONN15,
AFE_CONN16,
AFE_CONN17,
AFE_CONN18,
AFE_CONN19,
AFE_CONN20,
AFE_CONN21,
AFE_CONN26,
AFE_CONN27,
AFE_CONN28,
AFE_CONN29,
AFE_CONN30,
AFE_CONN31,
AFE_CONN32,
AFE_CONN33,
AFE_CONN34,
AFE_CONN35,
AFE_CONN36,
AFE_CONN_24BIT,
AFE_CONN_24BIT_1,
AFE_DAC_CON0,
AFE_DAC_CON1,
AFE_DL1_BASE,
AFE_DL1_END,
AFE_DL2_BASE,
AFE_DL2_END,
AFE_VUL_BASE,
AFE_VUL_END,
AFE_AWB_BASE,
AFE_AWB_END,
AFE_VUL3_BASE,
AFE_VUL3_END,
AFE_HDMI_OUT_BASE,
AFE_HDMI_OUT_END,
AFE_HDMI_IN_2CH_BASE,
AFE_HDMI_IN_2CH_END,
AFE_ADDA_UL_DL_CON0,
AFE_ADDA_DL_SRC2_CON0,
AFE_ADDA_DL_SRC2_CON1,
AFE_I2S_CON,
AFE_I2S_CON1,
AFE_I2S_CON2,
AFE_I2S_CON3,
AFE_ADDA_UL_SRC_CON0,
AFE_AUD_PAD_TOP,
AFE_HD_ENGEN_ENABLE,
};
static const struct snd_pcm_hardware mt8365_afe_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.buffer_bytes_max = 256 * 1024,
.period_bytes_min = 512,
.period_bytes_max = 128 * 1024,
.periods_min = 2,
.periods_max = 256,
.fifo_size = 0,
};
struct mt8365_afe_rate {
unsigned int rate;
unsigned int reg_val;
};
static const struct mt8365_afe_rate mt8365_afe_fs_rates[] = {
{ .rate = 8000, .reg_val = MT8365_FS_8K },
{ .rate = 11025, .reg_val = MT8365_FS_11D025K },
{ .rate = 12000, .reg_val = MT8365_FS_12K },
{ .rate = 16000, .reg_val = MT8365_FS_16K },
{ .rate = 22050, .reg_val = MT8365_FS_22D05K },
{ .rate = 24000, .reg_val = MT8365_FS_24K },
{ .rate = 32000, .reg_val = MT8365_FS_32K },
{ .rate = 44100, .reg_val = MT8365_FS_44D1K },
{ .rate = 48000, .reg_val = MT8365_FS_48K },
{ .rate = 88200, .reg_val = MT8365_FS_88D2K },
{ .rate = 96000, .reg_val = MT8365_FS_96K },
{ .rate = 176400, .reg_val = MT8365_FS_176D4K },
{ .rate = 192000, .reg_val = MT8365_FS_192K },
};
int mt8365_afe_fs_timing(unsigned int rate)
{
int i;
for (i = 0; i < ARRAY_SIZE(mt8365_afe_fs_rates); i++)
if (mt8365_afe_fs_rates[i].rate == rate)
return mt8365_afe_fs_rates[i].reg_val;
return -EINVAL;
}
bool mt8365_afe_rate_supported(unsigned int rate, unsigned int id)
{
switch (id) {
case MT8365_AFE_IO_TDM_IN:
if (rate >= 8000 && rate <= 192000)
return true;
break;
case MT8365_AFE_IO_DMIC:
if (rate >= 8000 && rate <= 48000)
return true;
break;
default:
break;
}
return false;
}
bool mt8365_afe_channel_supported(unsigned int channel, unsigned int id)
{
switch (id) {
case MT8365_AFE_IO_TDM_IN:
if (channel >= 1 && channel <= 8)
return true;
break;
case MT8365_AFE_IO_DMIC:
if (channel >= 1 && channel <= 8)
return true;
break;
default:
break;
}
return false;
}
bool mt8365_afe_clk_group_44k(int sample_rate)
{
if (sample_rate == 11025 ||
sample_rate == 22050 ||
sample_rate == 44100 ||
sample_rate == 88200 ||
sample_rate == 176400)
return true;
else
return false;
}
bool mt8365_afe_clk_group_48k(int sample_rate)
{
return (!mt8365_afe_clk_group_44k(sample_rate));
}
int mt8365_dai_set_priv(struct mtk_base_afe *afe, int id,
int priv_size, const void *priv_data)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
void *temp_data;
temp_data = devm_kzalloc(afe->dev, priv_size, GFP_KERNEL);
if (!temp_data)
return -ENOMEM;
if (priv_data)
memcpy(temp_data, priv_data, priv_size);
afe_priv->dai_priv[id] = temp_data;
return 0;
}
static int mt8365_afe_irq_direction_enable(struct mtk_base_afe *afe,
int irq_id, int direction)
{
struct mtk_base_afe_irq *irq;
if (irq_id >= MT8365_AFE_IRQ_NUM)
return -1;
irq = &afe->irqs[irq_id];
if (direction == MT8365_AFE_IRQ_DIR_MCU) {
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
(1 << irq->irq_data->irq_clr_shift),
0);
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
(1 << irq->irq_data->irq_clr_shift),
(1 << irq->irq_data->irq_clr_shift));
} else if (direction == MT8365_AFE_IRQ_DIR_DSP) {
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
(1 << irq->irq_data->irq_clr_shift),
(1 << irq->irq_data->irq_clr_shift));
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
(1 << irq->irq_data->irq_clr_shift),
0);
} else {
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
(1 << irq->irq_data->irq_clr_shift),
(1 << irq->irq_data->irq_clr_shift));
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
(1 << irq->irq_data->irq_clr_shift),
(1 << irq->irq_data->irq_clr_shift));
}
return 0;
}
static int mt8365_memif_fs(struct snd_pcm_substream *substream,
unsigned int rate)
{
return mt8365_afe_fs_timing(rate);
}
static int mt8365_irq_fs(struct snd_pcm_substream *substream,
unsigned int rate)
{
return mt8365_memif_fs(substream, rate);
}
static const struct mt8365_cm_ctrl_reg cm_ctrl_reg[MT8365_CM_NUM] = {
[MT8365_CM1] = {
.con0 = AFE_CM1_CON0,
.con1 = AFE_CM1_CON1,
.con2 = AFE_CM1_CON2,
.con3 = AFE_CM1_CON3,
.con4 = AFE_CM1_CON4,
},
[MT8365_CM2] = {
.con0 = AFE_CM2_CON0,
.con1 = AFE_CM2_CON1,
.con2 = AFE_CM2_CON2,
.con3 = AFE_CM2_CON3,
.con4 = AFE_CM2_CON4,
}
};
static int mt8365_afe_cm2_mux_conn(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
unsigned int input = afe_priv->cm2_mux_input;
/* TDM_IN interconnect to CM2 */
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG1_MASK,
CM2_AFE_CM2_CONN_CFG1(TDM_IN_CH0));
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG2_MASK,
CM2_AFE_CM2_CONN_CFG2(TDM_IN_CH1));
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG3_MASK,
CM2_AFE_CM2_CONN_CFG3(TDM_IN_CH2));
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG4_MASK,
CM2_AFE_CM2_CONN_CFG4(TDM_IN_CH3));
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG5_MASK,
CM2_AFE_CM2_CONN_CFG5(TDM_IN_CH4));
regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
CM2_AFE_CM2_CONN_CFG6_MASK,
CM2_AFE_CM2_CONN_CFG6(TDM_IN_CH5));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG7_MASK,
CM2_AFE_CM2_CONN_CFG7(TDM_IN_CH6));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG8_MASK,
CM2_AFE_CM2_CONN_CFG8(TDM_IN_CH7));
/* ref data interconnect to CM2 */
if (input == MT8365_FROM_GASRC1) {
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG9_MASK,
CM2_AFE_CM2_CONN_CFG9(GENERAL1_ASRC_OUT_LCH));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG10_MASK,
CM2_AFE_CM2_CONN_CFG10(GENERAL1_ASRC_OUT_RCH));
} else if (input == MT8365_FROM_GASRC2) {
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG9_MASK,
CM2_AFE_CM2_CONN_CFG9(GENERAL2_ASRC_OUT_LCH));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG10_MASK,
CM2_AFE_CM2_CONN_CFG10(GENERAL2_ASRC_OUT_RCH));
} else if (input == MT8365_FROM_TDM_ASRC) {
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG9_MASK,
CM2_AFE_CM2_CONN_CFG9(TDM_OUT_ASRC_CH0));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG10_MASK,
CM2_AFE_CM2_CONN_CFG10(TDM_OUT_ASRC_CH1));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG11_MASK,
CM2_AFE_CM2_CONN_CFG11(TDM_OUT_ASRC_CH2));
regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
CM2_AFE_CM2_CONN_CFG12_MASK,
CM2_AFE_CM2_CONN_CFG12(TDM_OUT_ASRC_CH3));
regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
CM2_AFE_CM2_CONN_CFG13_MASK,
CM2_AFE_CM2_CONN_CFG13(TDM_OUT_ASRC_CH4));
regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
CM2_AFE_CM2_CONN_CFG14_MASK,
CM2_AFE_CM2_CONN_CFG14(TDM_OUT_ASRC_CH5));
regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
CM2_AFE_CM2_CONN_CFG15_MASK,
CM2_AFE_CM2_CONN_CFG15(TDM_OUT_ASRC_CH6));
regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
CM2_AFE_CM2_CONN_CFG16_MASK,
CM2_AFE_CM2_CONN_CFG16(TDM_OUT_ASRC_CH7));
} else {
dev_err(afe->dev, "%s wrong CM2 input %d\n", __func__, input);
return -1;
}
return 0;
}
static int mt8365_afe_get_cm_update_cnt(struct mtk_base_afe *afe,
enum mt8365_cm_num cmNum,
unsigned int rate, unsigned int channel)
{
unsigned int total_cnt, div_cnt, ch_pair, best_cnt;
unsigned int ch_update_cnt[MT8365_CM_UPDATA_CNT_SET];
int i;
/* calculate cm update cnt
* total_cnt = clk / fs, clk is 26m or 24m or 22m
* div_cnt = total_cnt / ch_pair, max ch 16ch ,2ch is a set
* best_cnt < div_cnt ,we set best_cnt = div_cnt -10
* ch01 = best_cnt, ch23 = 2* ch01_up_cnt
* ch45 = 3* ch01_up_cnt ...ch1415 = 8* ch01_up_cnt
*/
if (cmNum == MT8365_CM1) {
total_cnt = MT8365_CLK_26M / rate;
} else if (cmNum == MT8365_CM2) {
if (mt8365_afe_clk_group_48k(rate))
total_cnt = MT8365_CLK_24M / rate;
else
total_cnt = MT8365_CLK_22M / rate;
} else {
return -1;
}
if (channel % 2)
ch_pair = (channel / 2) + 1;
else
ch_pair = channel / 2;
div_cnt = total_cnt / ch_pair;
best_cnt = div_cnt - 10;
if (best_cnt <= 0)
return -1;
for (i = 0; i < ch_pair; i++)
ch_update_cnt[i] = (i + 1) * best_cnt;
switch (channel) {
case 16:
fallthrough;
case 15:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4,
CM_AFE_CM_UPDATE_CNT2_MASK,
CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[7]));
fallthrough;
case 14:
fallthrough;
case 13:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4,
CM_AFE_CM_UPDATE_CNT1_MASK,
CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[6]));
fallthrough;
case 12:
fallthrough;
case 11:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3,
CM_AFE_CM_UPDATE_CNT2_MASK,
CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[5]));
fallthrough;
case 10:
fallthrough;
case 9:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3,
CM_AFE_CM_UPDATE_CNT1_MASK,
CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[4]));
fallthrough;
case 8:
fallthrough;
case 7:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2,
CM_AFE_CM_UPDATE_CNT2_MASK,
CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[3]));
fallthrough;
case 6:
fallthrough;
case 5:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2,
CM_AFE_CM_UPDATE_CNT1_MASK,
CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[2]));
fallthrough;
case 4:
fallthrough;
case 3:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1,
CM_AFE_CM_UPDATE_CNT2_MASK,
CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[1]));
fallthrough;
case 2:
fallthrough;
case 1:
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1,
CM_AFE_CM_UPDATE_CNT1_MASK,
CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[0]));
break;
default:
return -1;
}
return 0;
}
static int mt8365_afe_configure_cm(struct mtk_base_afe *afe,
enum mt8365_cm_num cmNum,
unsigned int channels,
unsigned int rate)
{
unsigned int val, mask;
unsigned int fs = mt8365_afe_fs_timing(rate);
val = FIELD_PREP(CM_AFE_CM_CH_NUM_MASK, (channels - 1)) |
FIELD_PREP(CM_AFE_CM_START_DATA_MASK, 0);
mask = CM_AFE_CM_CH_NUM_MASK |
CM_AFE_CM_START_DATA_MASK;
if (cmNum == MT8365_CM1) {
val |= FIELD_PREP(CM_AFE_CM1_IN_MODE_MASK, fs);
mask |= CM_AFE_CM1_VUL_SEL |
CM_AFE_CM1_IN_MODE_MASK;
} else if (cmNum == MT8365_CM2) {
if (mt8365_afe_clk_group_48k(rate))
val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 0);
else
val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 1);
val |= FIELD_PREP(CM_AFE_CM2_TDM_SEL, 1);
mask |= CM_AFE_CM2_TDM_SEL |
CM_AFE_CM1_IN_MODE_MASK |
CM_AFE_CM2_CLK_SEL;
mt8365_afe_cm2_mux_conn(afe);
} else {
return -1;
}
regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con0, mask, val);
mt8365_afe_get_cm_update_cnt(afe, cmNum, rate, channels);
return 0;
}
int mt8365_afe_fe_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct snd_pcm_runtime *runtime = substream->runtime;
int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
int ret;
memif->substream = substream;
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
snd_soc_set_runtime_hwparams(substream, afe->mtk_afe_hardware);
ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
mt8365_afe_enable_main_clk(afe);
return ret;
}
static void mt8365_afe_fe_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
memif->substream = NULL;
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_afe_fe_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data;
int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id];
size_t request_size = params_buffer_bytes(params);
unsigned int channels = params_channels(params);
unsigned int rate = params_rate(params);
unsigned int base_end_offset = 8;
int ret, fs;
dev_info(afe->dev, "%s %s period = %d rate = %d channels = %d\n",
__func__, memif->data->name, params_period_size(params),
rate, channels);
if (dai_id == MT8365_AFE_MEMIF_VUL2) {
if (!ctrl_data->bypass_cm1)
/* configure cm1 */
mt8365_afe_configure_cm(afe, MT8365_CM1,
channels, rate);
else
regmap_update_bits(afe->regmap, AFE_CM1_CON0,
CM_AFE_CM1_VUL_SEL,
CM_AFE_CM1_VUL_SEL);
} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN) {
if (!ctrl_data->bypass_cm2)
/* configure cm2 */
mt8365_afe_configure_cm(afe, MT8365_CM2,
channels, rate);
else
regmap_update_bits(afe->regmap, AFE_CM2_CON0,
CM_AFE_CM2_TDM_SEL,
~CM_AFE_CM2_TDM_SEL);
base_end_offset = 4;
}
if (request_size > fe_data->sram_size) {
ret = snd_pcm_lib_malloc_pages(substream, request_size);
if (ret < 0) {
dev_err(afe->dev,
"%s %s malloc pages %zu bytes failed %d\n",
__func__, memif->data->name, request_size, ret);
return ret;
}
fe_data->use_sram = false;
mt8365_afe_emi_clk_on(afe);
} else {
struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
dma_buf->dev.dev = substream->pcm->card->dev;
dma_buf->area = (unsigned char *)fe_data->sram_vir_addr;
dma_buf->addr = fe_data->sram_phy_addr;
dma_buf->bytes = request_size;
snd_pcm_set_runtime_buffer(substream, dma_buf);
fe_data->use_sram = true;
}
memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
memif->buffer_size = substream->runtime->dma_bytes;
/* start */
regmap_write(afe->regmap, memif->data->reg_ofs_base,
memif->phys_buf_addr);
/* end */
regmap_write(afe->regmap,
memif->data->reg_ofs_base + base_end_offset,
memif->phys_buf_addr + memif->buffer_size - 1);
/* set channel */
if (memif->data->mono_shift >= 0) {
unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
if (memif->data->mono_reg < 0)
dev_info(afe->dev, "%s mono_reg is NULL\n", __func__);
else
regmap_update_bits(afe->regmap, memif->data->mono_reg,
1 << memif->data->mono_shift,
mono << memif->data->mono_shift);
}
/* set rate */
if (memif->data->fs_shift < 0)
return 0;
fs = afe->memif_fs(substream, params_rate(params));
if (fs < 0)
return -EINVAL;
if (memif->data->fs_reg < 0)
dev_info(afe->dev, "%s fs_reg is NULL\n", __func__);
else
regmap_update_bits(afe->regmap, memif->data->fs_reg,
memif->data->fs_maskbit << memif->data->fs_shift,
fs << memif->data->fs_shift);
return 0;
}
static int mt8365_afe_fe_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id];
int ret = 0;
if (fe_data->use_sram) {
snd_pcm_set_runtime_buffer(substream, NULL);
} else {
ret = snd_pcm_lib_free_pages(substream);
mt8365_afe_emi_clk_off(afe);
}
return ret;
}
static int mt8365_afe_fe_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
/* set format */
if (memif->data->hd_reg >= 0) {
switch (substream->runtime->format) {
case SNDRV_PCM_FORMAT_S16_LE:
regmap_update_bits(afe->regmap, memif->data->hd_reg,
3 << memif->data->hd_shift,
0 << memif->data->hd_shift);
break;
case SNDRV_PCM_FORMAT_S32_LE:
regmap_update_bits(afe->regmap, memif->data->hd_reg,
3 << memif->data->hd_shift,
3 << memif->data->hd_shift);
if (dai_id == MT8365_AFE_MEMIF_TDM_IN) {
regmap_update_bits(afe->regmap,
memif->data->hd_reg,
3 << memif->data->hd_shift,
1 << memif->data->hd_shift);
regmap_update_bits(afe->regmap,
memif->data->hd_reg,
1 << memif->data->hd_align_mshift,
1 << memif->data->hd_align_mshift);
}
break;
case SNDRV_PCM_FORMAT_S24_LE:
regmap_update_bits(afe->regmap, memif->data->hd_reg,
3 << memif->data->hd_shift,
1 << memif->data->hd_shift);
break;
default:
return -EINVAL;
}
}
mt8365_afe_irq_direction_enable(afe, memif->irq_usage,
MT8365_AFE_IRQ_DIR_MCU);
return 0;
}
int mt8365_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
/* enable channel merge */
if (dai_id == MT8365_AFE_MEMIF_VUL2 &&
!ctrl_data->bypass_cm1) {
regmap_update_bits(afe->regmap, AFE_CM1_CON0,
CM_AFE_CM_ON, CM_AFE_CM_ON);
} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN &&
!ctrl_data->bypass_cm2) {
regmap_update_bits(afe->regmap, AFE_CM2_CON0,
CM_AFE_CM_ON, CM_AFE_CM_ON);
}
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
/* disable channel merge */
if (dai_id == MT8365_AFE_MEMIF_VUL2 &&
!ctrl_data->bypass_cm1) {
regmap_update_bits(afe->regmap, AFE_CM1_CON0,
CM_AFE_CM_ON, ~CM_AFE_CM_ON);
} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN &&
!ctrl_data->bypass_cm2) {
regmap_update_bits(afe->regmap, AFE_CM2_CON0,
CM_AFE_CM_ON, ~CM_AFE_CM_ON);
}
break;
default:
break;
}
return mtk_afe_fe_trigger(substream, cmd, dai);
}
static int mt8365_afe_hw_gain1_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
mt8365_afe_enable_main_clk(afe);
return 0;
}
static void mt8365_afe_hw_gain1_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be =
&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
if (be->prepared[substream->stream]) {
regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
AFE_GAIN1_CON0_EN_MASK, 0);
be->prepared[substream->stream] = false;
}
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_afe_hw_gain1_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be =
&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
int fs;
unsigned int val1 = 0, val2 = 0;
if (be->prepared[substream->stream]) {
dev_info(afe->dev, "%s prepared already\n", __func__);
return 0;
}
fs = mt8365_afe_fs_timing(substream->runtime->rate);
regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
AFE_GAIN1_CON0_MODE_MASK, (unsigned int)fs << 4);
regmap_read(afe->regmap, AFE_GAIN1_CON1, &val1);
regmap_read(afe->regmap, AFE_GAIN1_CUR, &val2);
if ((val1 & AFE_GAIN1_CON1_MASK) != (val2 & AFE_GAIN1_CUR_MASK))
regmap_update_bits(afe->regmap, AFE_GAIN1_CUR,
AFE_GAIN1_CUR_MASK, val1);
regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
AFE_GAIN1_CON0_EN_MASK, 1);
be->prepared[substream->stream] = true;
return 0;
}
static const struct snd_pcm_hardware mt8365_hostless_hardware = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.period_bytes_min = 256,
.period_bytes_max = 4 * 48 * 1024,
.periods_min = 2,
.periods_max = 256,
.buffer_bytes_max = 8 * 48 * 1024,
.fifo_size = 0,
};
/* dai ops */
static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
snd_soc_set_runtime_hwparams(substream, &mt8365_hostless_hardware);
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
return ret;
}
/* FE DAIs */
static const struct snd_soc_dai_ops mt8365_afe_fe_dai_ops = {
.startup = mt8365_afe_fe_startup,
.shutdown = mt8365_afe_fe_shutdown,
.hw_params = mt8365_afe_fe_hw_params,
.hw_free = mt8365_afe_fe_hw_free,
.prepare = mt8365_afe_fe_prepare,
.trigger = mt8365_afe_fe_trigger,
};
static const struct snd_soc_dai_ops mt8365_dai_hostless_ops = {
.startup = mtk_dai_hostless_startup,
};
static const struct snd_soc_dai_ops mt8365_afe_hw_gain1_ops = {
.startup = mt8365_afe_hw_gain1_startup,
.shutdown = mt8365_afe_hw_gain1_shutdown,
.prepare = mt8365_afe_hw_gain1_prepare,
};
static struct snd_soc_dai_driver mt8365_memif_dai_driver[] = {
/* FE DAIs: memory intefaces to CPU */
{
.name = "DL1",
.id = MT8365_AFE_MEMIF_DL1,
.playback = {
.stream_name = "DL1",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "DL2",
.id = MT8365_AFE_MEMIF_DL2,
.playback = {
.stream_name = "DL2",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "TDM_OUT",
.id = MT8365_AFE_MEMIF_TDM_OUT,
.playback = {
.stream_name = "TDM_OUT",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "AWB",
.id = MT8365_AFE_MEMIF_AWB,
.capture = {
.stream_name = "AWB",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "VUL",
.id = MT8365_AFE_MEMIF_VUL,
.capture = {
.stream_name = "VUL",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "VUL2",
.id = MT8365_AFE_MEMIF_VUL2,
.capture = {
.stream_name = "VUL2",
.channels_min = 1,
.channels_max = 16,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "VUL3",
.id = MT8365_AFE_MEMIF_VUL3,
.capture = {
.stream_name = "VUL3",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "TDM_IN",
.id = MT8365_AFE_MEMIF_TDM_IN,
.capture = {
.stream_name = "TDM_IN",
.channels_min = 1,
.channels_max = 16,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_fe_dai_ops,
}, {
.name = "Hostless FM DAI",
.id = MT8365_AFE_IO_VIRTUAL_FM,
.playback = {
.stream_name = "Hostless FM DL",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "Hostless FM UL",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_dai_hostless_ops,
}, {
.name = "HW_GAIN1",
.id = MT8365_AFE_IO_HW_GAIN1,
.playback = {
.stream_name = "HW Gain 1 In",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "HW Gain 1 Out",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_hw_gain1_ops,
.symmetric_rate = 1,
.symmetric_channels = 1,
.symmetric_sample_bits = 1,
},
};
static const struct snd_kcontrol_new mt8365_afe_o00_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN0, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN0, 7, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o01_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN1, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN1, 8, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o03_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN3, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN3, 7, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN3, 0, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I10 Switch", AFE_CONN3, 10, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o04_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN4, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN4, 8, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN4, 1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I11 Switch", AFE_CONN4, 11, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o05_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN5, 0, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN5, 3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN5, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN5, 7, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN5, 9, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN5, 14, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN5, 16, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN5, 18, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN5, 20, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN5, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I10L Switch", AFE_CONN5, 10, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o06_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN6, 1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN6, 4, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN6, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN6, 8, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN6, 22, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN6, 15, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN6, 17, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN6, 19, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN6, 21, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN6, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I11L Switch", AFE_CONN6, 11, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o07_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN7, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN7, 7, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o08_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN8, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN8, 8, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o09_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN9, 0, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN9, 3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN9, 9, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN9, 14, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN9, 16, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN9, 18, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN9, 20, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o10_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN10, 1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN10, 4, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN10, 22, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN10, 15, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN10, 17, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN10, 19, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN10, 21, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o11_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN11, 0, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN11, 3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN11, 9, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN11, 14, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN11, 16, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN11, 18, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN11, 20, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o12_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN12, 1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN12, 4, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN12, 22, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN12, 15, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN12, 17, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN12, 19, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN12, 21, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o13_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN13, 0, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o14_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN14, 1, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o15_mix[] = {
};
static const struct snd_kcontrol_new mt8365_afe_o16_mix[] = {
};
static const struct snd_kcontrol_new mt8365_afe_o17_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN17, 3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o18_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN18, 4, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN18, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN18, 25, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o19_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN19, 4, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN19, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN19, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN19, 25, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN19, 26, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o20_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN20, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN20, 26, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o21_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN21, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN21, 25, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o22_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN22, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN22, 26, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o23_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN23, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN23, 25, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o24_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN24, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN24, 26, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN24, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN24, 25, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o25_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I27 Switch", AFE_CONN25, 27, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN25, 23, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN25, 25, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o26_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I28 Switch", AFE_CONN26, 28, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN26, 24, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN26, 26, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o27_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN27, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN27, 7, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o28_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN28, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN28, 8, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o29_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN29, 5, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN29, 7, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o30_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN30, 6, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN30, 8, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o31_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I29 Switch", AFE_CONN31, 29, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o32_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I30 Switch", AFE_CONN32, 30, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o33_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I31 Switch", AFE_CONN33, 31, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o34_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I32 Switch", AFE_CONN34_1, 0, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o35_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I33 Switch", AFE_CONN35_1, 1, 1, 0),
};
static const struct snd_kcontrol_new mt8365_afe_o36_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I34 Switch", AFE_CONN36_1, 2, 1, 0),
};
static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13,
0, 1, 0),
};
static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14,
1, 1, 0),
};
static int mt8365_afe_cm2_io_input_mux_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = mCM2Input;
return 0;
}
static int mt8365_afe_cm2_io_input_mux_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm =
snd_soc_dapm_kcontrol_dapm(kcontrol);
struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(comp);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
int ret;
mCM2Input = ucontrol->value.enumerated.item[0];
afe_priv->cm2_mux_input = mCM2Input;
ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
return ret;
}
static const char * const fmhwgain_text[] = {
"OPEN", "FM_HW_GAIN_IO"
};
static const char * const ain_text[] = {
"INT ADC", "EXT ADC",
};
static const char * const vul2_in_input_text[] = {
"VUL2_IN_FROM_O17O18", "VUL2_IN_FROM_CM1",
};
static const char * const mt8365_afe_cm2_mux_text[] = {
"OPEN", "FROM_GASRC1_OUT", "FROM_GASRC2_OUT", "FROM_TDM_ASRC_OUT",
};
static SOC_ENUM_SINGLE_VIRT_DECL(fmhwgain_enum, fmhwgain_text);
static SOC_ENUM_SINGLE_DECL(ain_enum, AFE_ADDA_TOP_CON0, 0, ain_text);
static SOC_ENUM_SINGLE_VIRT_DECL(vul2_in_input_enum, vul2_in_input_text);
static SOC_ENUM_SINGLE_VIRT_DECL(mt8365_afe_cm2_mux_input_enum,
mt8365_afe_cm2_mux_text);
static const struct snd_kcontrol_new fmhwgain_mux =
SOC_DAPM_ENUM("FM HW Gain Source", fmhwgain_enum);
static const struct snd_kcontrol_new ain_mux =
SOC_DAPM_ENUM("AIN Source", ain_enum);
static const struct snd_kcontrol_new vul2_in_input_mux =
SOC_DAPM_ENUM("VUL2 Input", vul2_in_input_enum);
static const struct snd_kcontrol_new mt8365_afe_cm2_mux_input_mux =
SOC_DAPM_ENUM_EXT("CM2_MUX Source", mt8365_afe_cm2_mux_input_enum,
mt8365_afe_cm2_io_input_mux_get,
mt8365_afe_cm2_io_input_mux_put);
static const struct snd_soc_dapm_widget mt8365_memif_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I07", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I08", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I05L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I06L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I07L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I08L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I09", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I10", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I11", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I10L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I11L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I20", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I21", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I22", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I23", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I24", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I25", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I27", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I28", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I29", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I30", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I31", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I32", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I33", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I34", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0,
mt8365_afe_o00_mix, ARRAY_SIZE(mt8365_afe_o00_mix)),
SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0,
mt8365_afe_o01_mix, ARRAY_SIZE(mt8365_afe_o01_mix)),
SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0,
mt8365_afe_o03_mix, ARRAY_SIZE(mt8365_afe_o03_mix)),
SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0,
mt8365_afe_o04_mix, ARRAY_SIZE(mt8365_afe_o04_mix)),
SND_SOC_DAPM_MIXER("O05", SND_SOC_NOPM, 0, 0,
mt8365_afe_o05_mix, ARRAY_SIZE(mt8365_afe_o05_mix)),
SND_SOC_DAPM_MIXER("O06", SND_SOC_NOPM, 0, 0,
mt8365_afe_o06_mix, ARRAY_SIZE(mt8365_afe_o06_mix)),
SND_SOC_DAPM_MIXER("O07", SND_SOC_NOPM, 0, 0,
mt8365_afe_o07_mix, ARRAY_SIZE(mt8365_afe_o07_mix)),
SND_SOC_DAPM_MIXER("O08", SND_SOC_NOPM, 0, 0,
mt8365_afe_o08_mix, ARRAY_SIZE(mt8365_afe_o08_mix)),
SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0,
mt8365_afe_o09_mix, ARRAY_SIZE(mt8365_afe_o09_mix)),
SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0,
mt8365_afe_o10_mix, ARRAY_SIZE(mt8365_afe_o10_mix)),
SND_SOC_DAPM_MIXER("O11", SND_SOC_NOPM, 0, 0,
mt8365_afe_o11_mix, ARRAY_SIZE(mt8365_afe_o11_mix)),
SND_SOC_DAPM_MIXER("O12", SND_SOC_NOPM, 0, 0,
mt8365_afe_o12_mix, ARRAY_SIZE(mt8365_afe_o12_mix)),
SND_SOC_DAPM_MIXER("O13", SND_SOC_NOPM, 0, 0,
mt8365_afe_o13_mix, ARRAY_SIZE(mt8365_afe_o13_mix)),
SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0,
mt8365_afe_o14_mix, ARRAY_SIZE(mt8365_afe_o14_mix)),
SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0,
mt8365_afe_o15_mix, ARRAY_SIZE(mt8365_afe_o15_mix)),
SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0,
mt8365_afe_o16_mix, ARRAY_SIZE(mt8365_afe_o16_mix)),
SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0,
mt8365_afe_o17_mix, ARRAY_SIZE(mt8365_afe_o17_mix)),
SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0,
mt8365_afe_o18_mix, ARRAY_SIZE(mt8365_afe_o18_mix)),
SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0,
mt8365_afe_o19_mix, ARRAY_SIZE(mt8365_afe_o19_mix)),
SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0,
mt8365_afe_o20_mix, ARRAY_SIZE(mt8365_afe_o20_mix)),
SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0,
mt8365_afe_o21_mix, ARRAY_SIZE(mt8365_afe_o21_mix)),
SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0,
mt8365_afe_o22_mix, ARRAY_SIZE(mt8365_afe_o22_mix)),
SND_SOC_DAPM_MIXER("O23", SND_SOC_NOPM, 0, 0,
mt8365_afe_o23_mix, ARRAY_SIZE(mt8365_afe_o23_mix)),
SND_SOC_DAPM_MIXER("O24", SND_SOC_NOPM, 0, 0,
mt8365_afe_o24_mix, ARRAY_SIZE(mt8365_afe_o24_mix)),
SND_SOC_DAPM_MIXER("O25", SND_SOC_NOPM, 0, 0,
mt8365_afe_o25_mix, ARRAY_SIZE(mt8365_afe_o25_mix)),
SND_SOC_DAPM_MIXER("O26", SND_SOC_NOPM, 0, 0,
mt8365_afe_o26_mix, ARRAY_SIZE(mt8365_afe_o26_mix)),
SND_SOC_DAPM_MIXER("O27", SND_SOC_NOPM, 0, 0,
mt8365_afe_o27_mix, ARRAY_SIZE(mt8365_afe_o27_mix)),
SND_SOC_DAPM_MIXER("O28", SND_SOC_NOPM, 0, 0,
mt8365_afe_o28_mix, ARRAY_SIZE(mt8365_afe_o28_mix)),
SND_SOC_DAPM_MIXER("O29", SND_SOC_NOPM, 0, 0,
mt8365_afe_o29_mix, ARRAY_SIZE(mt8365_afe_o29_mix)),
SND_SOC_DAPM_MIXER("O30", SND_SOC_NOPM, 0, 0,
mt8365_afe_o30_mix, ARRAY_SIZE(mt8365_afe_o30_mix)),
SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0,
mt8365_afe_o31_mix, ARRAY_SIZE(mt8365_afe_o31_mix)),
SND_SOC_DAPM_MIXER("O32", SND_SOC_NOPM, 0, 0,
mt8365_afe_o32_mix, ARRAY_SIZE(mt8365_afe_o32_mix)),
SND_SOC_DAPM_MIXER("O33", SND_SOC_NOPM, 0, 0,
mt8365_afe_o33_mix, ARRAY_SIZE(mt8365_afe_o33_mix)),
SND_SOC_DAPM_MIXER("O34", SND_SOC_NOPM, 0, 0,
mt8365_afe_o34_mix, ARRAY_SIZE(mt8365_afe_o34_mix)),
SND_SOC_DAPM_MIXER("O35", SND_SOC_NOPM, 0, 0,
mt8365_afe_o35_mix, ARRAY_SIZE(mt8365_afe_o35_mix)),
SND_SOC_DAPM_MIXER("O36", SND_SOC_NOPM, 0, 0,
mt8365_afe_o36_mix, ARRAY_SIZE(mt8365_afe_o36_mix)),
SND_SOC_DAPM_MIXER("CM2_Mux IO", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("CM1_IO", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("O17O18", SND_SOC_NOPM, 0, 0, NULL, 0),
/* inter-connections */
SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0,
mtk_hw_gain1_in_ch1_mix,
ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)),
SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0,
mtk_hw_gain1_in_ch2_mix,
ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)),
SND_SOC_DAPM_INPUT("DL Source"),
SND_SOC_DAPM_MUX("CM2_Mux_IO Input Mux", SND_SOC_NOPM, 0, 0,
&mt8365_afe_cm2_mux_input_mux),
SND_SOC_DAPM_MUX("AIN Mux", SND_SOC_NOPM, 0, 0, &ain_mux),
SND_SOC_DAPM_MUX("VUL2 Input Mux", SND_SOC_NOPM, 0, 0,
&vul2_in_input_mux),
SND_SOC_DAPM_MUX("FM HW Gain Mux", SND_SOC_NOPM, 0, 0, &fmhwgain_mux),
SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"),
SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"),
};
static const struct snd_soc_dapm_route mt8365_memif_routes[] = {
/* downlink */
{"I00", NULL, "2ND I2S Capture"},
{"I01", NULL, "2ND I2S Capture"},
{"I05", NULL, "DL1"},
{"I06", NULL, "DL1"},
{"I07", NULL, "DL2"},
{"I08", NULL, "DL2"},
{"O03", "I05 Switch", "I05"},
{"O04", "I06 Switch", "I06"},
{"O00", "I05 Switch", "I05"},
{"O01", "I06 Switch", "I06"},
{"O07", "I05 Switch", "I05"},
{"O08", "I06 Switch", "I06"},
{"O27", "I05 Switch", "I05"},
{"O28", "I06 Switch", "I06"},
{"O29", "I05 Switch", "I05"},
{"O30", "I06 Switch", "I06"},
{"O03", "I07 Switch", "I07"},
{"O04", "I08 Switch", "I08"},
{"O00", "I07 Switch", "I07"},
{"O01", "I08 Switch", "I08"},
{"O07", "I07 Switch", "I07"},
{"O08", "I08 Switch", "I08"},
/* uplink */
{"AWB", NULL, "O05"},
{"AWB", NULL, "O06"},
{"VUL", NULL, "O09"},
{"VUL", NULL, "O10"},
{"VUL3", NULL, "O11"},
{"VUL3", NULL, "O12"},
{"AIN Mux", "EXT ADC", "I2S Capture"},
{"I03", NULL, "AIN Mux"},
{"I04", NULL, "AIN Mux"},
{"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1", "Hostless FM DL"},
{"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2", "Hostless FM DL"},
{"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"},
{"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"},
{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"},
{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"},
{"FM HW Gain Mux", "FM_HW_GAIN_IO", "HW Gain 1 Out"},
{"Hostless FM UL", NULL, "FM HW Gain Mux"},
{"Hostless FM UL", NULL, "FM 2ND I2S Mux"},
{"O05", "I05 Switch", "I05L"},
{"O06", "I06 Switch", "I06L"},
{"O05", "I07 Switch", "I07L"},
{"O06", "I08 Switch", "I08L"},
{"O05", "I03 Switch", "I03"},
{"O06", "I04 Switch", "I04"},
{"O05", "I00 Switch", "I00"},
{"O06", "I01 Switch", "I01"},
{"O05", "I09 Switch", "I09"},
{"O06", "I22 Switch", "I22"},
{"O05", "I14 Switch", "I14"},
{"O06", "I15 Switch", "I15"},
{"O05", "I16 Switch", "I16"},
{"O06", "I17 Switch", "I17"},
{"O05", "I18 Switch", "I18"},
{"O06", "I19 Switch", "I19"},
{"O05", "I20 Switch", "I20"},
{"O06", "I21 Switch", "I21"},
{"O05", "I23 Switch", "I23"},
{"O06", "I24 Switch", "I24"},
{"O09", "I03 Switch", "I03"},
{"O10", "I04 Switch", "I04"},
{"O09", "I00 Switch", "I00"},
{"O10", "I01 Switch", "I01"},
{"O09", "I09 Switch", "I09"},
{"O10", "I22 Switch", "I22"},
{"O09", "I14 Switch", "I14"},
{"O10", "I15 Switch", "I15"},
{"O09", "I16 Switch", "I16"},
{"O10", "I17 Switch", "I17"},
{"O09", "I18 Switch", "I18"},
{"O10", "I19 Switch", "I19"},
{"O09", "I20 Switch", "I20"},
{"O10", "I21 Switch", "I21"},
{"O11", "I03 Switch", "I03"},
{"O12", "I04 Switch", "I04"},
{"O11", "I00 Switch", "I00"},
{"O12", "I01 Switch", "I01"},
{"O11", "I09 Switch", "I09"},
{"O12", "I22 Switch", "I22"},
{"O11", "I14 Switch", "I14"},
{"O12", "I15 Switch", "I15"},
{"O11", "I16 Switch", "I16"},
{"O12", "I17 Switch", "I17"},
{"O11", "I18 Switch", "I18"},
{"O12", "I19 Switch", "I19"},
{"O11", "I20 Switch", "I20"},
{"O12", "I21 Switch", "I21"},
/* CM2_Mux*/
{"CM2_Mux IO", NULL, "CM2_Mux_IO Input Mux"},
/* VUL2 */
{"VUL2", NULL, "VUL2 Input Mux"},
{"VUL2 Input Mux", "VUL2_IN_FROM_O17O18", "O17O18"},
{"VUL2 Input Mux", "VUL2_IN_FROM_CM1", "CM1_IO"},
{"O17O18", NULL, "O17"},
{"O17O18", NULL, "O18"},
{"CM1_IO", NULL, "O17"},
{"CM1_IO", NULL, "O18"},
{"CM1_IO", NULL, "O19"},
{"CM1_IO", NULL, "O20"},
{"CM1_IO", NULL, "O21"},
{"CM1_IO", NULL, "O22"},
{"CM1_IO", NULL, "O23"},
{"CM1_IO", NULL, "O24"},
{"CM1_IO", NULL, "O25"},
{"CM1_IO", NULL, "O26"},
{"CM1_IO", NULL, "O31"},
{"CM1_IO", NULL, "O32"},
{"CM1_IO", NULL, "O33"},
{"CM1_IO", NULL, "O34"},
{"CM1_IO", NULL, "O35"},
{"CM1_IO", NULL, "O36"},
{"O17", "I14 Switch", "I14"},
{"O18", "I15 Switch", "I15"},
{"O19", "I16 Switch", "I16"},
{"O20", "I17 Switch", "I17"},
{"O21", "I18 Switch", "I18"},
{"O22", "I19 Switch", "I19"},
{"O23", "I20 Switch", "I20"},
{"O24", "I21 Switch", "I21"},
{"O25", "I23 Switch", "I23"},
{"O26", "I24 Switch", "I24"},
{"O25", "I25 Switch", "I25"},
{"O26", "I26 Switch", "I26"},
{"O17", "I03 Switch", "I03"},
{"O18", "I04 Switch", "I04"},
{"O18", "I23 Switch", "I23"},
{"O18", "I25 Switch", "I25"},
{"O19", "I04 Switch", "I04"},
{"O19", "I23 Switch", "I23"},
{"O19", "I24 Switch", "I24"},
{"O19", "I25 Switch", "I25"},
{"O19", "I26 Switch", "I26"},
{"O20", "I24 Switch", "I24"},
{"O20", "I26 Switch", "I26"},
{"O21", "I23 Switch", "I23"},
{"O21", "I25 Switch", "I25"},
{"O22", "I24 Switch", "I24"},
{"O22", "I26 Switch", "I26"},
{"O23", "I23 Switch", "I23"},
{"O23", "I25 Switch", "I25"},
{"O24", "I24 Switch", "I24"},
{"O24", "I26 Switch", "I26"},
{"O24", "I23 Switch", "I23"},
{"O24", "I25 Switch", "I25"},
{"O13", "I00 Switch", "I00"},
{"O14", "I01 Switch", "I01"},
{"O03", "I10 Switch", "I10"},
{"O04", "I11 Switch", "I11"},
};
static const struct mtk_base_memif_data memif_data[MT8365_AFE_MEMIF_NUM] = {
{
.name = "DL1",
.id = MT8365_AFE_MEMIF_DL1,
.reg_ofs_base = AFE_DL1_BASE,
.reg_ofs_cur = AFE_DL1_CUR,
.fs_reg = AFE_DAC_CON1,
.fs_shift = 0,
.fs_maskbit = 0xf,
.mono_reg = AFE_DAC_CON1,
.mono_shift = 21,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 16,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 1,
.msb_reg = -1,
.msb_shift = -1,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "DL2",
.id = MT8365_AFE_MEMIF_DL2,
.reg_ofs_base = AFE_DL2_BASE,
.reg_ofs_cur = AFE_DL2_CUR,
.fs_reg = AFE_DAC_CON1,
.fs_shift = 4,
.fs_maskbit = 0xf,
.mono_reg = AFE_DAC_CON1,
.mono_shift = 22,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 18,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 2,
.msb_reg = -1,
.msb_shift = -1,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "TDM OUT",
.id = MT8365_AFE_MEMIF_TDM_OUT,
.reg_ofs_base = AFE_HDMI_OUT_BASE,
.reg_ofs_cur = AFE_HDMI_OUT_CUR,
.fs_reg = -1,
.fs_shift = -1,
.fs_maskbit = -1,
.mono_reg = -1,
.mono_shift = -1,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 28,
.enable_reg = AFE_HDMI_OUT_CON0,
.enable_shift = 0,
.msb_reg = -1,
.msb_shift = -1,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "AWB",
.id = MT8365_AFE_MEMIF_AWB,
.reg_ofs_base = AFE_AWB_BASE,
.reg_ofs_cur = AFE_AWB_CUR,
.fs_reg = AFE_DAC_CON1,
.fs_shift = 12,
.fs_maskbit = 0xf,
.mono_reg = AFE_DAC_CON1,
.mono_shift = 24,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 20,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 6,
.msb_reg = AFE_MEMIF_MSB,
.msb_shift = 17,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "VUL",
.id = MT8365_AFE_MEMIF_VUL,
.reg_ofs_base = AFE_VUL_BASE,
.reg_ofs_cur = AFE_VUL_CUR,
.fs_reg = AFE_DAC_CON1,
.fs_shift = 16,
.fs_maskbit = 0xf,
.mono_reg = AFE_DAC_CON1,
.mono_shift = 27,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 22,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 3,
.msb_reg = AFE_MEMIF_MSB,
.msb_shift = 20,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "VUL2",
.id = MT8365_AFE_MEMIF_VUL2,
.reg_ofs_base = AFE_VUL_D2_BASE,
.reg_ofs_cur = AFE_VUL_D2_CUR,
.fs_reg = AFE_DAC_CON0,
.fs_shift = 20,
.fs_maskbit = 0xf,
.mono_reg = -1,
.mono_shift = -1,
.hd_reg = AFE_MEMIF_PBUF_SIZE,
.hd_shift = 14,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 9,
.msb_reg = AFE_MEMIF_MSB,
.msb_shift = 21,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "VUL3",
.id = MT8365_AFE_MEMIF_VUL3,
.reg_ofs_base = AFE_VUL3_BASE,
.reg_ofs_cur = AFE_VUL3_CUR,
.fs_reg = AFE_DAC_CON1,
.fs_shift = 8,
.fs_maskbit = 0xf,
.mono_reg = AFE_DAC_CON0,
.mono_shift = 13,
.hd_reg = AFE_MEMIF_PBUF2_SIZE,
.hd_shift = 10,
.enable_reg = AFE_DAC_CON0,
.enable_shift = 12,
.msb_reg = AFE_MEMIF_MSB,
.msb_shift = 27,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
}, {
.name = "TDM IN",
.id = MT8365_AFE_MEMIF_TDM_IN,
.reg_ofs_base = AFE_HDMI_IN_2CH_BASE,
.reg_ofs_cur = AFE_HDMI_IN_2CH_CUR,
.fs_reg = -1,
.fs_shift = -1,
.fs_maskbit = -1,
.mono_reg = AFE_HDMI_IN_2CH_CON0,
.mono_shift = 1,
.hd_reg = AFE_MEMIF_PBUF2_SIZE,
.hd_shift = 8,
.hd_align_mshift = 5,
.enable_reg = AFE_HDMI_IN_2CH_CON0,
.enable_shift = 0,
.msb_reg = AFE_MEMIF_MSB,
.msb_shift = 28,
.agent_disable_reg = -1,
.agent_disable_shift = -1,
},
};
static const struct mtk_base_irq_data irq_data[MT8365_AFE_IRQ_NUM] = {
{
.id = MT8365_AFE_IRQ1,
.irq_cnt_reg = AFE_IRQ_MCU_CNT1,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 0,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 4,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 0,
}, {
.id = MT8365_AFE_IRQ2,
.irq_cnt_reg = AFE_IRQ_MCU_CNT2,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 1,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 8,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 1,
}, {
.id = MT8365_AFE_IRQ3,
.irq_cnt_reg = AFE_IRQ_MCU_CNT3,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 2,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 16,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 2,
}, {
.id = MT8365_AFE_IRQ4,
.irq_cnt_reg = AFE_IRQ_MCU_CNT4,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 3,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 20,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 3,
}, {
.id = MT8365_AFE_IRQ5,
.irq_cnt_reg = AFE_IRQ_MCU_CNT5,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON2,
.irq_en_shift = 3,
.irq_fs_reg = -1,
.irq_fs_shift = 0,
.irq_fs_maskbit = 0x0,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 4,
}, {
.id = MT8365_AFE_IRQ6,
.irq_cnt_reg = -1,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x0,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 13,
.irq_fs_reg = -1,
.irq_fs_shift = 0,
.irq_fs_maskbit = 0x0,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 5,
}, {
.id = MT8365_AFE_IRQ7,
.irq_cnt_reg = AFE_IRQ_MCU_CNT7,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 14,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 24,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 6,
}, {
.id = MT8365_AFE_IRQ8,
.irq_cnt_reg = AFE_IRQ_MCU_CNT8,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 15,
.irq_fs_reg = AFE_IRQ_MCU_CON,
.irq_fs_shift = 28,
.irq_fs_maskbit = 0xf,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 7,
}, {
.id = MT8365_AFE_IRQ9,
.irq_cnt_reg = -1,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x0,
.irq_en_reg = AFE_IRQ_MCU_CON2,
.irq_en_shift = 2,
.irq_fs_reg = -1,
.irq_fs_shift = 0,
.irq_fs_maskbit = 0x0,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 8,
}, {
.id = MT8365_AFE_IRQ10,
.irq_cnt_reg = AFE_IRQ_MCU_CNT10,
.irq_cnt_shift = 0,
.irq_cnt_maskbit = 0x3ffff,
.irq_en_reg = AFE_IRQ_MCU_CON2,
.irq_en_shift = 4,
.irq_fs_reg = -1,
.irq_fs_shift = 0,
.irq_fs_maskbit = 0x0,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = 9,
},
};
static int memif_specified_irqs[MT8365_AFE_MEMIF_NUM] = {
[MT8365_AFE_MEMIF_DL1] = MT8365_AFE_IRQ1,
[MT8365_AFE_MEMIF_DL2] = MT8365_AFE_IRQ2,
[MT8365_AFE_MEMIF_TDM_OUT] = MT8365_AFE_IRQ5,
[MT8365_AFE_MEMIF_AWB] = MT8365_AFE_IRQ3,
[MT8365_AFE_MEMIF_VUL] = MT8365_AFE_IRQ4,
[MT8365_AFE_MEMIF_VUL2] = MT8365_AFE_IRQ7,
[MT8365_AFE_MEMIF_VUL3] = MT8365_AFE_IRQ8,
[MT8365_AFE_MEMIF_TDM_IN] = MT8365_AFE_IRQ10,
};
static const struct regmap_config mt8365_afe_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = MAX_REGISTER,
.cache_type = REGCACHE_NONE,
};
static irqreturn_t mt8365_afe_irq_handler(int irq, void *dev_id)
{
struct mtk_base_afe *afe = dev_id;
unsigned int reg_value;
unsigned int mcu_irq_mask;
int i, ret;
ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &reg_value);
if (ret) {
dev_err_ratelimited(afe->dev, "%s irq status err\n", __func__);
reg_value = AFE_IRQ_STATUS_BITS;
goto err_irq;
}
ret = regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_irq_mask);
if (ret) {
dev_err_ratelimited(afe->dev, "%s irq mcu_en err\n", __func__);
reg_value = AFE_IRQ_STATUS_BITS;
goto err_irq;
}
/* only clr cpu irq */
reg_value &= mcu_irq_mask;
for (i = 0; i < MT8365_AFE_MEMIF_NUM; i++) {
struct mtk_base_afe_memif *memif = &afe->memif[i];
struct mtk_base_afe_irq *mcu_irq;
if (memif->irq_usage < 0)
continue;
mcu_irq = &afe->irqs[memif->irq_usage];
if (!(reg_value & (1 << mcu_irq->irq_data->irq_clr_shift)))
continue;
snd_pcm_period_elapsed(memif->substream);
}
err_irq:
/* clear irq */
regmap_write(afe->regmap, AFE_IRQ_MCU_CLR,
reg_value & AFE_IRQ_STATUS_BITS);
return IRQ_HANDLED;
}
static int __maybe_unused mt8365_afe_runtime_suspend(struct device *dev)
{
return 0;
}
static int mt8365_afe_runtime_resume(struct device *dev)
{
return 0;
}
static int __maybe_unused mt8365_afe_suspend(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
struct regmap *regmap = afe->regmap;
int i;
mt8365_afe_enable_main_clk(afe);
if (!afe->reg_back_up)
afe->reg_back_up =
devm_kcalloc(dev, afe->reg_back_up_list_num,
sizeof(unsigned int), GFP_KERNEL);
for (i = 0; i < afe->reg_back_up_list_num; i++)
regmap_read(regmap, afe->reg_back_up_list[i],
&afe->reg_back_up[i]);
mt8365_afe_disable_main_clk(afe);
return 0;
}
static int __maybe_unused mt8365_afe_resume(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
struct regmap *regmap = afe->regmap;
int i = 0;
if (!afe->reg_back_up)
return 0;
mt8365_afe_enable_main_clk(afe);
for (i = 0; i < afe->reg_back_up_list_num; i++)
regmap_write(regmap, afe->reg_back_up_list[i],
afe->reg_back_up[i]);
mt8365_afe_disable_main_clk(afe);
return 0;
}
static int __maybe_unused mt8365_afe_dev_runtime_suspend(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
if (pm_runtime_status_suspended(dev) || afe->suspended)
return 0;
mt8365_afe_suspend(dev);
afe->suspended = true;
return 0;
}
static int __maybe_unused mt8365_afe_dev_runtime_resume(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
if (pm_runtime_status_suspended(dev) || !afe->suspended)
return 0;
mt8365_afe_resume(dev);
afe->suspended = false;
return 0;
}
static int mt8365_afe_init_registers(struct mtk_base_afe *afe)
{
size_t i;
static struct {
unsigned int reg;
unsigned int mask;
unsigned int val;
} init_regs[] = {
{ AFE_CONN_24BIT, GENMASK(31, 0), GENMASK(31, 0) },
{ AFE_CONN_24BIT_1, GENMASK(21, 0), GENMASK(21, 0) },
};
mt8365_afe_enable_main_clk(afe);
for (i = 0; i < ARRAY_SIZE(init_regs); i++)
regmap_update_bits(afe->regmap, init_regs[i].reg,
init_regs[i].mask, init_regs[i].val);
mt8365_afe_disable_main_clk(afe);
return 0;
}
static int mt8365_dai_memif_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mt8365_memif_dai_driver;
dai->num_dai_drivers = ARRAY_SIZE(mt8365_memif_dai_driver);
dai->dapm_widgets = mt8365_memif_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mt8365_memif_widgets);
dai->dapm_routes = mt8365_memif_routes;
dai->num_dapm_routes = ARRAY_SIZE(mt8365_memif_routes);
return 0;
}
typedef int (*dai_register_cb)(struct mtk_base_afe *);
static const dai_register_cb dai_register_cbs[] = {
mt8365_dai_pcm_register,
mt8365_dai_i2s_register,
mt8365_dai_adda_register,
mt8365_dai_dmic_register,
mt8365_dai_memif_register,
};
static int mt8365_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
struct mt8365_afe_private *afe_priv;
struct device *dev;
int ret, i, sel_irq;
unsigned int irq_id;
struct resource *res;
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
return -ENOMEM;
platform_set_drvdata(pdev, afe);
afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
GFP_KERNEL);
if (!afe->platform_priv)
return -ENOMEM;
afe_priv = afe->platform_priv;
afe->dev = &pdev->dev;
dev = afe->dev;
spin_lock_init(&afe_priv->afe_ctrl_lock);
mutex_init(&afe_priv->afe_clk_mutex);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(afe->base_addr))
return PTR_ERR(afe->base_addr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
afe_priv->afe_sram_vir_addr =
devm_ioremap_resource(&pdev->dev, res);
if (!IS_ERR(afe_priv->afe_sram_vir_addr)) {
afe_priv->afe_sram_phy_addr = res->start;
afe_priv->afe_sram_size = resource_size(res);
}
}
/* initial audio related clock */
ret = mt8365_afe_init_audio_clk(afe);
if (ret)
return dev_err_probe(afe->dev, ret, "mt8365_afe_init_audio_clk fail\n");
afe->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "top_audio_sel",
afe->base_addr,
&mt8365_afe_regmap_config);
if (IS_ERR(afe->regmap))
return PTR_ERR(afe->regmap);
/* memif % irq initialize*/
afe->memif_size = MT8365_AFE_MEMIF_NUM;
afe->memif = devm_kcalloc(afe->dev, afe->memif_size,
sizeof(*afe->memif), GFP_KERNEL);
if (!afe->memif)
return -ENOMEM;
afe->irqs_size = MT8365_AFE_IRQ_NUM;
afe->irqs = devm_kcalloc(afe->dev, afe->irqs_size,
sizeof(*afe->irqs), GFP_KERNEL);
if (!afe->irqs)
return -ENOMEM;
for (i = 0; i < afe->irqs_size; i++)
afe->irqs[i].irq_data = &irq_data[i];
irq_id = platform_get_irq(pdev, 0);
if (!irq_id) {
dev_err_probe(afe->dev, irq_id, "np %s no irq\n", afe->dev->of_node->name);
return -ENXIO;
}
ret = devm_request_irq(afe->dev, irq_id, mt8365_afe_irq_handler,
0, "Afe_ISR_Handle", (void *)afe);
if (ret)
return dev_err_probe(afe->dev, ret, "could not request_irq\n");
/* init sub_dais */
INIT_LIST_HEAD(&afe->sub_dais);
for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
ret = dai_register_cbs[i](afe);
if (ret) {
dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
i, ret);
return ret;
}
}
/* init dai_driver and component_driver */
ret = mtk_afe_combine_sub_dai(afe);
if (ret) {
dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
ret);
return ret;
}
for (i = 0; i < afe->memif_size; i++) {
afe->memif[i].data = &memif_data[i];
sel_irq = memif_specified_irqs[i];
if (sel_irq >= 0) {
afe->memif[i].irq_usage = sel_irq;
afe->memif[i].const_irq = 1;
afe->irqs[sel_irq].irq_occupyed = true;
} else {
afe->memif[i].irq_usage = -1;
}
}
afe->mtk_afe_hardware = &mt8365_afe_hardware;
afe->memif_fs = mt8365_memif_fs;
afe->irq_fs = mt8365_irq_fs;
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
pm_runtime_get_sync(&pdev->dev);
afe->reg_back_up_list = mt8365_afe_backup_list;
afe->reg_back_up_list_num = ARRAY_SIZE(mt8365_afe_backup_list);
afe->runtime_resume = mt8365_afe_runtime_resume;
afe->runtime_suspend = mt8365_afe_runtime_suspend;
/* open afe pdn for dapm read/write audio register */
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE);
/* Set 26m parent clk */
mt8365_afe_set_clk_parent(afe,
afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL],
afe_priv->clocks[MT8365_CLK_CLK26M]);
ret = devm_snd_soc_register_component(&pdev->dev,
&mtk_afe_pcm_platform,
afe->dai_drivers,
afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_platform\n");
return ret;
}
mt8365_afe_init_registers(afe);
return 0;
}
static void mt8365_afe_pcm_dev_remove(struct platform_device *pdev)
{
struct mtk_base_afe *afe = platform_get_drvdata(pdev);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
mt8365_afe_runtime_suspend(&pdev->dev);
}
static const struct of_device_id mt8365_afe_pcm_dt_match[] = {
{ .compatible = "mediatek,mt8365-afe-pcm", },
{ }
};
MODULE_DEVICE_TABLE(of, mt8365_afe_pcm_dt_match);
static const struct dev_pm_ops mt8365_afe_pm_ops = {
SET_RUNTIME_PM_OPS(mt8365_afe_dev_runtime_suspend,
mt8365_afe_dev_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(mt8365_afe_suspend,
mt8365_afe_resume)
};
static struct platform_driver mt8365_afe_pcm_driver = {
.driver = {
.name = "mt8365-afe-pcm",
.of_match_table = mt8365_afe_pcm_dt_match,
.pm = &mt8365_afe_pm_ops,
},
.probe = mt8365_afe_pcm_dev_probe,
.remove_new = mt8365_afe_pcm_dev_remove,
};
module_platform_driver(mt8365_afe_pcm_driver);
MODULE_DESCRIPTION("MediaTek ALSA SoC AFE platform driver");
MODULE_AUTHOR("Jia Zeng <jia.zeng@mediatek.com>");
MODULE_AUTHOR("Alexandre Mergnat <amergnat@baylibre.com>");
MODULE_LICENSE("GPL");
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 ALSA SoC Audio DAI ADDA Control
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"
#include "../common/mtk-dai-adda-common.h"
static int adda_afe_on_ref_cnt;
/* DAI Drivers */
static int mt8365_dai_set_adda_out(struct mtk_base_afe *afe, unsigned int rate)
{
unsigned int val;
if (rate == 8000 || rate == 16000)
val = AFE_ADDA_DL_VOICE_DATA;
else
val = 0;
val |= FIELD_PREP(AFE_ADDA_DL_SAMPLING_RATE,
mtk_adda_dl_rate_transform(afe, rate));
val |= AFE_ADDA_DL_8X_UPSAMPLE |
AFE_ADDA_DL_MUTE_OFF_CH1 |
AFE_ADDA_DL_MUTE_OFF_CH2 |
AFE_ADDA_DL_DEGRADE_GAIN;
regmap_update_bits(afe->regmap, AFE_ADDA_PREDIS_CON0, 0xffffffff, 0);
regmap_update_bits(afe->regmap, AFE_ADDA_PREDIS_CON1, 0xffffffff, 0);
regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 0xffffffff, val);
/* SA suggest apply -0.3db to audio/speech path */
regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON1,
0xffffffff, 0xf74f0000);
/* SA suggest use default value for sdm */
regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON,
0xffffffff, 0x0700701e);
return 0;
}
static int mt8365_dai_set_adda_in(struct mtk_base_afe *afe, unsigned int rate)
{
unsigned int val;
val = FIELD_PREP(AFE_ADDA_UL_SAMPLING_RATE,
mtk_adda_ul_rate_transform(afe, rate));
regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
AFE_ADDA_UL_SAMPLING_RATE, val);
/* Using Internal ADC */
regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x0);
return 0;
}
int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe)
{
unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
adda_afe_on_ref_cnt++;
if (adda_afe_on_ref_cnt == 1)
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
AFE_ADDA_UL_DL_ADDA_AFE_ON,
AFE_ADDA_UL_DL_ADDA_AFE_ON);
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe)
{
unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
adda_afe_on_ref_cnt--;
if (adda_afe_on_ref_cnt == 0)
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
AFE_ADDA_UL_DL_ADDA_AFE_ON,
~AFE_ADDA_UL_DL_ADDA_AFE_ON);
else if (adda_afe_on_ref_cnt < 0) {
adda_afe_on_ref_cnt = 0;
dev_warn(afe->dev, "Abnormal adda_on ref count. Force it to 0\n");
}
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
return 0;
}
static void mt8365_dai_set_adda_out_enable(struct mtk_base_afe *afe,
bool enable)
{
regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 0x1, enable);
if (enable)
mt8365_dai_enable_adda_on(afe);
else
mt8365_dai_disable_adda_on(afe);
}
static void mt8365_dai_set_adda_in_enable(struct mtk_base_afe *afe, bool enable)
{
if (enable) {
regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 0x1, 0x1);
mt8365_dai_enable_adda_on(afe);
/* enable aud_pad_top fifo */
regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP,
0xffffffff, 0x31);
} else {
/* disable aud_pad_top fifo */
regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP,
0xffffffff, 0x30);
regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 0x1, 0x0);
/* de suggest disable ADDA_UL_SRC at least wait 125us */
usleep_range(150, 300);
mt8365_dai_disable_adda_on(afe);
}
}
static int mt8365_dai_int_adda_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
unsigned int stream = substream->stream;
mt8365_afe_enable_main_clk(afe);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DAC);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DAC_PREDIS);
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_ADC);
}
return 0;
}
static void mt8365_dai_int_adda_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be =
&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
unsigned int stream = substream->stream;
if (be->prepared[stream]) {
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mt8365_dai_set_adda_out_enable(afe, false);
mt8365_afe_set_i2s_out_enable(afe, false);
} else {
mt8365_dai_set_adda_in_enable(afe, false);
}
be->prepared[stream] = false;
}
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DAC_PREDIS);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DAC);
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_ADC);
}
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_dai_int_adda_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be =
&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
unsigned int rate = substream->runtime->rate;
int bit_width = snd_pcm_format_width(substream->runtime->format);
int ret;
dev_info(afe->dev, "%s '%s' rate = %u\n", __func__,
snd_pcm_stream_str(substream), rate);
if (be->prepared[substream->stream]) {
dev_info(afe->dev, "%s '%s' prepared already\n",
__func__, snd_pcm_stream_str(substream));
return 0;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = mt8365_dai_set_adda_out(afe, rate);
if (ret)
return ret;
ret = mt8365_afe_set_i2s_out(afe, rate, bit_width);
if (ret)
return ret;
mt8365_dai_set_adda_out_enable(afe, true);
mt8365_afe_set_i2s_out_enable(afe, true);
} else {
ret = mt8365_dai_set_adda_in(afe, rate);
if (ret)
return ret;
mt8365_dai_set_adda_in_enable(afe, true);
}
be->prepared[substream->stream] = true;
return 0;
}
static const struct snd_soc_dai_ops mt8365_afe_int_adda_ops = {
.startup = mt8365_dai_int_adda_startup,
.shutdown = mt8365_dai_int_adda_shutdown,
.prepare = mt8365_dai_int_adda_prepare,
};
static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
{
.name = "INT ADDA",
.id = MT8365_AFE_IO_INT_ADDA,
.playback = {
.stream_name = "INT ADDA Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "INT ADDA Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_int_adda_ops,
}
};
/* DAI Controls */
static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN3,
10, 1, 0),
};
static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN4,
11, 1, 0),
};
static const struct snd_kcontrol_new int_adda_o03_o04_enable_ctl =
SOC_DAPM_SINGLE_VIRT("Switch", 1);
/* DAI widget */
static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
SND_SOC_DAPM_SWITCH("INT ADDA O03_O04", SND_SOC_NOPM, 0, 0,
&int_adda_o03_o04_enable_ctl),
/* inter-connections */
SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch1_mix,
ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch2_mix,
ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
};
/* DAI route */
static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
{"INT ADDA O03_O04", "Switch", "O03"},
{"INT ADDA O03_O04", "Switch", "O04"},
{"INT ADDA Playback", NULL, "INT ADDA O03_O04"},
{"INT ADDA Playback", NULL, "ADDA_DL_CH1"},
{"INT ADDA Playback", NULL, "ADDA_DL_CH2"},
{"AIN Mux", "INT ADC", "INT ADDA Capture"},
{"ADDA_DL_CH1", "GAIN1_OUT_CH1", "Hostless FM DL"},
{"ADDA_DL_CH2", "GAIN1_OUT_CH2", "Hostless FM DL"},
};
int mt8365_dai_adda_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_adda_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
dai->dapm_widgets = mtk_dai_adda_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
dai->dapm_routes = mtk_dai_adda_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
return 0;
}
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 ALSA SoC Audio DAI DMIC Control
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"
struct mt8365_dmic_data {
bool two_wire_mode;
unsigned int clk_phase_sel_ch1;
unsigned int clk_phase_sel_ch2;
bool iir_on;
unsigned int irr_mode;
unsigned int dmic_mode;
unsigned int dmic_channel;
};
static int get_chan_reg(unsigned int channel)
{
switch (channel) {
case 8:
fallthrough;
case 7:
return AFE_DMIC3_UL_SRC_CON0;
case 6:
fallthrough;
case 5:
return AFE_DMIC2_UL_SRC_CON0;
case 4:
fallthrough;
case 3:
return AFE_DMIC1_UL_SRC_CON0;
case 2:
fallthrough;
case 1:
return AFE_DMIC0_UL_SRC_CON0;
default:
return -EINVAL;
}
}
/* DAI Drivers */
static void audio_dmic_adda_enable(struct mtk_base_afe *afe)
{
mt8365_dai_enable_adda_on(afe);
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
}
static void audio_dmic_adda_disable(struct mtk_base_afe *afe)
{
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
~AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
mt8365_dai_disable_adda_on(afe);
}
static void mt8365_dai_enable_dmic(struct mtk_base_afe *afe,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
unsigned int val_mask;
int reg = get_chan_reg(dmic_data->dmic_channel);
if (reg < 0)
return;
/* val and mask will be always same to enable */
val_mask = DMIC_TOP_CON_CH1_ON |
DMIC_TOP_CON_CH2_ON |
DMIC_TOP_CON_SRC_ON;
regmap_update_bits(afe->regmap, reg, val_mask, val_mask);
}
static void mt8365_dai_disable_dmic(struct mtk_base_afe *afe,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
unsigned int mask;
int reg = get_chan_reg(dmic_data->dmic_channel);
if (reg < 0)
return;
dev_dbg(afe->dev, "%s dmic_channel %d\n", __func__, dmic_data->dmic_channel);
mask = DMIC_TOP_CON_CH1_ON |
DMIC_TOP_CON_CH2_ON |
DMIC_TOP_CON_SRC_ON |
DMIC_TOP_CON_SDM3_LEVEL_MODE;
/* Set all masked values to 0 */
regmap_update_bits(afe->regmap, reg, mask, 0);
}
static const struct reg_sequence mt8365_dmic_iir_coeff[] = {
{ AFE_DMIC0_IIR_COEF_02_01, 0x00000000 },
{ AFE_DMIC0_IIR_COEF_04_03, 0x00003FB8 },
{ AFE_DMIC0_IIR_COEF_06_05, 0x3FB80000 },
{ AFE_DMIC0_IIR_COEF_08_07, 0x3FB80000 },
{ AFE_DMIC0_IIR_COEF_10_09, 0x0000C048 },
{ AFE_DMIC1_IIR_COEF_02_01, 0x00000000 },
{ AFE_DMIC1_IIR_COEF_04_03, 0x00003FB8 },
{ AFE_DMIC1_IIR_COEF_06_05, 0x3FB80000 },
{ AFE_DMIC1_IIR_COEF_08_07, 0x3FB80000 },
{ AFE_DMIC1_IIR_COEF_10_09, 0x0000C048 },
{ AFE_DMIC2_IIR_COEF_02_01, 0x00000000 },
{ AFE_DMIC2_IIR_COEF_04_03, 0x00003FB8 },
{ AFE_DMIC2_IIR_COEF_06_05, 0x3FB80000 },
{ AFE_DMIC2_IIR_COEF_08_07, 0x3FB80000 },
{ AFE_DMIC2_IIR_COEF_10_09, 0x0000C048 },
{ AFE_DMIC3_IIR_COEF_02_01, 0x00000000 },
{ AFE_DMIC3_IIR_COEF_04_03, 0x00003FB8 },
{ AFE_DMIC3_IIR_COEF_06_05, 0x3FB80000 },
{ AFE_DMIC3_IIR_COEF_08_07, 0x3FB80000 },
{ AFE_DMIC3_IIR_COEF_10_09, 0x0000C048 },
};
static int mt8365_dai_load_dmic_iir_coeff_table(struct mtk_base_afe *afe)
{
return regmap_multi_reg_write(afe->regmap,
mt8365_dmic_iir_coeff,
ARRAY_SIZE(mt8365_dmic_iir_coeff));
}
static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
bool two_wire_mode = dmic_data->two_wire_mode;
unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1;
unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2;
unsigned int val = 0;
unsigned int rate = dai->rate;
int reg = get_chan_reg(dai->channels);
if (reg < 0)
return -EINVAL;
dmic_data->dmic_channel = dai->channels;
val |= DMIC_TOP_CON_SDM3_LEVEL_MODE;
if (two_wire_mode) {
val |= DMIC_TOP_CON_TWO_WIRE_MODE;
} else {
val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH1,
clk_phase_sel_ch1);
val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH2,
clk_phase_sel_ch2);
}
switch (rate) {
case 48000:
val |= DMIC_TOP_CON_VOICE_MODE_48K;
break;
case 32000:
val |= DMIC_TOP_CON_VOICE_MODE_32K;
break;
case 16000:
val |= DMIC_TOP_CON_VOICE_MODE_16K;
break;
case 8000:
val |= DMIC_TOP_CON_VOICE_MODE_8K;
break;
default:
return -EINVAL;
}
regmap_update_bits(afe->regmap, reg, DMIC_TOP_CON_CONFIG_MASK, val);
return 0;
}
static int mt8365_dai_dmic_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
mt8365_afe_enable_main_clk(afe);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
audio_dmic_adda_enable(afe);
return 0;
}
static void mt8365_dai_dmic_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
mt8365_dai_disable_dmic(afe, substream, dai);
audio_dmic_adda_disable(afe);
/* HW Request delay 125us before CG off */
usleep_range(125, 300);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_dai_dmic_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
mt8365_dai_configure_dmic(afe, substream, dai);
mt8365_dai_enable_dmic(afe, substream, dai);
return 0;
}
static const struct snd_soc_dai_ops mt8365_afe_dmic_ops = {
.startup = mt8365_dai_dmic_startup,
.shutdown = mt8365_dai_dmic_shutdown,
.prepare = mt8365_dai_dmic_prepare,
};
static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = {
{
.name = "DMIC",
.id = MT8365_AFE_IO_DMIC,
.capture = {
.stream_name = "DMIC Capture",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_dmic_ops,
}
};
/* DAI Controls */
/* Values for 48kHz mode */
static const char * const iir_mode_src[] = {
"SW custom", "5Hz", "10Hz", "25Hz", "50Hz", "65Hz"
};
static SOC_ENUM_SINGLE_DECL(iir_mode, AFE_DMIC0_UL_SRC_CON0, 7, iir_mode_src);
static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = {
SOC_SINGLE("DMIC IIR Switch", AFE_DMIC0_UL_SRC_CON0, DMIC_TOP_CON_IIR_ON, 1, 0),
SOC_ENUM("DMIC IIR Mode", iir_mode),
};
/* DAI widget */
static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = {
SND_SOC_DAPM_INPUT("DMIC In"),
};
/* DAI route */
static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = {
{"I14", NULL, "DMIC Capture"},
{"I15", NULL, "DMIC Capture"},
{"I16", NULL, "DMIC Capture"},
{"I17", NULL, "DMIC Capture"},
{"I18", NULL, "DMIC Capture"},
{"I19", NULL, "DMIC Capture"},
{"I20", NULL, "DMIC Capture"},
{"I21", NULL, "DMIC Capture"},
{"DMIC Capture", NULL, "DMIC In"},
};
static int init_dmic_priv_data(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_dmic_data *dmic_priv;
struct device_node *np = afe->dev->of_node;
unsigned int temps[4];
int ret;
dmic_priv = devm_kzalloc(afe->dev, sizeof(*dmic_priv), GFP_KERNEL);
if (!dmic_priv)
return -ENOMEM;
ret = of_property_read_u32_array(np, "mediatek,dmic-mode",
&temps[0],
1);
if (ret == 0)
dmic_priv->two_wire_mode = !!temps[0];
if (!dmic_priv->two_wire_mode) {
dmic_priv->clk_phase_sel_ch1 = 0;
dmic_priv->clk_phase_sel_ch2 = 4;
}
afe_priv->dai_priv[MT8365_AFE_IO_DMIC] = dmic_priv;
return 0;
}
int mt8365_dai_dmic_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_dmic_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver);
dai->controls = mtk_dai_dmic_controls;
dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls);
dai->dapm_widgets = mtk_dai_dmic_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets);
dai->dapm_routes = mtk_dai_dmic_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes);
return init_dmic_priv_data(afe);
}
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 ALSA SoC Audio DAI I2S Control
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"
#define IIR_RATIOVER 9
#define IIR_INV_COEF 10
#define IIR_NO_NEED 11
struct mtk_afe_i2s_priv {
bool adda_link;
int i2s_out_on_ref_cnt;
int id;
int low_jitter_en;
int mclk_id;
int share_i2s_id;
unsigned int clk_id_in;
unsigned int clk_id_in_m_sel;
unsigned int clk_id_out;
unsigned int clk_id_out_m_sel;
unsigned int clk_in_mult;
unsigned int clk_out_mult;
unsigned int config_val_in;
unsigned int config_val_out;
unsigned int dynamic_bck;
unsigned int reg_off_in;
unsigned int reg_off_out;
};
/* This enum is merely for mtk_afe_i2s_priv declare */
enum {
DAI_I2S0 = 0,
DAI_I2S3,
DAI_I2S_NUM,
};
static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = {
[DAI_I2S0] = {
.id = MT8365_AFE_IO_I2S,
.mclk_id = MT8365_I2S0_MCK,
.share_i2s_id = -1,
.clk_id_in = MT8365_CLK_AUD_I2S2_M,
.clk_id_out = MT8365_CLK_AUD_I2S1_M,
.clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL,
.clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL,
.clk_in_mult = 256,
.clk_out_mult = 256,
.adda_link = true,
.config_val_out = AFE_I2S_CON1_I2S2_TO_PAD,
.reg_off_in = AFE_I2S_CON2,
.reg_off_out = AFE_I2S_CON1,
},
[DAI_I2S3] = {
.id = MT8365_AFE_IO_2ND_I2S,
.mclk_id = MT8365_I2S3_MCK,
.share_i2s_id = -1,
.clk_id_in = MT8365_CLK_AUD_I2S0_M,
.clk_id_out = MT8365_CLK_AUD_I2S3_M,
.clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL,
.clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL,
.clk_in_mult = 256,
.clk_out_mult = 256,
.adda_link = false,
.config_val_in = AFE_I2S_CON_FROM_IO_MUX,
.reg_off_in = AFE_I2S_CON,
.reg_off_out = AFE_I2S_CON3,
},
};
static const u32 *get_iir_coef(unsigned int input_fs,
unsigned int output_fs, unsigned int *count)
{
static const u32 IIR_COEF_48_TO_44p1[30] = {
0x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003,
0x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003,
0x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003,
0x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002,
0x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002,
};
static const u32 IIR_COEF_44p1_TO_32[42] = {
0x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002,
0x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003,
0x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003,
0x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002,
0x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002,
0x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001,
0x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002,
};
static const u32 IIR_COEF_48_TO_32[42] = {
0x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002,
0x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003,
0x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002,
0x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002,
0x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001,
0x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001,
0x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002,
};
static const u32 IIR_COEF_32_TO_16[48] = {
0x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001,
0x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002,
0x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002,
0x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002,
0x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002,
0x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002,
0x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001,
0x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001,
};
static const u32 IIR_COEF_96_TO_44p1[48] = {
0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
};
static const u32 IIR_COEF_44p1_TO_16[48] = {
0x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002,
0x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003,
0x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002,
0x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002,
0x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002,
0x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002,
0x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001,
0x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001,
};
static const u32 IIR_COEF_48_TO_16[48] = {
0x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002,
0x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003,
0x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003,
0x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002,
0x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002,
0x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002,
0x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002,
0x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001,
};
static const u32 IIR_COEF_96_TO_16[48] = {
0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
};
static const struct {
const u32 *coef;
unsigned int cnt;
} iir_coef_tbl_list[8] = {
/* 0: 0.9188 */
{ IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) },
/* 1: 0.7256 */
{ IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) },
/* 2: 0.6667 */
{ IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) },
/* 3: 0.5 */
{ IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) },
/* 4: 0.4594 */
{ IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) },
/* 5: 0.3628 */
{ IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) },
/* 6: 0.3333 */
{ IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) },
/* 7: 0.1667 */
{ IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) },
};
static const u32 freq_new_index[16] = {
0, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99
};
static const u32 iir_coef_tbl_matrix[13][13] = {
{/*0*/
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*1*/
1, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*2*/
2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*3*/
3, IIR_INV_COEF, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*4*/
5, 3, IIR_INV_COEF, 2, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*5*/
6, 4, 3, 2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED
},
{/*6*/
IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 3, IIR_INV_COEF,
IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*7*/
IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 5, 3,
IIR_INV_COEF, 1, IIR_NO_NEED, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*8*/
7, IIR_INV_COEF, IIR_INV_COEF, 6, 4, 3, 2, 0, IIR_NO_NEED,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*9*/
IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
IIR_INV_COEF, IIR_INV_COEF, 5, 3, IIR_INV_COEF,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{/*10*/
IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
IIR_INV_COEF, 6, 4, 3, 0,
IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
},
{ /*11*/
IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
IIR_INV_COEF, 3, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED
},
{/*12*/
IIR_RATIOVER, IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF,
IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
IIR_INV_COEF, 4, 3, 0, IIR_NO_NEED
},
};
const u32 *coef = NULL;
unsigned int cnt = 0;
u32 i = freq_new_index[input_fs];
u32 j = freq_new_index[output_fs];
if (i < 13 && j < 13) {
u32 k = iir_coef_tbl_matrix[i][j];
if (k >= IIR_NO_NEED) {
} else if (k == IIR_RATIOVER) {
} else if (k == IIR_INV_COEF) {
} else {
coef = iir_coef_tbl_list[k].coef;
cnt = iir_coef_tbl_list[k].cnt;
}
}
*count = cnt;
return coef;
}
static int mt8365_dai_set_config(struct mtk_base_afe *afe,
struct mtk_afe_i2s_priv *i2s_data,
bool is_input, unsigned int rate,
int bit_width)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be =
&afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE];
unsigned int val, reg_off;
int fs = mt8365_afe_fs_timing(rate);
if (fs < 0)
return -EINVAL;
val = AFE_I2S_CON_LOW_JITTER_CLK | AFE_I2S_CON_FORMAT_I2S;
val |= FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs);
if (is_input) {
reg_off = i2s_data->reg_off_in;
if (i2s_data->adda_link)
val |= i2s_data->config_val_in;
} else {
reg_off = i2s_data->reg_off_out;
val |= i2s_data->config_val_in;
}
/* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */
if (i2s_data->dynamic_bck) {
if (bit_width > 16)
val |= AFE_I2S_CON_WLEN_32BIT;
else
val &= ~(u32)AFE_I2S_CON_WLEN_32BIT;
} else {
val |= AFE_I2S_CON_WLEN_32BIT;
}
if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBM_CFM) {
val |= AFE_I2S_CON_SRC_SLAVE;
val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys
}
regmap_update_bits(afe->regmap, reg_off, ~(u32)AFE_I2S_CON_EN, val);
if (i2s_data->adda_link && is_input)
regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
return 0;
}
int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe,
unsigned int rate, int bit_width)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data =
afe_priv->dai_priv[MT8365_AFE_IO_I2S];
return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
}
static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe,
unsigned int rate_in,
unsigned int rate_out,
unsigned int width,
unsigned int mono,
int o16bit, int tracking)
{
int ifs, ofs = 0;
unsigned int val = 0;
unsigned int mask = 0;
const u32 *coef;
u32 iir_stage;
unsigned int coef_count = 0;
ifs = mt8365_afe_fs_timing(rate_in);
if (ifs < 0)
return -EINVAL;
ofs = mt8365_afe_fs_timing(rate_out);
if (ofs < 0)
return -EINVAL;
val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono);
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
O16BIT | IS_MONO, val);
coef = get_iir_coef(ifs, ofs, &coef_count);
iir_stage = ((u32)coef_count / 6) - 1;
if (coef) {
unsigned int i;
/* CPU control IIR coeff SRAM */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
COEFF_SRAM_CTRL, COEFF_SRAM_CTRL);
/* set to 0, IIR coeff SRAM addr */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13,
0xffffffff, 0x0);
for (i = 0; i < coef_count; ++i)
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12,
0xffffffff, coef[i]);
/* disable IIR coeff SRAM access */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
COEFF_SRAM_CTRL,
(unsigned long)~COEFF_SRAM_CTRL);
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK,
CLR_IIR_HISTORY | IIR_EN |
FIELD_PREP(IIR_STAGE_MASK, iir_stage));
} else {
/* disable IIR */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
IIR_EN, (unsigned long)~IIR_EN);
}
/* CON3 setting (RX OFS) */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3,
0x00FFFFFF, rx_frequency_palette(ofs));
/* CON4 setting (RX IFS) */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4,
0x00FFFFFF, rx_frequency_palette(ifs));
/* CON5 setting */
if (tracking) {
val = CALI_64_CYCLE |
CALI_AUTORST |
AUTO_TUNE_FREQ5 |
COMP_FREQ_RES |
CALI_BP_DGL |
CALI_AUTO_RESTART |
CALI_USE_FREQ_OUT |
CALI_SEL_01;
mask = CALI_CYCLE_MASK |
CALI_AUTORST |
AUTO_TUNE_FREQ5 |
COMP_FREQ_RES |
CALI_SEL_MASK |
CALI_BP_DGL |
AUTO_TUNE_FREQ4 |
CALI_AUTO_RESTART |
CALI_USE_FREQ_OUT |
CALI_ON;
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
mask, val);
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
CALI_ON, CALI_ON);
} else {
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
0xffffffff, 0x0);
}
/* CON6 setting fix 8125 */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6,
0x0000ffff, 0x1FBD);
/* CON9 setting (RX IFS) */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9,
0x000fffff, AutoRstThHi(ifs));
/* CON10 setting (RX IFS) */
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10,
0x000fffff, AutoRstThLo(ifs));
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
CHSET_STR_CLR, CHSET_STR_CLR);
return 0;
}
static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,
bool enable)
{
if (enable)
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
ASM_ON, ASM_ON);
else
regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
ASM_ON, (unsigned long)~ASM_ON);
return 0;
}
void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
{
int i;
unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data;
for (i = 0; i < DAI_I2S_NUM; i++) {
if (mt8365_i2s_priv[i].adda_link)
i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id];
}
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
if (enable) {
i2s_data->i2s_out_on_ref_cnt++;
if (i2s_data->i2s_out_on_ref_cnt == 1)
regmap_update_bits(afe->regmap, AFE_I2S_CON1,
0x1, enable);
} else {
i2s_data->i2s_out_on_ref_cnt--;
if (i2s_data->i2s_out_on_ref_cnt == 0)
regmap_update_bits(afe->regmap, AFE_I2S_CON1,
0x1, enable);
else if (i2s_data->i2s_out_on_ref_cnt < 0)
i2s_data->i2s_out_on_ref_cnt = 0;
}
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
}
static void mt8365_dai_set_enable(struct mtk_base_afe *afe,
struct mtk_afe_i2s_priv *i2s_data,
bool is_input, bool enable)
{
unsigned int reg_off;
if (is_input) {
reg_off = i2s_data->reg_off_in;
} else {
if (i2s_data->adda_link) {
mt8365_afe_set_i2s_out_enable(afe, enable);
return;
}
reg_off = i2s_data->reg_off_out;
}
regmap_update_bits(afe->regmap, reg_off,
0x1, enable);
}
static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
bool i2s_in_slave =
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBM_CFM);
mt8365_afe_enable_main_clk(afe);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_out]);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !i2s_in_slave)
clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_in]);
if (i2s_in_slave)
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
return 0;
}
static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
bool reset_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
bool reset_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
bool i2s_in_slave =
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBM_CFM);
if (be->prepared[substream->stream]) {
if (reset_i2s_out_change)
mt8365_dai_set_enable(afe, i2s_data, false, false);
if (reset_i2s_in_change)
mt8365_dai_set_enable(afe, i2s_data, true, false);
if (substream->runtime->rate % 8000)
mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
else
mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
if (reset_i2s_out_change)
be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false;
if (reset_i2s_in_change)
be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false;
}
if (reset_i2s_out_change)
mt8365_afe_disable_clk(afe,
afe_priv->clocks[i2s_data->clk_id_out]);
if (reset_i2s_in_change && !i2s_in_slave)
mt8365_afe_disable_clk(afe,
afe_priv->clocks[i2s_data->clk_id_in]);
if (i2s_in_slave)
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
bool apply_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
bool apply_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned int rate = substream->runtime->rate;
int bit_width = snd_pcm_format_width(substream->runtime->format);
int ret;
if (be->prepared[substream->stream]) {
dev_info(afe->dev, "%s '%s' prepared already\n",
__func__, snd_pcm_stream_str(substream));
return 0;
}
if (apply_i2s_out_change) {
ret = mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
if (ret)
return ret;
}
if (apply_i2s_in_change) {
if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
== SND_SOC_DAIFMT_CBM_CFM) {
ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate,
(unsigned int)bit_width,
0, 0, 1);
if (ret < 0)
return ret;
}
ret = mt8365_dai_set_config(afe, i2s_data, true, rate, bit_width);
if (ret)
return ret;
}
if (rate % 8000)
mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
else
mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
if (apply_i2s_out_change) {
mt8365_afe_set_clk_parent(afe,
afe_priv->clocks[i2s_data->clk_id_out_m_sel],
((rate % 8000) ?
afe_priv->clocks[MT8365_CLK_AUD1] :
afe_priv->clocks[MT8365_CLK_AUD2]));
mt8365_afe_set_clk_rate(afe,
afe_priv->clocks[i2s_data->clk_id_out],
rate * i2s_data->clk_out_mult);
mt8365_dai_set_enable(afe, i2s_data, false, true);
be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true;
}
if (apply_i2s_in_change) {
mt8365_afe_set_clk_parent(afe,
afe_priv->clocks[i2s_data->clk_id_in_m_sel],
((rate % 8000) ?
afe_priv->clocks[MT8365_CLK_AUD1] :
afe_priv->clocks[MT8365_CLK_AUD2]));
mt8365_afe_set_clk_rate(afe,
afe_priv->clocks[i2s_data->clk_id_in],
rate * i2s_data->clk_in_mult);
mt8365_dai_set_enable(afe, i2s_data, true, true);
if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
== SND_SOC_DAIFMT_CBM_CFM)
mt8365_afe_set_2nd_i2s_asrc_enable(afe, true);
be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true;
}
return 0;
}
static int mt8365_afe_2nd_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
unsigned int width_val = params_width(params) > 16 ?
(AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val);
return 0;
}
static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
be->fmt_mode = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
be->fmt_mode |= SND_SOC_DAIFMT_I2S;
break;
case SND_SOC_DAIFMT_LEFT_J:
be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J;
break;
default:
dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
return -EINVAL;
}
if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) &&
((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) &&
((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) &&
((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) {
dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
return -EINVAL;
}
be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK);
if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM))
be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK);
return 0;
}
static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = {
.startup = mt8365_dai_i2s_startup,
.shutdown = mt8365_dai_i2s_shutdown,
.prepare = mt8365_dai_i2s_prepare,
};
static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = {
.startup = mt8365_dai_i2s_startup,
.shutdown = mt8365_dai_i2s_shutdown,
.hw_params = mt8365_afe_2nd_i2s_hw_params,
.prepare = mt8365_dai_i2s_prepare,
.set_fmt = mt8365_afe_2nd_i2s_set_fmt,
};
static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
{
.name = "I2S",
.id = MT8365_AFE_IO_I2S,
.playback = {
.stream_name = "I2S Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "I2S Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_i2s_ops,
}, {
.name = "2ND I2S",
.id = MT8365_AFE_IO_2ND_I2S,
.playback = {
.stream_name = "2ND I2S Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "2ND I2S Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_afe_2nd_i2s_ops,
}
};
/* low jitter control */
static const char * const mt8365_i2s_hd_str[] = {
"Normal", "Low_Jitter"
};
static SOC_ENUM_SINGLE_EXT_DECL(mt8365_i2s_enum, mt8365_i2s_hd_str);
static const char * const fmi2sin_text[] = {
"OPEN", "FM_2ND_I2S_IN"
};
static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text);
static const struct snd_kcontrol_new fmi2sin_mux =
SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum);
static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl =
SOC_DAPM_SINGLE_VIRT("Switch", 1);
static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0,
&i2s_o03_o04_enable_ctl),
SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux),
SND_SOC_DAPM_INPUT("2ND I2S In"),
};
static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
{"I2S O03_O04", "Switch", "O03"},
{"I2S O03_O04", "Switch", "O04"},
{"I2S Playback", NULL, "I2S O03_O04"},
{"2ND I2S Playback", NULL, "O00"},
{"2ND I2S Playback", NULL, "O01"},
{"2ND I2S Capture", NULL, "2ND I2S In"},
{"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"},
};
static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe)
{
int i, ret;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
for (i = 0; i < DAI_I2S_NUM; i++) {
ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,
sizeof(*afe_priv),
&mt8365_i2s_priv[i]);
if (ret)
return ret;
}
return 0;
}
int mt8365_dai_i2s_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_i2s_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
dai->dapm_widgets = mtk_dai_i2s_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
dai->dapm_routes = mtk_dai_i2s_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
/* set all dai i2s private data */
return mt8365_dai_i2s_set_priv(afe);
}
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek 8365 ALSA SoC Audio DAI PCM Control
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"
struct mt8365_pcm_intf_data {
bool slave_mode;
bool lrck_inv;
bool bck_inv;
unsigned int format;
};
/* DAI Drivers */
static void mt8365_dai_enable_pcm1(struct mtk_base_afe *afe)
{
regmap_update_bits(afe->regmap, PCM_INTF_CON1,
PCM_INTF_CON1_EN, PCM_INTF_CON1_EN);
}
static void mt8365_dai_disable_pcm1(struct mtk_base_afe *afe)
{
regmap_update_bits(afe->regmap, PCM_INTF_CON1,
PCM_INTF_CON1_EN, 0x0);
}
static int mt8365_dai_configure_pcm1(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1];
bool slave_mode = pcm_priv->slave_mode;
bool lrck_inv = pcm_priv->lrck_inv;
bool bck_inv = pcm_priv->bck_inv;
unsigned int fmt = pcm_priv->format;
unsigned int bit_width = dai->sample_bits;
unsigned int val = 0;
if (!slave_mode) {
val |= PCM_INTF_CON1_MASTER_MODE |
PCM_INTF_CON1_BYPASS_ASRC;
if (lrck_inv)
val |= PCM_INTF_CON1_SYNC_OUT_INV;
if (bck_inv)
val |= PCM_INTF_CON1_BCLK_OUT_INV;
} else {
val |= PCM_INTF_CON1_SLAVE_MODE;
if (lrck_inv)
val |= PCM_INTF_CON1_SYNC_IN_INV;
if (bck_inv)
val |= PCM_INTF_CON1_BCLK_IN_INV;
/* TODO: add asrc setting */
}
val |= FIELD_PREP(PCM_INTF_CON1_FORMAT_MASK, fmt);
if (fmt == MT8365_PCM_FORMAT_PCMA ||
fmt == MT8365_PCM_FORMAT_PCMB)
val |= PCM_INTF_CON1_SYNC_LEN(1);
else
val |= PCM_INTF_CON1_SYNC_LEN(bit_width);
switch (substream->runtime->rate) {
case 48000:
val |= PCM_INTF_CON1_FS_48K;
break;
case 32000:
val |= PCM_INTF_CON1_FS_32K;
break;
case 16000:
val |= PCM_INTF_CON1_FS_16K;
break;
case 8000:
val |= PCM_INTF_CON1_FS_8K;
break;
default:
return -EINVAL;
}
if (bit_width > 16)
val |= PCM_INTF_CON1_24BIT | PCM_INTF_CON1_64BCK;
else
val |= PCM_INTF_CON1_16BIT | PCM_INTF_CON1_32BCK;
val |= PCM_INTF_CON1_EXT_MODEM;
regmap_update_bits(afe->regmap, PCM_INTF_CON1,
PCM_INTF_CON1_CONFIG_MASK, val);
return 0;
}
static int mt8365_dai_pcm1_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
if (snd_soc_dai_active(dai))
return 0;
mt8365_afe_enable_main_clk(afe);
return 0;
}
static void mt8365_dai_pcm1_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
if (snd_soc_dai_active(dai))
return;
mt8365_dai_disable_pcm1(afe);
mt8365_afe_disable_main_clk(afe);
}
static int mt8365_dai_pcm1_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int ret;
if ((snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) +
snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) > 1) {
dev_info(afe->dev, "%s '%s' active(%u-%u) already\n",
__func__, snd_pcm_stream_str(substream),
snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK),
snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE));
return 0;
}
ret = mt8365_dai_configure_pcm1(substream, dai);
if (ret)
return ret;
mt8365_dai_enable_pcm1(afe);
return 0;
}
static int mt8365_dai_pcm1_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1];
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
pcm_priv->format = MT8365_PCM_FORMAT_I2S;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
pcm_priv->bck_inv = false;
pcm_priv->lrck_inv = false;
break;
case SND_SOC_DAIFMT_NB_IF:
pcm_priv->bck_inv = false;
pcm_priv->lrck_inv = true;
break;
case SND_SOC_DAIFMT_IB_NF:
pcm_priv->bck_inv = true;
pcm_priv->lrck_inv = false;
break;
case SND_SOC_DAIFMT_IB_IF:
pcm_priv->bck_inv = true;
pcm_priv->lrck_inv = true;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
pcm_priv->slave_mode = true;
break;
case SND_SOC_DAIFMT_CBS_CFS:
pcm_priv->slave_mode = false;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dai_ops mt8365_dai_pcm1_ops = {
.startup = mt8365_dai_pcm1_startup,
.shutdown = mt8365_dai_pcm1_shutdown,
.prepare = mt8365_dai_pcm1_prepare,
.set_fmt = mt8365_dai_pcm1_set_fmt,
};
static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
{
.name = "PCM1",
.id = MT8365_AFE_IO_PCM1,
.playback = {
.stream_name = "PCM1 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "PCM1 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &mt8365_dai_pcm1_ops,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
}
};
/* DAI widget */
static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
SND_SOC_DAPM_OUTPUT("PCM1 Out"),
SND_SOC_DAPM_INPUT("PCM1 In"),
};
/* DAI route */
static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
{"PCM1 Playback", NULL, "O07"},
{"PCM1 Playback", NULL, "O08"},
{"PCM1 Out", NULL, "PCM1 Playback"},
{"I09", NULL, "PCM1 Capture"},
{"I22", NULL, "PCM1 Capture"},
{"PCM1 Capture", NULL, "PCM1 In"},
};
static int init_pcmif_priv_data(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mt8365_pcm_intf_data *pcmif_priv;
pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mt8365_pcm_intf_data),
GFP_KERNEL);
if (!pcmif_priv)
return -ENOMEM;
afe_priv->dai_priv[MT8365_AFE_IO_PCM1] = pcmif_priv;
return 0;
}
int mt8365_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;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_pcm_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
dai->dapm_widgets = mtk_dai_pcm_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
dai->dapm_routes = mtk_dai_pcm_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
return init_pcmif_priv_data(afe);
}
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek MT8365 Sound Card driver
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Nicolas Belin <nbelin@baylibre.com>
*/
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-common.h"
#include <linux/pinctrl/consumer.h>
#include "../common/mtk-soc-card.h"
#include "../common/mtk-soundcard-driver.h"
enum pinctrl_pin_state {
PIN_STATE_DEFAULT,
PIN_STATE_DMIC,
PIN_STATE_MISO_OFF,
PIN_STATE_MISO_ON,
PIN_STATE_MOSI_OFF,
PIN_STATE_MOSI_ON,
PIN_STATE_MAX
};
static const char * const mt8365_mt6357_pin_str[PIN_STATE_MAX] = {
"default",
"dmic",
"miso_off",
"miso_on",
"mosi_off",
"mosi_on",
};
struct mt8365_mt6357_priv {
struct pinctrl *pinctrl;
struct pinctrl_state *pin_states[PIN_STATE_MAX];
};
enum {
/* FE */
DAI_LINK_DL1_PLAYBACK = 0,
DAI_LINK_DL2_PLAYBACK,
DAI_LINK_AWB_CAPTURE,
DAI_LINK_VUL_CAPTURE,
/* BE */
DAI_LINK_2ND_I2S_INTF,
DAI_LINK_DMIC,
DAI_LINK_INT_ADDA,
DAI_LINK_NUM
};
static const struct snd_soc_dapm_widget mt8365_mt6357_widgets[] = {
SND_SOC_DAPM_OUTPUT("HDMI Out"),
};
static const struct snd_soc_dapm_route mt8365_mt6357_routes[] = {
{"HDMI Out", NULL, "2ND I2S Playback"},
{"DMIC In", NULL, "MICBIAS0"},
};
static int mt8365_mt6357_int_adda_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
int ret = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_ON]))
return ret;
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[PIN_STATE_MOSI_ON]);
if (ret)
dev_err(rtd->card->dev, "%s failed to select state %d\n",
__func__, ret);
}
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (IS_ERR(priv->pin_states[PIN_STATE_MISO_ON]))
return ret;
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[PIN_STATE_MISO_ON]);
if (ret)
dev_err(rtd->card->dev, "%s failed to select state %d\n",
__func__, ret);
}
return 0;
}
static void mt8365_mt6357_int_adda_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
int ret = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_OFF]))
return;
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[PIN_STATE_MOSI_OFF]);
if (ret)
dev_err(rtd->card->dev, "%s failed to select state %d\n",
__func__, ret);
}
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (IS_ERR(priv->pin_states[PIN_STATE_MISO_OFF]))
return;
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[PIN_STATE_MISO_OFF]);
if (ret)
dev_err(rtd->card->dev, "%s failed to select state %d\n",
__func__, ret);
}
}
static const struct snd_soc_ops mt8365_mt6357_int_adda_ops = {
.startup = mt8365_mt6357_int_adda_startup,
.shutdown = mt8365_mt6357_int_adda_shutdown,
};
SND_SOC_DAILINK_DEFS(playback1,
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback2,
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(awb_capture,
DAILINK_COMP_ARRAY(COMP_CPU("AWB")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(vul,
DAILINK_COMP_ARRAY(COMP_CPU("VUL")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s3,
DAILINK_COMP_ARRAY(COMP_CPU("2ND I2S")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(dmic,
DAILINK_COMP_ARRAY(COMP_CPU("DMIC")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(primary_codec,
DAILINK_COMP_ARRAY(COMP_CPU("INT ADDA")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6357-sound", "mt6357-snd-codec-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
/* Front End DAI links */
[DAI_LINK_DL1_PLAYBACK] = {
.name = "DL1_FE",
.stream_name = "MultiMedia1_PLayback",
.id = DAI_LINK_DL1_PLAYBACK,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(playback1),
},
[DAI_LINK_DL2_PLAYBACK] = {
.name = "DL2_FE",
.stream_name = "MultiMedia2_PLayback",
.id = DAI_LINK_DL2_PLAYBACK,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(playback2),
},
[DAI_LINK_AWB_CAPTURE] = {
.name = "AWB_FE",
.stream_name = "DL1_AWB_Record",
.id = DAI_LINK_AWB_CAPTURE,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
.dpcm_capture = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(awb_capture),
},
[DAI_LINK_VUL_CAPTURE] = {
.name = "VUL_FE",
.stream_name = "MultiMedia1_Capture",
.id = DAI_LINK_VUL_CAPTURE,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
.dpcm_capture = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(vul),
},
/* Back End DAI links */
[DAI_LINK_2ND_I2S_INTF] = {
.name = "I2S_OUT_BE",
.no_pcm = 1,
.id = DAI_LINK_2ND_I2S_INTF,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.dpcm_playback = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(i2s3),
},
[DAI_LINK_DMIC] = {
.name = "DMIC_BE",
.no_pcm = 1,
.id = DAI_LINK_DMIC,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(dmic),
},
[DAI_LINK_INT_ADDA] = {
.name = "MTK_Codec",
.no_pcm = 1,
.id = DAI_LINK_INT_ADDA,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ops = &mt8365_mt6357_int_adda_ops,
SND_SOC_DAILINK_REG(primary_codec),
},
};
static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card)
{
struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card);
int ret, i;
priv->pinctrl = devm_pinctrl_get(card->dev);
if (IS_ERR(priv->pinctrl)) {
ret = PTR_ERR(priv->pinctrl);
return dev_err_probe(card->dev, ret,
"Failed to get pinctrl\n");
}
for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) {
priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
mt8365_mt6357_pin_str[i]);
if (IS_ERR(priv->pin_states[i])) {
ret = PTR_ERR(priv->pin_states[i]);
dev_warn(card->dev, "No pin state for %s\n",
mt8365_mt6357_pin_str[i]);
} else {
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[i]);
if (ret) {
dev_err_probe(card->dev, ret,
"Failed to select pin state %s\n",
mt8365_mt6357_pin_str[i]);
return ret;
}
}
}
return 0;
}
static struct snd_soc_card mt8365_mt6357_soc_card = {
.name = "mt8365-evk",
.owner = THIS_MODULE,
.dai_link = mt8365_mt6357_dais,
.num_links = ARRAY_SIZE(mt8365_mt6357_dais),
.dapm_widgets = mt8365_mt6357_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8365_mt6357_widgets),
.dapm_routes = mt8365_mt6357_routes,
.num_dapm_routes = ARRAY_SIZE(mt8365_mt6357_routes),
};
static int mt8365_mt6357_dev_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
{
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct device *dev = card->dev;
struct device_node *platform_node;
struct mt8365_mt6357_priv *mach_priv;
int i, ret;
card->dev = dev;
ret = parse_dai_link_info(card);
if (ret)
goto err;
mach_priv = devm_kzalloc(dev, sizeof(*mach_priv),
GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
soc_card_data->mach_priv = mach_priv;
snd_soc_card_set_drvdata(card, soc_card_data);
mt8365_mt6357_gpio_probe(card);
return 0;
err:
clean_card_reference(card);
return ret;
}
static const struct mtk_soundcard_pdata mt8365_mt6357_card = {
.card_name = "mt8365-mt6357",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8365_mt6357_soc_card,
},
.soc_probe = mt8365_mt6357_dev_probe
};
static const struct of_device_id mt8365_mt6357_dt_match[] = {
{ .compatible = "mediatek,mt8365-mt6357", .data = &mt8365_mt6357_card },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mt8365_mt6357_dt_match);
static struct platform_driver mt8365_mt6357_driver = {
.driver = {
.name = "mt8365_mt6357",
.of_match_table = mt8365_mt6357_dt_match,
.pm = &snd_soc_pm_ops,
},
.probe = mtk_soundcard_common_probe,
};
module_platform_driver(mt8365_mt6357_driver);
/* Module information */
MODULE_DESCRIPTION("MT8365 EVK SoC machine driver");
MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform: mt8365_mt6357");
/* SPDX-License-Identifier: GPL-2.0
*
* MediaTek 8365 audio driver reg definition
*
* Copyright (c) 2024 MediaTek Inc.
* Authors: Jia Zeng <jia.zeng@mediatek.com>
* Alexandre Mergnat <amergnat@baylibre.com>
*/
#ifndef _MT8365_REG_H_
#define _MT8365_REG_H_
#define AUDIO_TOP_CON0 (0x0000)
#define AUDIO_TOP_CON1 (0x0004)
#define AUDIO_TOP_CON2 (0x0008)
#define AUDIO_TOP_CON3 (0x000c)
#define AFE_DAC_CON0 (0x0010)
#define AFE_DAC_CON1 (0x0014)
#define AFE_I2S_CON (0x0018)
#define AFE_CONN0 (0x0020)
#define AFE_CONN1 (0x0024)
#define AFE_CONN2 (0x0028)
#define AFE_CONN3 (0x002c)
#define AFE_CONN4 (0x0030)
#define AFE_I2S_CON1 (0x0034)
#define AFE_I2S_CON2 (0x0038)
#define AFE_MRGIF_CON (0x003c)
#define AFE_DL1_BASE (0x0040)
#define AFE_DL1_CUR (0x0044)
#define AFE_DL1_END (0x0048)
#define AFE_I2S_CON3 (0x004c)
#define AFE_DL2_BASE (0x0050)
#define AFE_DL2_CUR (0x0054)
#define AFE_DL2_END (0x0058)
#define AFE_CONN5 (0x005c)
#define AFE_AWB_BASE (0x0070)
#define AFE_AWB_END (0x0078)
#define AFE_AWB_CUR (0x007c)
#define AFE_VUL_BASE (0x0080)
#define AFE_VUL_END (0x0088)
#define AFE_VUL_CUR (0x008c)
#define AFE_CONN6 (0x00bc)
#define AFE_MEMIF_MSB (0x00cc)
#define AFE_MEMIF_MON0 (0x00d0)
#define AFE_MEMIF_MON1 (0x00d4)
#define AFE_MEMIF_MON2 (0x00d8)
#define AFE_MEMIF_MON3 (0x00dc)
#define AFE_MEMIF_MON4 (0x00e0)
#define AFE_MEMIF_MON5 (0x00e4)
#define AFE_MEMIF_MON6 (0x00e8)
#define AFE_MEMIF_MON7 (0x00ec)
#define AFE_MEMIF_MON8 (0x00f0)
#define AFE_MEMIF_MON9 (0x00f4)
#define AFE_MEMIF_MON10 (0x00f8)
#define AFE_MEMIF_MON11 (0x00fc)
#define AFE_ADDA_DL_SRC2_CON0 (0x0108)
#define AFE_ADDA_DL_SRC2_CON1 (0x010c)
#define AFE_ADDA_UL_SRC_CON0 (0x0114)
#define AFE_ADDA_UL_SRC_CON1 (0x0118)
#define AFE_ADDA_TOP_CON0 (0x0120)
#define AFE_ADDA_UL_DL_CON0 (0x0124)
#define AFE_ADDA_SRC_DEBUG (0x012c)
#define AFE_ADDA_SRC_DEBUG_MON0 (0x0130)
#define AFE_ADDA_SRC_DEBUG_MON1 (0x0134)
#define AFE_ADDA_UL_SRC_MON0 (0x0148)
#define AFE_ADDA_UL_SRC_MON1 (0x014c)
#define AFE_SRAM_BOUND (0x0170)
#define AFE_SECURE_CON (0x0174)
#define AFE_SECURE_CONN0 (0x0178)
#define AFE_SIDETONE_DEBUG (0x01d0)
#define AFE_SIDETONE_MON (0x01d4)
#define AFE_SIDETONE_CON0 (0x01e0)
#define AFE_SIDETONE_COEFF (0x01e4)
#define AFE_SIDETONE_CON1 (0x01e8)
#define AFE_SIDETONE_GAIN (0x01ec)
#define AFE_SGEN_CON0 (0x01f0)
#define AFE_SINEGEN_CON_TDM (0x01f8)
#define AFE_SINEGEN_CON_TDM_IN (0x01fc)
#define AFE_TOP_CON0 (0x0200)
#define AFE_BUS_CFG (0x0240)
#define AFE_BUS_MON0 (0x0244)
#define AFE_ADDA_PREDIS_CON0 (0x0260)
#define AFE_ADDA_PREDIS_CON1 (0x0264)
#define AFE_CONN_MON0 (0x0280)
#define AFE_CONN_MON1 (0x0284)
#define AFE_CONN_MON2 (0x0288)
#define AFE_CONN_MON3 (0x028c)
#define AFE_ADDA_IIR_COEF_02_01 (0x0290)
#define AFE_ADDA_IIR_COEF_04_03 (0x0294)
#define AFE_ADDA_IIR_COEF_06_05 (0x0298)
#define AFE_ADDA_IIR_COEF_08_07 (0x029c)
#define AFE_ADDA_IIR_COEF_10_09 (0x02a0)
#define AFE_VUL_D2_BASE (0x0350)
#define AFE_VUL_D2_END (0x0358)
#define AFE_VUL_D2_CUR (0x035c)
#define AFE_HDMI_OUT_CON0 (0x0370)
#define AFE_HDMI_OUT_BASE (0x0374)
#define AFE_HDMI_OUT_CUR (0x0378)
#define AFE_HDMI_OUT_END (0x037c)
#define AFE_SPDIF_OUT_CON0 (0x0380)
#define AFE_SPDIF_OUT_BASE (0x0384)
#define AFE_SPDIF_OUT_CUR (0x0388)
#define AFE_SPDIF_OUT_END (0x038c)
#define AFE_HDMI_CONN0 (0x0390)
#define AFE_HDMI_CONN1 (0x0398)
#define AFE_CONN_TDMIN_CON (0x039c)
#define AFE_IRQ_MCU_CON (0x03a0)
#define AFE_IRQ_MCU_STATUS (0x03a4)
#define AFE_IRQ_MCU_CLR (0x03a8)
#define AFE_IRQ_MCU_CNT1 (0x03ac)
#define AFE_IRQ_MCU_CNT2 (0x03b0)
#define AFE_IRQ_MCU_EN (0x03b4)
#define AFE_IRQ_MCU_MON2 (0x03b8)
#define AFE_IRQ_MCU_CNT5 (0x03bc)
#define AFE_IRQ1_MCU_CNT_MON (0x03c0)
#define AFE_IRQ2_MCU_CNT_MON (0x03c4)
#define AFE_IRQ1_MCU_EN_CNT_MON (0x03c8)
#define AFE_IRQ5_MCU_CNT_MON (0x03cc)
#define AFE_MEMIF_MINLEN (0x03d0)
#define AFE_MEMIF_MAXLEN (0x03d4)
#define AFE_MEMIF_PBUF_SIZE (0x03d8)
#define AFE_IRQ_MCU_CNT7 (0x03dc)
#define AFE_IRQ7_MCU_CNT_MON (0x03e0)
#define AFE_MEMIF_PBUF2_SIZE (0x03ec)
#define AFE_APLL_TUNER_CFG (0x03f0)
#define AFE_APLL_TUNER_CFG1 (0x03f4)
#define AFE_IRQ_MCU_CON2 (0x03f8)
#define IRQ13_MCU_CNT (0x0408)
#define IRQ13_MCU_CNT_MON (0x040c)
#define AFE_GAIN1_CON0 (0x0410)
#define AFE_GAIN1_CON1 (0x0414)
#define AFE_GAIN1_CON2 (0x0418)
#define AFE_GAIN1_CON3 (0x041c)
#define AFE_GAIN2_CON0 (0x0428)
#define AFE_GAIN2_CON1 (0x042c)
#define AFE_GAIN2_CON2 (0x0430)
#define AFE_GAIN2_CON3 (0x0434)
#define AFE_GAIN2_CUR (0x043c)
#define AFE_CONN11 (0x0448)
#define AFE_CONN12 (0x044c)
#define AFE_CONN13 (0x0450)
#define AFE_CONN14 (0x0454)
#define AFE_CONN15 (0x0458)
#define AFE_CONN16 (0x045c)
#define AFE_CONN7 (0x0460)
#define AFE_CONN8 (0x0464)
#define AFE_CONN9 (0x0468)
#define AFE_CONN10 (0x046c)
#define AFE_CONN21 (0x0470)
#define AFE_CONN22 (0x0474)
#define AFE_CONN23 (0x0478)
#define AFE_CONN24 (0x047c)
#define AFE_IEC_CFG (0x0480)
#define AFE_IEC_NSNUM (0x0484)
#define AFE_IEC_BURST_INFO (0x0488)
#define AFE_IEC_BURST_LEN (0x048c)
#define AFE_IEC_NSADR (0x0490)
#define AFE_CONN_RS (0x0494)
#define AFE_CONN_DI (0x0498)
#define AFE_IEC_CHL_STAT0 (0x04a0)
#define AFE_IEC_CHL_STAT1 (0x04a4)
#define AFE_IEC_CHR_STAT0 (0x04a8)
#define AFE_IEC_CHR_STAT1 (0x04ac)
#define AFE_CONN25 (0x04b0)
#define AFE_CONN26 (0x04b4)
#define FPGA_CFG2 (0x04b8)
#define FPGA_CFG3 (0x04bc)
#define FPGA_CFG0 (0x04c0)
#define FPGA_CFG1 (0x04c4)
#define AFE_SRAM_DELSEL_CON0 (0x04f0)
#define AFE_SRAM_DELSEL_CON1 (0x04f4)
#define AFE_SRAM_DELSEL_CON2 (0x04f8)
#define FPGA_CFG4 (0x04fc)
#define AFE_TDM_GASRC4_ASRC_2CH_CON0 (0x0500)
#define AFE_TDM_GASRC4_ASRC_2CH_CON1 (0x0504)
#define AFE_TDM_GASRC4_ASRC_2CH_CON2 (0x0508)
#define AFE_TDM_GASRC4_ASRC_2CH_CON3 (0x050c)
#define AFE_TDM_GASRC4_ASRC_2CH_CON4 (0x0510)
#define AFE_TDM_GASRC4_ASRC_2CH_CON5 (0x0514)
#define AFE_TDM_GASRC4_ASRC_2CH_CON6 (0x0518)
#define AFE_TDM_GASRC4_ASRC_2CH_CON7 (0x051c)
#define AFE_TDM_GASRC4_ASRC_2CH_CON8 (0x0520)
#define AFE_TDM_GASRC4_ASRC_2CH_CON9 (0x0524)
#define AFE_TDM_GASRC4_ASRC_2CH_CON10 (0x0528)
#define AFE_TDM_GASRC4_ASRC_2CH_CON12 (0x0530)
#define AFE_TDM_GASRC4_ASRC_2CH_CON13 (0x0534)
#define PCM_INTF_CON2 (0x0538)
#define PCM2_INTF_CON (0x053c)
#define AFE_APB_MON (0x0540)
#define AFE_CONN34 (0x0544)
#define AFE_TDM_CON1 (0x0548)
#define AFE_TDM_CON2 (0x054c)
#define PCM_INTF_CON1 (0x0550)
#define AFE_SECURE_MASK_CONN47_1 (0x0554)
#define AFE_SECURE_MASK_CONN48_1 (0x0558)
#define AFE_SECURE_MASK_CONN49_1 (0x055c)
#define AFE_SECURE_MASK_CONN50_1 (0x0560)
#define AFE_SECURE_MASK_CONN51_1 (0x0564)
#define AFE_SECURE_MASK_CONN52_1 (0x0568)
#define AFE_SECURE_MASK_CONN53_1 (0x056c)
#define AFE_SE_SECURE_CON (0x0570)
#define AFE_TDM_IN_CON1 (0x0588)
#define AFE_TDM_IN_CON2 (0x058c)
#define AFE_TDM_IN_MON1 (0x0590)
#define AFE_TDM_IN_MON2 (0x0594)
#define AFE_TDM_IN_MON3 (0x0598)
#define AFE_DMIC0_UL_SRC_CON0 (0x05b4)
#define AFE_DMIC0_UL_SRC_CON1 (0x05b8)
#define AFE_DMIC0_SRC_DEBUG (0x05bc)
#define AFE_DMIC0_SRC_DEBUG_MON0 (0x05c0)
#define AFE_DMIC0_UL_SRC_MON0 (0x05c8)
#define AFE_DMIC0_UL_SRC_MON1 (0x05cc)
#define AFE_DMIC0_IIR_COEF_02_01 (0x05d0)
#define AFE_DMIC0_IIR_COEF_04_03 (0x05d4)
#define AFE_DMIC0_IIR_COEF_06_05 (0x05d8)
#define AFE_DMIC0_IIR_COEF_08_07 (0x05dc)
#define AFE_DMIC0_IIR_COEF_10_09 (0x05e0)
#define AFE_DMIC1_UL_SRC_CON0 (0x0620)
#define AFE_DMIC1_UL_SRC_CON1 (0x0624)
#define AFE_DMIC1_SRC_DEBUG (0x0628)
#define AFE_DMIC1_SRC_DEBUG_MON0 (0x062c)
#define AFE_DMIC1_UL_SRC_MON0 (0x0634)
#define AFE_DMIC1_UL_SRC_MON1 (0x0638)
#define AFE_DMIC1_IIR_COEF_02_01 (0x063c)
#define AFE_DMIC1_IIR_COEF_04_03 (0x0640)
#define AFE_DMIC1_IIR_COEF_06_05 (0x0644)
#define AFE_DMIC1_IIR_COEF_08_07 (0x0648)
#define AFE_DMIC1_IIR_COEF_10_09 (0x064c)
#define AFE_SECURE_MASK_CONN39_1 (0x068c)
#define AFE_SECURE_MASK_CONN40_1 (0x0690)
#define AFE_SECURE_MASK_CONN41_1 (0x0694)
#define AFE_SECURE_MASK_CONN42_1 (0x0698)
#define AFE_SECURE_MASK_CONN43_1 (0x069c)
#define AFE_SECURE_MASK_CONN44_1 (0x06a0)
#define AFE_SECURE_MASK_CONN45_1 (0x06a4)
#define AFE_SECURE_MASK_CONN46_1 (0x06a8)
#define AFE_TDM_GASRC1_ASRC_2CH_CON0 (0x06c0)
#define AFE_TDM_GASRC1_ASRC_2CH_CON1 (0x06c4)
#define AFE_TDM_GASRC1_ASRC_2CH_CON2 (0x06c8)
#define AFE_TDM_GASRC1_ASRC_2CH_CON3 (0x06cc)
#define AFE_TDM_GASRC1_ASRC_2CH_CON4 (0x06d0)
#define AFE_TDM_GASRC1_ASRC_2CH_CON5 (0x06d4)
#define AFE_TDM_GASRC1_ASRC_2CH_CON6 (0x06d8)
#define AFE_TDM_GASRC1_ASRC_2CH_CON7 (0x06dc)
#define AFE_TDM_GASRC1_ASRC_2CH_CON8 (0x06e0)
#define AFE_TDM_GASRC1_ASRC_2CH_CON9 (0x06e4)
#define AFE_TDM_GASRC1_ASRC_2CH_CON10 (0x06e8)
#define AFE_TDM_GASRC1_ASRC_2CH_CON12 (0x06f0)
#define AFE_TDM_GASRC1_ASRC_2CH_CON13 (0x06f4)
#define AFE_TDM_ASRC_CON0 (0x06f8)
#define AFE_TDM_GASRC2_ASRC_2CH_CON0 (0x0700)
#define AFE_TDM_GASRC2_ASRC_2CH_CON1 (0x0704)
#define AFE_TDM_GASRC2_ASRC_2CH_CON2 (0x0708)
#define AFE_TDM_GASRC2_ASRC_2CH_CON3 (0x070c)
#define AFE_TDM_GASRC2_ASRC_2CH_CON4 (0x0710)
#define AFE_TDM_GASRC2_ASRC_2CH_CON5 (0x0714)
#define AFE_TDM_GASRC2_ASRC_2CH_CON6 (0x0718)
#define AFE_TDM_GASRC2_ASRC_2CH_CON7 (0x071c)
#define AFE_TDM_GASRC2_ASRC_2CH_CON8 (0x0720)
#define AFE_TDM_GASRC2_ASRC_2CH_CON9 (0x0724)
#define AFE_TDM_GASRC2_ASRC_2CH_CON10 (0x0728)
#define AFE_TDM_GASRC2_ASRC_2CH_CON12 (0x0730)
#define AFE_TDM_GASRC2_ASRC_2CH_CON13 (0x0734)
#define AFE_TDM_GASRC3_ASRC_2CH_CON0 (0x0740)
#define AFE_TDM_GASRC3_ASRC_2CH_CON1 (0x0744)
#define AFE_TDM_GASRC3_ASRC_2CH_CON2 (0x0748)
#define AFE_TDM_GASRC3_ASRC_2CH_CON3 (0x074c)
#define AFE_TDM_GASRC3_ASRC_2CH_CON4 (0x0750)
#define AFE_TDM_GASRC3_ASRC_2CH_CON5 (0x0754)
#define AFE_TDM_GASRC3_ASRC_2CH_CON6 (0x0758)
#define AFE_TDM_GASRC3_ASRC_2CH_CON7 (0x075c)
#define AFE_TDM_GASRC3_ASRC_2CH_CON8 (0x0760)
#define AFE_TDM_GASRC3_ASRC_2CH_CON9 (0x0764)
#define AFE_TDM_GASRC3_ASRC_2CH_CON10 (0x0768)
#define AFE_TDM_GASRC3_ASRC_2CH_CON12 (0x0770)
#define AFE_TDM_GASRC3_ASRC_2CH_CON13 (0x0774)
#define AFE_DMIC2_UL_SRC_CON0 (0x0780)
#define AFE_DMIC2_UL_SRC_CON1 (0x0784)
#define AFE_DMIC2_SRC_DEBUG (0x0788)
#define AFE_DMIC2_SRC_DEBUG_MON0 (0x078c)
#define AFE_DMIC2_UL_SRC_MON0 (0x0794)
#define AFE_DMIC2_UL_SRC_MON1 (0x0798)
#define AFE_DMIC2_IIR_COEF_02_01 (0x079c)
#define AFE_DMIC2_IIR_COEF_04_03 (0x07a0)
#define AFE_DMIC2_IIR_COEF_06_05 (0x07a4)
#define AFE_DMIC2_IIR_COEF_08_07 (0x07a8)
#define AFE_DMIC2_IIR_COEF_10_09 (0x07ac)
#define AFE_DMIC3_UL_SRC_CON0 (0x07ec)
#define AFE_DMIC3_UL_SRC_CON1 (0x07f0)
#define AFE_DMIC3_SRC_DEBUG (0x07f4)
#define AFE_DMIC3_SRC_DEBUG_MON0 (0x07f8)
#define AFE_DMIC3_UL_SRC_MON0 (0x0800)
#define AFE_DMIC3_UL_SRC_MON1 (0x0804)
#define AFE_DMIC3_IIR_COEF_02_01 (0x0808)
#define AFE_DMIC3_IIR_COEF_04_03 (0x080c)
#define AFE_DMIC3_IIR_COEF_06_05 (0x0810)
#define AFE_DMIC3_IIR_COEF_08_07 (0x0814)
#define AFE_DMIC3_IIR_COEF_10_09 (0x0818)
#define AFE_SECURE_MASK_CONN25_1 (0x0858)
#define AFE_SECURE_MASK_CONN26_1 (0x085c)
#define AFE_SECURE_MASK_CONN27_1 (0x0860)
#define AFE_SECURE_MASK_CONN28_1 (0x0864)
#define AFE_SECURE_MASK_CONN29_1 (0x0868)
#define AFE_SECURE_MASK_CONN30_1 (0x086c)
#define AFE_SECURE_MASK_CONN31_1 (0x0870)
#define AFE_SECURE_MASK_CONN32_1 (0x0874)
#define AFE_SECURE_MASK_CONN33_1 (0x0878)
#define AFE_SECURE_MASK_CONN34_1 (0x087c)
#define AFE_SECURE_MASK_CONN35_1 (0x0880)
#define AFE_SECURE_MASK_CONN36_1 (0x0884)
#define AFE_SECURE_MASK_CONN37_1 (0x0888)
#define AFE_SECURE_MASK_CONN38_1 (0x088c)
#define AFE_IRQ_MCU_SCP_EN (0x0890)
#define AFE_IRQ_MCU_DSP_EN (0x0894)
#define AFE_IRQ3_MCU_CNT_MON (0x0898)
#define AFE_IRQ4_MCU_CNT_MON (0x089c)
#define AFE_IRQ8_MCU_CNT_MON (0x08a0)
#define AFE_IRQ_MCU_CNT3 (0x08a4)
#define AFE_IRQ_MCU_CNT4 (0x08a8)
#define AFE_IRQ_MCU_CNT8 (0x08ac)
#define AFE_IRQ_MCU_CNT11 (0x08b0)
#define AFE_IRQ_MCU_CNT12 (0x08b4)
#define AFE_IRQ11_MCU_CNT_MON (0x08b8)
#define AFE_IRQ12_MCU_CNT_MON (0x08bc)
#define AFE_VUL3_BASE (0x08c0)
#define AFE_VUL3_CUR (0x08c4)
#define AFE_VUL3_END (0x08c8)
#define AFE_VUL3_BASE_MSB (0x08d0)
#define AFE_VUL3_END_MSB (0x08d4)
#define AFE_IRQ10_MCU_CNT_MON (0x08d8)
#define AFE_IRQ_MCU_CNT10 (0x08dc)
#define AFE_IRQ_ACC1_CNT (0x08e0)
#define AFE_IRQ_ACC2_CNT (0x08e4)
#define AFE_IRQ_ACC1_CNT_MON1 (0x08e8)
#define AFE_IRQ_ACC2_CNT_MON (0x08ec)
#define AFE_TSF_CON (0x08f0)
#define AFE_TSF_MON (0x08f4)
#define AFE_IRQ_ACC1_CNT_MON2 (0x08f8)
#define AFE_SPDIFIN_CFG0 (0x0900)
#define AFE_SPDIFIN_CFG1 (0x0904)
#define AFE_SPDIFIN_CHSTS1 (0x0908)
#define AFE_SPDIFIN_CHSTS2 (0x090c)
#define AFE_SPDIFIN_CHSTS3 (0x0910)
#define AFE_SPDIFIN_CHSTS4 (0x0914)
#define AFE_SPDIFIN_CHSTS5 (0x0918)
#define AFE_SPDIFIN_CHSTS6 (0x091c)
#define AFE_SPDIFIN_DEBUG1 (0x0920)
#define AFE_SPDIFIN_DEBUG2 (0x0924)
#define AFE_SPDIFIN_DEBUG3 (0x0928)
#define AFE_SPDIFIN_DEBUG4 (0x092c)
#define AFE_SPDIFIN_EC (0x0930)
#define AFE_SPDIFIN_CKLOCK_CFG (0x0934)
#define AFE_SPDIFIN_BR (0x093c)
#define AFE_SPDIFIN_BR_DBG1 (0x0940)
#define AFE_SPDIFIN_INT_EXT (0x0948)
#define AFE_SPDIFIN_INT_EXT2 (0x094c)
#define SPDIFIN_FREQ_INFO (0x0950)
#define SPDIFIN_FREQ_INFO_2 (0x0954)
#define SPDIFIN_FREQ_INFO_3 (0x0958)
#define SPDIFIN_FREQ_STATUS (0x095c)
#define SPDIFIN_USERCODE1 (0x0960)
#define SPDIFIN_USERCODE2 (0x0964)
#define SPDIFIN_USERCODE3 (0x0968)
#define SPDIFIN_USERCODE4 (0x096c)
#define SPDIFIN_USERCODE5 (0x0970)
#define SPDIFIN_USERCODE6 (0x0974)
#define SPDIFIN_USERCODE7 (0x0978)
#define SPDIFIN_USERCODE8 (0x097c)
#define SPDIFIN_USERCODE9 (0x0980)
#define SPDIFIN_USERCODE10 (0x0984)
#define SPDIFIN_USERCODE11 (0x0988)
#define SPDIFIN_USERCODE12 (0x098c)
#define SPDIFIN_MEMIF_CON0 (0x0990)
#define SPDIFIN_BASE_ADR (0x0994)
#define SPDIFIN_END_ADR (0x0998)
#define SPDIFIN_APLL_TUNER_CFG (0x09a0)
#define SPDIFIN_APLL_TUNER_CFG1 (0x09a4)
#define SPDIFIN_APLL2_TUNER_CFG (0x09a8)
#define SPDIFIN_APLL2_TUNER_CFG1 (0x09ac)
#define SPDIFIN_TYPE_DET (0x09b0)
#define MPHONE_MULTI_CON0 (0x09b4)
#define SPDIFIN_CUR_ADR (0x09b8)
#define AFE_SINEGEN_CON_SPDIFIN (0x09bc)
#define AFE_HDMI_IN_2CH_CON0 (0x09c0)
#define AFE_HDMI_IN_2CH_BASE (0x09c4)
#define AFE_HDMI_IN_2CH_END (0x09c8)
#define AFE_HDMI_IN_2CH_CUR (0x09cc)
#define AFE_MEMIF_BUF_MON0 (0x09d0)
#define AFE_MEMIF_BUF_MON1 (0x09d4)
#define AFE_MEMIF_BUF_MON2 (0x09d8)
#define AFE_MEMIF_BUF_MON3 (0x09dc)
#define AFE_MEMIF_BUF_MON6 (0x09e8)
#define AFE_MEMIF_BUF_MON7 (0x09ec)
#define AFE_MEMIF_BUF_MON8 (0x09f0)
#define AFE_MEMIF_BUF_MON10 (0x09f8)
#define AFE_MEMIF_BUF_MON11 (0x09fc)
#define SYSTOP_STC_CONFIG (0x0a00)
#define AUDIO_STC_STATUS (0x0a04)
#define SYSTOP_W_STC_H (0x0a08)
#define SYSTOP_W_STC_L (0x0a0c)
#define SYSTOP_R_STC_H (0x0a10)
#define SYSTOP_R_STC_L (0x0a14)
#define AUDIO_W_STC_H (0x0a18)
#define AUDIO_W_STC_L (0x0a1c)
#define AUDIO_R_STC_H (0x0a20)
#define AUDIO_R_STC_L (0x0a24)
#define SYSTOP_W_STC2_H (0x0a28)
#define SYSTOP_W_STC2_L (0x0a2c)
#define SYSTOP_R_STC2_H (0x0a30)
#define SYSTOP_R_STC2_L (0x0a34)
#define AUDIO_W_STC2_H (0x0a38)
#define AUDIO_W_STC2_L (0x0a3c)
#define AUDIO_R_STC2_H (0x0a40)
#define AUDIO_R_STC2_L (0x0a44)
#define AFE_CONN17 (0x0a48)
#define AFE_CONN18 (0x0a4c)
#define AFE_CONN19 (0x0a50)
#define AFE_CONN20 (0x0a54)
#define AFE_CONN27 (0x0a58)
#define AFE_CONN28 (0x0a5c)
#define AFE_CONN29 (0x0a60)
#define AFE_CONN30 (0x0a64)
#define AFE_CONN31 (0x0a68)
#define AFE_CONN32 (0x0a6c)
#define AFE_CONN33 (0x0a70)
#define AFE_CONN35 (0x0a74)
#define AFE_CONN36 (0x0a78)
#define AFE_CONN37 (0x0a7c)
#define AFE_CONN38 (0x0a80)
#define AFE_CONN39 (0x0a84)
#define AFE_CONN40 (0x0a88)
#define AFE_CONN41 (0x0a8c)
#define AFE_CONN42 (0x0a90)
#define AFE_CONN44 (0x0a94)
#define AFE_CONN45 (0x0a98)
#define AFE_CONN46 (0x0a9c)
#define AFE_CONN47 (0x0aa0)
#define AFE_CONN_24BIT (0x0aa4)
#define AFE_CONN0_1 (0x0aa8)
#define AFE_CONN1_1 (0x0aac)
#define AFE_CONN2_1 (0x0ab0)
#define AFE_CONN3_1 (0x0ab4)
#define AFE_CONN4_1 (0x0ab8)
#define AFE_CONN5_1 (0x0abc)
#define AFE_CONN6_1 (0x0ac0)
#define AFE_CONN7_1 (0x0ac4)
#define AFE_CONN8_1 (0x0ac8)
#define AFE_CONN9_1 (0x0acc)
#define AFE_CONN10_1 (0x0ad0)
#define AFE_CONN11_1 (0x0ad4)
#define AFE_CONN12_1 (0x0ad8)
#define AFE_CONN13_1 (0x0adc)
#define AFE_CONN14_1 (0x0ae0)
#define AFE_CONN15_1 (0x0ae4)
#define AFE_CONN16_1 (0x0ae8)
#define AFE_CONN17_1 (0x0aec)
#define AFE_CONN18_1 (0x0af0)
#define AFE_CONN19_1 (0x0af4)
#define AFE_CONN43 (0x0af8)
#define AFE_CONN43_1 (0x0afc)
#define AFE_CONN21_1 (0x0b00)
#define AFE_CONN22_1 (0x0b04)
#define AFE_CONN23_1 (0x0b08)
#define AFE_CONN24_1 (0x0b0c)
#define AFE_CONN25_1 (0x0b10)
#define AFE_CONN26_1 (0x0b14)
#define AFE_CONN27_1 (0x0b18)
#define AFE_CONN28_1 (0x0b1c)
#define AFE_CONN29_1 (0x0b20)
#define AFE_CONN30_1 (0x0b24)
#define AFE_CONN31_1 (0x0b28)
#define AFE_CONN32_1 (0x0b2c)
#define AFE_CONN33_1 (0x0b30)
#define AFE_CONN34_1 (0x0b34)
#define AFE_CONN35_1 (0x0b38)
#define AFE_CONN36_1 (0x0b3c)
#define AFE_CONN37_1 (0x0b40)
#define AFE_CONN38_1 (0x0b44)
#define AFE_CONN39_1 (0x0b48)
#define AFE_CONN40_1 (0x0b4c)
#define AFE_CONN41_1 (0x0b50)
#define AFE_CONN42_1 (0x0b54)
#define AFE_CONN44_1 (0x0b58)
#define AFE_CONN45_1 (0x0b5c)
#define AFE_CONN46_1 (0x0b60)
#define AFE_CONN47_1 (0x0b64)
#define AFE_CONN_RS_1 (0x0b68)
#define AFE_CONN_DI_1 (0x0b6c)
#define AFE_CONN_24BIT_1 (0x0b70)
#define AFE_GAIN1_CUR (0x0b78)
#define AFE_CONN20_1 (0x0b7c)
#define AFE_DL1_BASE_MSB (0x0b80)
#define AFE_DL1_END_MSB (0x0b84)
#define AFE_DL2_BASE_MSB (0x0b88)
#define AFE_DL2_END_MSB (0x0b8c)
#define AFE_AWB_BASE_MSB (0x0b90)
#define AFE_AWB_END_MSB (0x0b94)
#define AFE_VUL_BASE_MSB (0x0ba0)
#define AFE_VUL_END_MSB (0x0ba4)
#define AFE_VUL_D2_BASE_MSB (0x0ba8)
#define AFE_VUL_D2_END_MSB (0x0bac)
#define AFE_HDMI_OUT_BASE_MSB (0x0bb8)
#define AFE_HDMI_OUT_END_MSB (0x0bbc)
#define AFE_HDMI_IN_2CH_BASE_MSB (0x0bc0)
#define AFE_HDMI_IN_2CH_END_MSB (0x0bc4)
#define AFE_SPDIF_OUT_BASE_MSB (0x0bc8)
#define AFE_SPDIF_OUT_END_MSB (0x0bcc)
#define SPDIFIN_BASE_MSB (0x0bd0)
#define SPDIFIN_END_MSB (0x0bd4)
#define AFE_DL1_CUR_MSB (0x0bd8)
#define AFE_DL2_CUR_MSB (0x0bdc)
#define AFE_AWB_CUR_MSB (0x0be8)
#define AFE_VUL_CUR_MSB (0x0bf8)
#define AFE_VUL_D2_CUR_MSB (0x0c04)
#define AFE_HDMI_OUT_CUR_MSB (0x0c0c)
#define AFE_HDMI_IN_2CH_CUR_MSB (0x0c10)
#define AFE_SPDIF_OUT_CUR_MSB (0x0c14)
#define SPDIFIN_CUR_MSB (0x0c18)
#define AFE_CONN_REG (0x0c20)
#define AFE_SECURE_MASK_CONN14_1 (0x0c24)
#define AFE_SECURE_MASK_CONN15_1 (0x0c28)
#define AFE_SECURE_MASK_CONN16_1 (0x0c2c)
#define AFE_SECURE_MASK_CONN17_1 (0x0c30)
#define AFE_SECURE_MASK_CONN18_1 (0x0c34)
#define AFE_SECURE_MASK_CONN19_1 (0x0c38)
#define AFE_SECURE_MASK_CONN20_1 (0x0c3c)
#define AFE_SECURE_MASK_CONN21_1 (0x0c40)
#define AFE_SECURE_MASK_CONN22_1 (0x0c44)
#define AFE_SECURE_MASK_CONN23_1 (0x0c48)
#define AFE_SECURE_MASK_CONN24_1 (0x0c4c)
#define AFE_ADDA_DL_SDM_DCCOMP_CON (0x0c50)
#define AFE_ADDA_DL_SDM_TEST (0x0c54)
#define AFE_ADDA_DL_DC_COMP_CFG0 (0x0c58)
#define AFE_ADDA_DL_DC_COMP_CFG1 (0x0c5c)
#define AFE_ADDA_DL_SDM_FIFO_MON (0x0c60)
#define AFE_ADDA_DL_SRC_LCH_MON (0x0c64)
#define AFE_ADDA_DL_SRC_RCH_MON (0x0c68)
#define AFE_ADDA_DL_SDM_OUT_MON (0x0c6c)
#define AFE_ADDA_DL_SDM_DITHER_CON (0x0c70)
#define AFE_VUL3_CUR_MSB (0x0c78)
#define AFE_ASRC_2CH_CON0 (0x0c80)
#define AFE_ASRC_2CH_CON1 (0x0c84)
#define AFE_ASRC_2CH_CON2 (0x0c88)
#define AFE_ASRC_2CH_CON3 (0x0c8c)
#define AFE_ASRC_2CH_CON4 (0x0c90)
#define AFE_ASRC_2CH_CON5 (0x0c94)
#define AFE_ASRC_2CH_CON6 (0x0c98)
#define AFE_ASRC_2CH_CON7 (0x0c9c)
#define AFE_ASRC_2CH_CON8 (0x0ca0)
#define AFE_ASRC_2CH_CON9 (0x0ca4)
#define AFE_ASRC_2CH_CON10 (0x0ca8)
#define AFE_ASRC_2CH_CON12 (0x0cb0)
#define AFE_ASRC_2CH_CON13 (0x0cb4)
#define AFE_PCM_TX_ASRC_2CH_CON0 (0x0cc0)
#define AFE_PCM_TX_ASRC_2CH_CON1 (0x0cc4)
#define AFE_PCM_TX_ASRC_2CH_CON2 (0x0cc8)
#define AFE_PCM_TX_ASRC_2CH_CON3 (0x0ccc)
#define AFE_PCM_TX_ASRC_2CH_CON4 (0x0cd0)
#define AFE_PCM_TX_ASRC_2CH_CON5 (0x0cd4)
#define AFE_PCM_TX_ASRC_2CH_CON6 (0x0cd8)
#define AFE_PCM_TX_ASRC_2CH_CON7 (0x0cdc)
#define AFE_PCM_TX_ASRC_2CH_CON8 (0x0ce0)
#define AFE_PCM_TX_ASRC_2CH_CON9 (0x0ce4)
#define AFE_PCM_TX_ASRC_2CH_CON10 (0x0ce8)
#define AFE_PCM_TX_ASRC_2CH_CON12 (0x0cf0)
#define AFE_PCM_TX_ASRC_2CH_CON13 (0x0cf4)
#define AFE_PCM_RX_ASRC_2CH_CON0 (0x0d00)
#define AFE_PCM_RX_ASRC_2CH_CON1 (0x0d04)
#define AFE_PCM_RX_ASRC_2CH_CON2 (0x0d08)
#define AFE_PCM_RX_ASRC_2CH_CON3 (0x0d0c)
#define AFE_PCM_RX_ASRC_2CH_CON4 (0x0d10)
#define AFE_PCM_RX_ASRC_2CH_CON5 (0x0d14)
#define AFE_PCM_RX_ASRC_2CH_CON6 (0x0d18)
#define AFE_PCM_RX_ASRC_2CH_CON7 (0x0d1c)
#define AFE_PCM_RX_ASRC_2CH_CON8 (0x0d20)
#define AFE_PCM_RX_ASRC_2CH_CON9 (0x0d24)
#define AFE_PCM_RX_ASRC_2CH_CON10 (0x0d28)
#define AFE_PCM_RX_ASRC_2CH_CON12 (0x0d30)
#define AFE_PCM_RX_ASRC_2CH_CON13 (0x0d34)
#define AFE_ADDA_PREDIS_CON2 (0x0d40)
#define AFE_ADDA_PREDIS_CON3 (0x0d44)
#define AFE_SECURE_MASK_CONN4_1 (0x0d48)
#define AFE_SECURE_MASK_CONN5_1 (0x0d4c)
#define AFE_SECURE_MASK_CONN6_1 (0x0d50)
#define AFE_SECURE_MASK_CONN7_1 (0x0d54)
#define AFE_SECURE_MASK_CONN8_1 (0x0d58)
#define AFE_SECURE_MASK_CONN9_1 (0x0d5c)
#define AFE_SECURE_MASK_CONN10_1 (0x0d60)
#define AFE_SECURE_MASK_CONN11_1 (0x0d64)
#define AFE_SECURE_MASK_CONN12_1 (0x0d68)
#define AFE_SECURE_MASK_CONN13_1 (0x0d6c)
#define AFE_MEMIF_MON12 (0x0d70)
#define AFE_MEMIF_MON13 (0x0d74)
#define AFE_MEMIF_MON14 (0x0d78)
#define AFE_MEMIF_MON15 (0x0d7c)
#define AFE_SECURE_MASK_CONN42 (0x0dbc)
#define AFE_SECURE_MASK_CONN43 (0x0dc0)
#define AFE_SECURE_MASK_CONN44 (0x0dc4)
#define AFE_SECURE_MASK_CONN45 (0x0dc8)
#define AFE_SECURE_MASK_CONN46 (0x0dcc)
#define AFE_HD_ENGEN_ENABLE (0x0dd0)
#define AFE_SECURE_MASK_CONN47 (0x0dd4)
#define AFE_SECURE_MASK_CONN48 (0x0dd8)
#define AFE_SECURE_MASK_CONN49 (0x0ddc)
#define AFE_SECURE_MASK_CONN50 (0x0de0)
#define AFE_SECURE_MASK_CONN51 (0x0de4)
#define AFE_SECURE_MASK_CONN52 (0x0de8)
#define AFE_SECURE_MASK_CONN53 (0x0dec)
#define AFE_SECURE_MASK_CONN0_1 (0x0df0)
#define AFE_SECURE_MASK_CONN1_1 (0x0df4)
#define AFE_SECURE_MASK_CONN2_1 (0x0df8)
#define AFE_SECURE_MASK_CONN3_1 (0x0dfc)
#define AFE_ADDA_MTKAIF_CFG0 (0x0e00)
#define AFE_ADDA_MTKAIF_SYNCWORD_CFG (0x0e14)
#define AFE_ADDA_MTKAIF_RX_CFG0 (0x0e20)
#define AFE_ADDA_MTKAIF_RX_CFG1 (0x0e24)
#define AFE_ADDA_MTKAIF_RX_CFG2 (0x0e28)
#define AFE_ADDA_MTKAIF_MON0 (0x0e34)
#define AFE_ADDA_MTKAIF_MON1 (0x0e38)
#define AFE_AUD_PAD_TOP (0x0e40)
#define AFE_CM1_CON4 (0x0e48)
#define AFE_CM2_CON4 (0x0e4c)
#define AFE_CM1_CON0 (0x0e50)
#define AFE_CM1_CON1 (0x0e54)
#define AFE_CM1_CON2 (0x0e58)
#define AFE_CM1_CON3 (0x0e5c)
#define AFE_CM2_CON0 (0x0e60)
#define AFE_CM2_CON1 (0x0e64)
#define AFE_CM2_CON2 (0x0e68)
#define AFE_CM2_CON3 (0x0e6c)
#define AFE_CM2_CONN0 (0x0e70)
#define AFE_CM2_CONN1 (0x0e74)
#define AFE_CM2_CONN2 (0x0e78)
#define AFE_GENERAL1_ASRC_2CH_CON0 (0x0e80)
#define AFE_GENERAL1_ASRC_2CH_CON1 (0x0e84)
#define AFE_GENERAL1_ASRC_2CH_CON2 (0x0e88)
#define AFE_GENERAL1_ASRC_2CH_CON3 (0x0e8c)
#define AFE_GENERAL1_ASRC_2CH_CON4 (0x0e90)
#define AFE_GENERAL1_ASRC_2CH_CON5 (0x0e94)
#define AFE_GENERAL1_ASRC_2CH_CON6 (0x0e98)
#define AFE_GENERAL1_ASRC_2CH_CON7 (0x0e9c)
#define AFE_GENERAL1_ASRC_2CH_CON8 (0x0ea0)
#define AFE_GENERAL1_ASRC_2CH_CON9 (0x0ea4)
#define AFE_GENERAL1_ASRC_2CH_CON10 (0x0ea8)
#define AFE_GENERAL1_ASRC_2CH_CON12 (0x0eb0)
#define AFE_GENERAL1_ASRC_2CH_CON13 (0x0eb4)
#define GENERAL_ASRC_MODE (0x0eb8)
#define GENERAL_ASRC_EN_ON (0x0ebc)
#define AFE_CONN48 (0x0ec0)
#define AFE_CONN49 (0x0ec4)
#define AFE_CONN50 (0x0ec8)
#define AFE_CONN51 (0x0ecc)
#define AFE_CONN52 (0x0ed0)
#define AFE_CONN53 (0x0ed4)
#define AFE_CONN48_1 (0x0ee0)
#define AFE_CONN49_1 (0x0ee4)
#define AFE_CONN50_1 (0x0ee8)
#define AFE_CONN51_1 (0x0eec)
#define AFE_CONN52_1 (0x0ef0)
#define AFE_CONN53_1 (0x0ef4)
#define AFE_GENERAL2_ASRC_2CH_CON0 (0x0f00)
#define AFE_GENERAL2_ASRC_2CH_CON1 (0x0f04)
#define AFE_GENERAL2_ASRC_2CH_CON2 (0x0f08)
#define AFE_GENERAL2_ASRC_2CH_CON3 (0x0f0c)
#define AFE_GENERAL2_ASRC_2CH_CON4 (0x0f10)
#define AFE_GENERAL2_ASRC_2CH_CON5 (0x0f14)
#define AFE_GENERAL2_ASRC_2CH_CON6 (0x0f18)
#define AFE_GENERAL2_ASRC_2CH_CON7 (0x0f1c)
#define AFE_GENERAL2_ASRC_2CH_CON8 (0x0f20)
#define AFE_GENERAL2_ASRC_2CH_CON9 (0x0f24)
#define AFE_GENERAL2_ASRC_2CH_CON10 (0x0f28)
#define AFE_GENERAL2_ASRC_2CH_CON12 (0x0f30)
#define AFE_GENERAL2_ASRC_2CH_CON13 (0x0f34)
#define AFE_SECURE_MASK_CONN28 (0x0f48)
#define AFE_SECURE_MASK_CONN29 (0x0f4c)
#define AFE_SECURE_MASK_CONN30 (0x0f50)
#define AFE_SECURE_MASK_CONN31 (0x0f54)
#define AFE_SECURE_MASK_CONN32 (0x0f58)
#define AFE_SECURE_MASK_CONN33 (0x0f5c)
#define AFE_SECURE_MASK_CONN34 (0x0f60)
#define AFE_SECURE_MASK_CONN35 (0x0f64)
#define AFE_SECURE_MASK_CONN36 (0x0f68)
#define AFE_SECURE_MASK_CONN37 (0x0f6c)
#define AFE_SECURE_MASK_CONN38 (0x0f70)
#define AFE_SECURE_MASK_CONN39 (0x0f74)
#define AFE_SECURE_MASK_CONN40 (0x0f78)
#define AFE_SECURE_MASK_CONN41 (0x0f7c)
#define AFE_SIDEBAND0 (0x0f80)
#define AFE_SIDEBAND1 (0x0f84)
#define AFE_SECURE_SIDEBAND0 (0x0f88)
#define AFE_SECURE_SIDEBAND1 (0x0f8c)
#define AFE_SECURE_MASK_CONN0 (0x0f90)
#define AFE_SECURE_MASK_CONN1 (0x0f94)
#define AFE_SECURE_MASK_CONN2 (0x0f98)
#define AFE_SECURE_MASK_CONN3 (0x0f9c)
#define AFE_SECURE_MASK_CONN4 (0x0fa0)
#define AFE_SECURE_MASK_CONN5 (0x0fa4)
#define AFE_SECURE_MASK_CONN6 (0x0fa8)
#define AFE_SECURE_MASK_CONN7 (0x0fac)
#define AFE_SECURE_MASK_CONN8 (0x0fb0)
#define AFE_SECURE_MASK_CONN9 (0x0fb4)
#define AFE_SECURE_MASK_CONN10 (0x0fb8)
#define AFE_SECURE_MASK_CONN11 (0x0fbc)
#define AFE_SECURE_MASK_CONN12 (0x0fc0)
#define AFE_SECURE_MASK_CONN13 (0x0fc4)
#define AFE_SECURE_MASK_CONN14 (0x0fc8)
#define AFE_SECURE_MASK_CONN15 (0x0fcc)
#define AFE_SECURE_MASK_CONN16 (0x0fd0)
#define AFE_SECURE_MASK_CONN17 (0x0fd4)
#define AFE_SECURE_MASK_CONN18 (0x0fd8)
#define AFE_SECURE_MASK_CONN19 (0x0fdc)
#define AFE_SECURE_MASK_CONN20 (0x0fe0)
#define AFE_SECURE_MASK_CONN21 (0x0fe4)
#define AFE_SECURE_MASK_CONN22 (0x0fe8)
#define AFE_SECURE_MASK_CONN23 (0x0fec)
#define AFE_SECURE_MASK_CONN24 (0x0ff0)
#define AFE_SECURE_MASK_CONN25 (0x0ff4)
#define AFE_SECURE_MASK_CONN26 (0x0ff8)
#define AFE_SECURE_MASK_CONN27 (0x0ffc)
#define MAX_REGISTER AFE_SECURE_MASK_CONN27
#define AFE_IRQ_STATUS_BITS 0x3ff
/* AUDIO_TOP_CON0 (0x0000) */
#define AUD_TCON0_PDN_TML BIT(27)
#define AUD_TCON0_PDN_DAC_PREDIS BIT(26)
#define AUD_TCON0_PDN_DAC BIT(25)
#define AUD_TCON0_PDN_ADC BIT(24)
#define AUD_TCON0_PDN_TDM_IN BIT(23)
#define AUD_TCON0_PDN_TDM_OUT BIT(22)
#define AUD_TCON0_PDN_SPDIF BIT(21)
#define AUD_TCON0_PDN_APLL_TUNER BIT(19)
#define AUD_TCON0_PDN_APLL2_TUNER BIT(18)
#define AUD_TCON0_PDN_INTDIR BIT(15)
#define AUD_TCON0_PDN_24M BIT(9)
#define AUD_TCON0_PDN_22M BIT(8)
#define AUD_TCON0_PDN_I2S_IN BIT(6)
#define AUD_TCON0_PDN_AFE BIT(2)
/* AUDIO_TOP_CON1 (0x0004) */
#define AUD_TCON1_PDN_TDM_ASRC BIT(15)
#define AUD_TCON1_PDN_GENERAL2_ASRC BIT(14)
#define AUD_TCON1_PDN_GENERAL1_ASRC BIT(13)
#define AUD_TCON1_PDN_CONNSYS_I2S_ASRC BIT(12)
#define AUD_TCON1_PDN_DMIC3_ADC BIT(11)
#define AUD_TCON1_PDN_DMIC2_ADC BIT(10)
#define AUD_TCON1_PDN_DMIC1_ADC BIT(9)
#define AUD_TCON1_PDN_DMIC0_ADC BIT(8)
#define AUD_TCON1_PDN_I2S4_BCLK BIT(7)
#define AUD_TCON1_PDN_I2S3_BCLK BIT(6)
#define AUD_TCON1_PDN_I2S2_BCLK BIT(5)
#define AUD_TCON1_PDN_I2S1_BCLK BIT(4)
/* AUDIO_TOP_CON3 (0x000C) */
#define AUD_TCON3_HDMI_BCK_INV BIT(3)
/* AFE_I2S_CON (0x0018) */
#define AFE_I2S_CON_PHASE_SHIFT_FIX BIT(31)
#define AFE_I2S_CON_FROM_IO_MUX BIT(28)
#define AFE_I2S_CON_LOW_JITTER_CLK BIT(12)
#define AFE_I2S_CON_RATE_MASK GENMASK(11, 8)
#define AFE_I2S_CON_FORMAT_I2S BIT(3)
#define AFE_I2S_CON_SRC_SLAVE BIT(2)
/* AFE_ASRC_2CH_CON0 */
#define ONE_HEART BIT(31)
#define CHSET_STR_CLR BIT(4)
#define COEFF_SRAM_CTRL BIT(1)
#define ASM_ON BIT(0)
/* CON2 */
#define O16BIT BIT(19)
#define CLR_IIR_HISTORY BIT(17)
#define IS_MONO BIT(16)
#define IIR_EN BIT(11)
#define IIR_STAGE_MASK GENMASK(10, 8)
/* CON5 */
#define CALI_CYCLE_MASK GENMASK(31, 16)
#define CALI_64_CYCLE FIELD_PREP(CALI_CYCLE_MASK, 0x3F)
#define CALI_96_CYCLE FIELD_PREP(CALI_CYCLE_MASK, 0x5F)
#define CALI_441_CYCLE FIELD_PREP(CALI_CYCLE_MASK, 0x1B8)
#define CALI_AUTORST BIT(15)
#define AUTO_TUNE_FREQ5 BIT(12)
#define COMP_FREQ_RES BIT(11)
#define CALI_SEL_MASK GENMASK(9, 8)
#define CALI_SEL_00 FIELD_PREP(CALI_SEL_MASK, 0)
#define CALI_SEL_01 FIELD_PREP(CALI_SEL_MASK, 1)
#define CALI_BP_DGL BIT(7) /* Bypass the deglitch circuit */
#define AUTO_TUNE_FREQ4 BIT(3)
#define CALI_AUTO_RESTART BIT(2)
#define CALI_USE_FREQ_OUT BIT(1)
#define CALI_ON BIT(0)
#define AFE_I2S_CON_WLEN_32BIT BIT(1)
#define AFE_I2S_CON_EN BIT(0)
#define AFE_CONN3_I03_O03_S BIT(3)
#define AFE_CONN4_I04_O04_S BIT(4)
#define AFE_CONN4_I03_O04_S BIT(3)
/* AFE_I2S_CON1 (0x0034) */
#define AFE_I2S_CON1_I2S2_TO_PAD BIT(18)
#define AFE_I2S_CON1_TDMOUT_TO_PAD (0 << 18)
#define AFE_I2S_CON1_RATE GENMASK(11, 8)
#define AFE_I2S_CON1_FORMAT_I2S BIT(3)
#define AFE_I2S_CON1_WLEN_32BIT BIT(1)
#define AFE_I2S_CON1_EN BIT(0)
/* AFE_I2S_CON2 (0x0038) */
#define AFE_I2S_CON2_LOW_JITTER_CLK BIT(12)
#define AFE_I2S_CON2_RATE GENMASK(11, 8)
#define AFE_I2S_CON2_FORMAT_I2S BIT(3)
#define AFE_I2S_CON2_WLEN_32BIT BIT(1)
#define AFE_I2S_CON2_EN BIT(0)
/* AFE_I2S_CON3 (0x004C) */
#define AFE_I2S_CON3_LOW_JITTER_CLK BIT(12)
#define AFE_I2S_CON3_RATE GENMASK(11, 8)
#define AFE_I2S_CON3_FORMAT_I2S BIT(3)
#define AFE_I2S_CON3_WLEN_32BIT BIT(1)
#define AFE_I2S_CON3_EN BIT(0)
/* AFE_ADDA_DL_SRC2_CON0 (0x0108) */
#define AFE_ADDA_DL_SAMPLING_RATE GENMASK(31, 28)
#define AFE_ADDA_DL_8X_UPSAMPLE GENMASK(25, 24)
#define AFE_ADDA_DL_MUTE_OFF_CH1 BIT(12)
#define AFE_ADDA_DL_MUTE_OFF_CH2 BIT(11)
#define AFE_ADDA_DL_VOICE_DATA BIT(5)
#define AFE_ADDA_DL_DEGRADE_GAIN BIT(1)
/* AFE_ADDA_UL_SRC_CON0 (0x0114) */
#define AFE_ADDA_UL_SAMPLING_RATE GENMASK(19, 17)
/* AFE_ADDA_UL_DL_CON0 */
#define AFE_ADDA_UL_DL_ADDA_AFE_ON BIT(0)
#define AFE_ADDA_UL_DL_DMIC_CLKDIV_ON BIT(1)
/* AFE_APLL_TUNER_CFG (0x03f0) */
#define AFE_APLL_TUNER_CFG_MASK GENMASK(15, 1)
#define AFE_APLL_TUNER_CFG_EN_MASK BIT(0)
/* AFE_APLL_TUNER_CFG1 (0x03f4) */
#define AFE_APLL_TUNER_CFG1_MASK GENMASK(15, 1)
#define AFE_APLL_TUNER_CFG1_EN_MASK BIT(0)
/* PCM_INTF_CON1 (0x0550) */
#define PCM_INTF_CON1_EXT_MODEM BIT(17)
#define PCM_INTF_CON1_16BIT (0 << 16)
#define PCM_INTF_CON1_24BIT BIT(16)
#define PCM_INTF_CON1_32BCK (0 << 14)
#define PCM_INTF_CON1_64BCK BIT(14)
#define PCM_INTF_CON1_MASTER_MODE (0 << 5)
#define PCM_INTF_CON1_SLAVE_MODE BIT(5)
#define PCM_INTF_CON1_FS_MASK GENMASK(4, 3)
#define PCM_INTF_CON1_FS_8K FIELD_PREP(PCM_INTF_CON1_FS_MASK, 0)
#define PCM_INTF_CON1_FS_16K FIELD_PREP(PCM_INTF_CON1_FS_MASK, 1)
#define PCM_INTF_CON1_FS_32K FIELD_PREP(PCM_INTF_CON1_FS_MASK, 2)
#define PCM_INTF_CON1_FS_48K FIELD_PREP(PCM_INTF_CON1_FS_MASK, 3)
#define PCM_INTF_CON1_SYNC_LEN_MASK GENMASK(13, 9)
#define PCM_INTF_CON1_SYNC_LEN(x) FIELD_PREP(PCM_INTF_CON1_SYNC_LEN_MASK, ((x) - 1))
#define PCM_INTF_CON1_FORMAT_MASK GENMASK(2, 1)
#define PCM_INTF_CON1_SYNC_OUT_INV BIT(23)
#define PCM_INTF_CON1_BCLK_OUT_INV BIT(22)
#define PCM_INTF_CON1_SYNC_IN_INV BIT(21)
#define PCM_INTF_CON1_BCLK_IN_INV BIT(20)
#define PCM_INTF_CON1_BYPASS_ASRC BIT(6)
#define PCM_INTF_CON1_EN BIT(0)
#define PCM_INTF_CON1_CONFIG_MASK (0xf3fffe)
/* AFE_DMIC0_UL_SRC_CON0 (0x05b4)
* AFE_DMIC1_UL_SRC_CON0 (0x0620)
* AFE_DMIC2_UL_SRC_CON0 (0x0780)
* AFE_DMIC3_UL_SRC_CON0 (0x07ec)
*/
#define DMIC_TOP_CON_CK_PHASE_SEL_CH1 GENMASK(29, 27)
#define DMIC_TOP_CON_CK_PHASE_SEL_CH2 GENMASK(26, 24)
#define DMIC_TOP_CON_TWO_WIRE_MODE BIT(23)
#define DMIC_TOP_CON_CH2_ON BIT(22)
#define DMIC_TOP_CON_CH1_ON BIT(21)
#define DMIC_TOP_CON_VOICE_MODE_MASK GENMASK(19, 17)
#define DMIC_TOP_CON_VOICE_MODE_8K FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 0)
#define DMIC_TOP_CON_VOICE_MODE_16K FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 1)
#define DMIC_TOP_CON_VOICE_MODE_32K FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 2)
#define DMIC_TOP_CON_VOICE_MODE_48K FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 3)
#define DMIC_TOP_CON_LOW_POWER_MODE_MASK GENMASK(15, 14)
#define DMIC_TOP_CON_LOW_POWER_MODE(x) FIELD_PREP(DMIC_TOP_CON_LOW_POWER_MODE_MASK, (x))
#define DMIC_TOP_CON_IIR_ON BIT(10)
#define DMIC_TOP_CON_IIR_MODE GENMASK(9, 7)
#define DMIC_TOP_CON_INPUT_MODE BIT(5)
#define DMIC_TOP_CON_SDM3_LEVEL_MODE BIT(1)
#define DMIC_TOP_CON_SRC_ON BIT(0)
#define DMIC_TOP_CON_SDM3_DE_SELECT (0 << 1)
#define DMIC_TOP_CON_CONFIG_MASK (0x3f8ed7a6)
/* AFE_CONN_24BIT (0x0AA4) */
#define AFE_CONN_24BIT_O10 BIT(10)
#define AFE_CONN_24BIT_O09 BIT(9)
#define AFE_CONN_24BIT_O06 BIT(6)
#define AFE_CONN_24BIT_O05 BIT(5)
#define AFE_CONN_24BIT_O04 BIT(4)
#define AFE_CONN_24BIT_O03 BIT(3)
#define AFE_CONN_24BIT_O02 BIT(2)
#define AFE_CONN_24BIT_O01 BIT(1)
#define AFE_CONN_24BIT_O00 BIT(0)
/* AFE_HD_ENGEN_ENABLE */
#define AFE_22M_PLL_EN BIT(0)
#define AFE_24M_PLL_EN BIT(1)
/* AFE_GAIN1_CON0 (0x0410) */
#define AFE_GAIN1_CON0_EN_MASK GENMASK(0, 0)
#define AFE_GAIN1_CON0_MODE_MASK GENMASK(7, 4)
#define AFE_GAIN1_CON0_SAMPLE_PER_STEP_MASK GENMASK(15, 8)
/* AFE_GAIN1_CON1 (0x0414) */
#define AFE_GAIN1_CON1_MASK GENMASK(19, 0)
/* AFE_GAIN1_CUR (0x0B78) */
#define AFE_GAIN1_CUR_MASK GENMASK(19, 0)
/* AFE_CM1_CON0 (0x0e50) */
/* AFE_CM2_CON0 (0x0e60) */
#define CM_AFE_CM_CH_NUM_MASK GENMASK(3, 0)
#define CM_AFE_CM_CH_NUM(x) FIELD_PREP(CM_AFE_CM_CH_NUM_MASK, ((x) - 1))
#define CM_AFE_CM_ON BIT(4)
#define CM_AFE_CM_START_DATA_MASK GENMASK(11, 8)
#define CM_AFE_CM1_VUL_SEL BIT(12)
#define CM_AFE_CM1_IN_MODE_MASK GENMASK(19, 16)
#define CM_AFE_CM2_TDM_SEL BIT(12)
#define CM_AFE_CM2_CLK_SEL BIT(13)
#define CM_AFE_CM2_GASRC1_OUT_SEL BIT(17)
#define CM_AFE_CM2_GASRC2_OUT_SEL BIT(16)
/* AFE_CM2_CONN* */
#define CM2_AFE_CM2_CONN_CFG1(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG1_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG1_MASK GENMASK(4, 0)
#define CM2_AFE_CM2_CONN_CFG2(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG2_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG2_MASK GENMASK(9, 5)
#define CM2_AFE_CM2_CONN_CFG3(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG3_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG3_MASK GENMASK(14, 10)
#define CM2_AFE_CM2_CONN_CFG4(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG4_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG4_MASK GENMASK(19, 15)
#define CM2_AFE_CM2_CONN_CFG5(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG5_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG5_MASK GENMASK(24, 20)
#define CM2_AFE_CM2_CONN_CFG6(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG6_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG6_MASK GENMASK(29, 25)
#define CM2_AFE_CM2_CONN_CFG7(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG7_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG7_MASK GENMASK(4, 0)
#define CM2_AFE_CM2_CONN_CFG8(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG8_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG8_MASK GENMASK(9, 5)
#define CM2_AFE_CM2_CONN_CFG9(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG9_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG9_MASK GENMASK(14, 10)
#define CM2_AFE_CM2_CONN_CFG10(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG10_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG10_MASK GENMASK(19, 15)
#define CM2_AFE_CM2_CONN_CFG11(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG11_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG11_MASK GENMASK(24, 20)
#define CM2_AFE_CM2_CONN_CFG12(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG12_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG12_MASK GENMASK(29, 25)
#define CM2_AFE_CM2_CONN_CFG13(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG13_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG13_MASK GENMASK(4, 0)
#define CM2_AFE_CM2_CONN_CFG14(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG14_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG14_MASK GENMASK(9, 5)
#define CM2_AFE_CM2_CONN_CFG15(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG15_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG15_MASK GENMASK(14, 10)
#define CM2_AFE_CM2_CONN_CFG16(x) FIELD_PREP(CM2_AFE_CM2_CONN_CFG16_MASK, (x))
#define CM2_AFE_CM2_CONN_CFG16_MASK GENMASK(19, 15)
/* AFE_CM1_CON* */
#define CM_AFE_CM_UPDATE_CNT1_MASK GENMASK(15, 0)
#define CM_AFE_CM_UPDATE_CNT1(x) FIELD_PREP(CM_AFE_CM_UPDATE_CNT1_MASK, (x))
#define CM_AFE_CM_UPDATE_CNT2_MASK GENMASK(31, 16)
#define CM_AFE_CM_UPDATE_CNT2(x) FIELD_PREP(CM_AFE_CM_UPDATE_CNT2_MASK, (x))
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment