Commit 860bfa6d authored by Mark Brown's avatar Mark Brown

Merge series "ASoC: Mediatek: Add support for MT8192 SoC" from Jiaxin Yu <jiaxin.yu@mediatek.com>:

This series of patches adds support for Mediatek AFE for MT8192 SoC. At the same
time, the calibration function of MT6359 is completed with real machine driver.
The patch is based on broonie tree "for-next" branch.

Change since v3:
  - use normal conditional statements to improve legiblity in [v3,3/9]
  - remove mtk_i2s_hd_en_event as there's trace in the core
  - impove mt8192_i2s_enum and mt8192_adda_enum

Change since v2:
  - split the dai driver files as a separate patch
  - fix dt-bindings to GPL-2.0-only License
  - remove unnecessary preperty descriptions such as 'maxItems'

Change since v1:
  - fixed some typos related to dt-bindings in [v1,3/5] and [v1,5/5]
  - add vendor prefix to the properties, such as "mediatek,apmixedsys"
  - add a dependency description to indicate the required header files

Jiaxin Yu (9):
  ASoC: mediatek: mt6359: add the calibration functions
  ASoC: mediatek: mt8192: add platform driver
  ASoC: mediatek: mt8192: support i2s in platform driver
  ASoC: mediatek: mt8192: support adda in platform driver
  ASoC: mediatek: mt8192: support pcm in platform driver
  ASoC: mediatek: mt8192: support tdm in platform driver
  dt-bindings: mediatek: mt8192: add audio afe document
  ASoC: mediatek: mt8192: add machine driver with mt6359, rt1015 and
    rt5682
  dt-bindings: mediatek: mt8192: add mt8192-mt6358-rt1015-rt5682
    document

 .../bindings/sound/mt8192-afe-pcm.yaml        |  100 +
 .../sound/mt8192-mt6359-rt1015-rt5682.yaml    |   42 +
 sound/soc/codecs/mt6359.c                     |  110 +
 sound/soc/codecs/mt6359.h                     |    7 +
 sound/soc/mediatek/Kconfig                    |   23 +
 sound/soc/mediatek/Makefile                   |    1 +
 sound/soc/mediatek/common/mtk-afe-fe-dai.c    |   13 +-
 sound/soc/mediatek/common/mtk-base-afe.h      |    1 +
 sound/soc/mediatek/mt8192/Makefile            |   16 +
 sound/soc/mediatek/mt8192/mt8192-afe-clk.c    |  669 ++++
 sound/soc/mediatek/mt8192/mt8192-afe-clk.h    |  244 ++
 sound/soc/mediatek/mt8192/mt8192-afe-common.h |  170 +
 .../soc/mediatek/mt8192/mt8192-afe-control.c  |  163 +
 sound/soc/mediatek/mt8192/mt8192-afe-gpio.c   |  306 ++
 sound/soc/mediatek/mt8192/mt8192-afe-gpio.h   |   19 +
 sound/soc/mediatek/mt8192/mt8192-afe-pcm.c    | 2389 +++++++++++++
 sound/soc/mediatek/mt8192/mt8192-dai-adda.c   | 1471 ++++++++
 sound/soc/mediatek/mt8192/mt8192-dai-i2s.c    | 2110 +++++++++++
 sound/soc/mediatek/mt8192/mt8192-dai-pcm.c    |  409 +++
 sound/soc/mediatek/mt8192/mt8192-dai-tdm.c    |  778 ++++
 .../mediatek/mt8192/mt8192-interconnection.h  |   65 +
 .../mt8192/mt8192-mt6359-rt1015-rt5682.c      | 1058 ++++++
 sound/soc/mediatek/mt8192/mt8192-reg.h        | 3131 +++++++++++++++++
 23 files changed, 13291 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8192-afe-pcm.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
 create mode 100644 sound/soc/mediatek/mt8192/Makefile
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-clk.h
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-control.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-gpio.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-gpio.h
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-dai-adda.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-dai-i2s.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-interconnection.h
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
 create mode 100644 sound/soc/mediatek/mt8192/mt8192-reg.h

--
2.18.0
parents 7e9a2387 4a232122
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mt8192-afe-pcm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek AFE PCM controller for mt8192
maintainers:
- Jiaxin Yu <jiaxin.yu@mediatek.com>
- Shane Chien <shane.chien@mediatek.com>
properties:
compatible:
const: mediatek,mt8192-audio
interrupts:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: audiosys
mediatek,apmixedsys:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of the mediatek apmixedsys controller
mediatek,infracfg:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of the mediatek infracfg controller
mediatek,topckgen:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of the mediatek topckgen controller
power-domains:
maxItems: 1
clocks:
items:
- description: AFE clock
- description: ADDA DAC clock
- description: ADDA DAC pre-distortion clock
- description: audio infra sys clock
- description: audio infra 26M clock
clock-names:
items:
- const: aud_afe_clk
- const: aud_dac_clk
- const: aud_dac_predis_clk
- const: aud_infra_clk
- const: aud_infra_26m_clk
required:
- compatible
- interrupts
- resets
- reset-names
- mediatek,apmixedsys
- mediatek,infracfg
- mediatek,topckgen
- power-domains
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8192-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/mt8192-power.h>
#include <dt-bindings/reset-controller/mt8192-resets.h>
afe: mt8192-afe-pcm {
compatible = "mediatek,mt8192-audio";
interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
resets = <&watchdog MT8192_TOPRGU_AUDIO_SW_RST>;
reset-names = "audiosys";
mediatek,apmixedsys = <&apmixedsys>;
mediatek,infracfg = <&infracfg>;
mediatek,topckgen = <&topckgen>;
power-domains = <&scpsys MT8192_POWER_DOMAIN_AUDIO>;
clocks = <&audsys CLK_AUD_AFE>,
<&audsys CLK_AUD_DAC>,
<&audsys CLK_AUD_DAC_PREDIS>,
<&infracfg CLK_INFRA_AUDIO>,
<&infracfg CLK_INFRA_AUDIO_26M_B>;
clock-names = "aud_afe_clk",
"aud_dac_clk",
"aud_dac_predis_clk",
"aud_infra_clk",
"aud_infra_26m_clk";
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mt8192-mt6359-rt1015-rt5682.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek MT8192 with MT6359, RT1015 and RT5682 ASoC sound card driver
maintainers:
- Jiaxin Yu <jiaxin.yu@mediatek.com>
- Shane Chien <shane.chien@mediatek.com>
description:
This binding describes the MT8192 sound card.
properties:
compatible:
const: mediatek,mt8192_mt6359_rt1015_rt5682
mediatek,platform:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8192 ASoC platform.
additionalProperties: false
required:
- compatible
- mediatek,platform
examples:
- |
sound: mt8192-sound {
compatible = "mediatek,mt8192-mt6359-rt1015-rt5682";
mediatek,platform = <&afe>;
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
};
...
......@@ -68,6 +68,38 @@ static void mt6359_reset_capture_gpio(struct mt6359_priv *priv)
0x3 << 0, 0x0);
}
/* use only when doing mtkaif calibraiton at the boot time */
static void mt6359_set_dcxo(struct mt6359_priv *priv, bool enable)
{
regmap_update_bits(priv->regmap, MT6359_DCXO_CW12,
0x1 << RG_XO_AUDIO_EN_M_SFT,
(enable ? 1 : 0) << RG_XO_AUDIO_EN_M_SFT);
}
/* use only when doing mtkaif calibraiton at the boot time */
static void mt6359_set_clksq(struct mt6359_priv *priv, bool enable)
{
/* Enable/disable CLKSQ 26MHz */
regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON23,
RG_CLKSQ_EN_MASK_SFT,
(enable ? 1 : 0) << RG_CLKSQ_EN_SFT);
}
/* use only when doing mtkaif calibraiton at the boot time */
static void mt6359_set_aud_global_bias(struct mt6359_priv *priv, bool enable)
{
regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON13,
RG_AUDGLB_PWRDN_VA32_MASK_SFT,
(enable ? 0 : 1) << RG_AUDGLB_PWRDN_VA32_SFT);
}
/* use only when doing mtkaif calibraiton at the boot time */
static void mt6359_set_topck(struct mt6359_priv *priv, bool enable)
{
regmap_update_bits(priv->regmap, MT6359_AUD_TOP_CKPDN_CON0,
0x0066, enable ? 0x0 : 0x66);
}
static void mt6359_set_decoder_clk(struct mt6359_priv *priv, bool enable)
{
regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON13,
......@@ -122,6 +154,84 @@ static void mt6359_mtkaif_tx_disable(struct mt6359_priv *priv)
0xff00, 0x3000);
}
void mt6359_set_mtkaif_protocol(struct snd_soc_component *cmpnt,
int mtkaif_protocol)
{
struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt);
priv->mtkaif_protocol = mtkaif_protocol;
}
EXPORT_SYMBOL_GPL(mt6359_set_mtkaif_protocol);
void mt6359_mtkaif_calibration_enable(struct snd_soc_component *cmpnt)
{
struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt);
mt6359_set_playback_gpio(priv);
mt6359_set_capture_gpio(priv);
mt6359_mtkaif_tx_enable(priv);
mt6359_set_dcxo(priv, true);
mt6359_set_aud_global_bias(priv, true);
mt6359_set_clksq(priv, true);
mt6359_set_topck(priv, true);
/* set dat_miso_loopback on */
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT,
1 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT,
1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG1,
RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_MASK_SFT,
1 << RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_SFT);
}
EXPORT_SYMBOL_GPL(mt6359_mtkaif_calibration_enable);
void mt6359_mtkaif_calibration_disable(struct snd_soc_component *cmpnt)
{
struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt);
/* set dat_miso_loopback off */
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT,
0 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT,
0 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG1,
RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_MASK_SFT,
0 << RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_SFT);
mt6359_set_topck(priv, false);
mt6359_set_clksq(priv, false);
mt6359_set_aud_global_bias(priv, false);
mt6359_set_dcxo(priv, false);
mt6359_mtkaif_tx_disable(priv);
mt6359_reset_playback_gpio(priv);
mt6359_reset_capture_gpio(priv);
}
EXPORT_SYMBOL_GPL(mt6359_mtkaif_calibration_disable);
void mt6359_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
int phase_1, int phase_2, int phase_3)
{
struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_PHASE_MODE_MASK_SFT,
phase_1 << RG_AUD_PAD_TOP_PHASE_MODE_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG,
RG_AUD_PAD_TOP_PHASE_MODE2_MASK_SFT,
phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT);
regmap_update_bits(priv->regmap, MT6359_AUDIO_DIG_CFG1,
RG_AUD_PAD_TOP_PHASE_MODE3_MASK_SFT,
phase_3 << RG_AUD_PAD_TOP_PHASE_MODE3_SFT);
}
EXPORT_SYMBOL_GPL(mt6359_set_mtkaif_calibration_phase);
static void zcd_disable(struct mt6359_priv *priv)
{
regmap_write(priv->regmap, MT6359_ZCD_CON0, 0x0000);
......
......@@ -2637,4 +2637,11 @@ struct mt6359_priv {
(type) == MIC_TYPE_MUX_DCC_ECM_DIFF || \
(type) == MIC_TYPE_MUX_DCC_ECM_SINGLE)
void mt6359_set_mtkaif_protocol(struct snd_soc_component *cmpnt,
int mtkaif_protocol);
void mt6359_mtkaif_calibration_enable(struct snd_soc_component *cmpnt);
void mt6359_mtkaif_calibration_disable(struct snd_soc_component *cmpnt);
void mt6359_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
int phase_1, int phase_2, int phase_3);
#endif/* end _MT6359_H_ */
......@@ -158,3 +158,26 @@ config SND_SOC_MTK_BTCVSD
BT encoded data to/from BT firmware.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8192
tristate "ASoC support for Mediatek MT8192 chip"
depends on ARCH_MEDIATEK
select SND_SOC_MEDIATEK
help
This adds ASoC platform driver support for Mediatek MT8192 chip
that can be used with other codecs.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8192_MT6359_RT1015_RT5682
tristate "ASoC Audio driver for MT8192 with MT6359 RT1015 RT5682 codec"
depends on I2C
depends on SND_SOC_MT8192
select SND_SOC_MT6359
select SND_SOC_RT1015
select SND_SOC_RT5682_I2C
help
This adds ASoC driver for Mediatek MT8192 boards
with the MT6359 RT1015 RT5682 audio codec.
Select Y if you have such device.
If unsure select "N".
......@@ -4,3 +4,4 @@ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
......@@ -542,8 +542,13 @@ int mtk_memif_set_format(struct mtk_base_afe *afe,
break;
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_U32_LE:
if (afe->memif_32bit_supported) {
hd_audio = 2;
hd_align = 0;
} else {
hd_audio = 1;
hd_align = 1;
}
break;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_U24_LE:
......@@ -556,10 +561,10 @@ int mtk_memif_set_format(struct mtk_base_afe *afe,
}
mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
1, hd_audio, memif->data->hd_shift);
0x3, hd_audio, memif->data->hd_shift);
mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg,
1, hd_align, memif->data->hd_align_mshift);
0x1, hd_align, memif->data->hd_align_mshift);
return 0;
}
......
......@@ -91,6 +91,7 @@ struct mtk_base_afe {
int memif_size;
struct mtk_base_afe_irq *irqs;
int irqs_size;
int memif_32bit_supported;
struct list_head sub_dais;
struct snd_soc_dai_driver *dai_drivers;
......
# SPDX-License-Identifier: GPL-2.0
# platform driver
snd-soc-mt8192-afe-objs := \
mt8192-afe-pcm.o \
mt8192-afe-clk.o \
mt8192-afe-gpio.o \
mt8192-dai-adda.o \
mt8192-afe-control.o \
mt8192-dai-i2s.o \
mt8192-dai-pcm.o \
mt8192-dai-tdm.o
obj-$(CONFIG_SND_SOC_MT8192) += snd-soc-mt8192-afe.o
obj-$(CONFIG_SND_SOC_MT8192_MT6359_RT1015_RT5682) += \
mt8192-mt6359-rt1015-rt5682.o
// SPDX-License-Identifier: GPL-2.0
//
// mt8192-afe-clk.c -- Mediatek 8192 afe clock ctrl
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "mt8192-afe-clk.h"
#include "mt8192-afe-common.h"
static const char *aud_clks[CLK_NUM] = {
[CLK_AFE] = "aud_afe_clk",
[CLK_TML] = "aud_tml_clk",
[CLK_APLL22M] = "aud_apll22m_clk",
[CLK_APLL24M] = "aud_apll24m_clk",
[CLK_APLL1_TUNER] = "aud_apll1_tuner_clk",
[CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
[CLK_NLE] = "aud_nle",
[CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
[CLK_INFRA_AUDIO_26M] = "aud_infra_26m_clk",
[CLK_MUX_AUDIO] = "top_mux_audio",
[CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int",
[CLK_TOP_MAINPLL_D4_D4] = "top_mainpll_d4_d4",
[CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
[CLK_TOP_APLL1_CK] = "top_apll1_ck",
[CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
[CLK_TOP_APLL2_CK] = "top_apll2_ck",
[CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
[CLK_TOP_APLL1_D4] = "top_apll1_d4",
[CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
[CLK_TOP_APLL2_D4] = "top_apll2_d4",
[CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h",
[CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
[CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
[CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
[CLK_TOP_I2S3_M_SEL] = "top_i2s3_m_sel",
[CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
[CLK_TOP_I2S5_M_SEL] = "top_i2s5_m_sel",
[CLK_TOP_I2S6_M_SEL] = "top_i2s6_m_sel",
[CLK_TOP_I2S7_M_SEL] = "top_i2s7_m_sel",
[CLK_TOP_I2S8_M_SEL] = "top_i2s8_m_sel",
[CLK_TOP_I2S9_M_SEL] = "top_i2s9_m_sel",
[CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
[CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
[CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
[CLK_TOP_APLL12_DIV3] = "top_apll12_div3",
[CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
[CLK_TOP_APLL12_DIVB] = "top_apll12_divb",
[CLK_TOP_APLL12_DIV5] = "top_apll12_div5",
[CLK_TOP_APLL12_DIV6] = "top_apll12_div6",
[CLK_TOP_APLL12_DIV7] = "top_apll12_div7",
[CLK_TOP_APLL12_DIV8] = "top_apll12_div8",
[CLK_TOP_APLL12_DIV9] = "top_apll12_div9",
[CLK_CLK26M] = "top_clk26m_clk",
};
int mt8192_set_audio_int_bus_parent(struct mtk_base_afe *afe,
int clk_id)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
afe_priv->clk[clk_id]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_MUX_AUDIOINTBUS],
aud_clks[clk_id], ret);
}
return ret;
}
static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
if (enable) {
ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_1], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
afe_priv->clk[CLK_TOP_APLL1_CK]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_1],
aud_clks[CLK_TOP_APLL1_CK], ret);
goto EXIT;
}
/* 180.6336 / 4 = 45.1584MHz */
ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
afe_priv->clk[CLK_TOP_APLL1_D4]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
aud_clks[CLK_TOP_APLL1_D4], ret);
goto EXIT;
}
} else {
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
afe_priv->clk[CLK_CLK26M]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
afe_priv->clk[CLK_CLK26M]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_1],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
}
EXIT:
return ret;
}
static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
if (enable) {
ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_2], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
afe_priv->clk[CLK_TOP_APLL2_CK]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_2],
aud_clks[CLK_TOP_APLL2_CK], ret);
goto EXIT;
}
/* 196.608 / 4 = 49.152MHz */
ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
afe_priv->clk[CLK_TOP_APLL2_D4]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
aud_clks[CLK_TOP_APLL2_D4], ret);
goto EXIT;
}
} else {
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
afe_priv->clk[CLK_CLK26M]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
afe_priv->clk[CLK_CLK26M]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUD_2],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
}
EXIT:
return ret;
}
int mt8192_afe_enable_clock(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
dev_info(afe->dev, "%s()\n", __func__);
ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_INFRA_AUDIO_26M], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_MUX_AUDIO], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
afe_priv->clk[CLK_CLK26M]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_MUX_AUDIO],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
goto EXIT;
}
ret = mt8192_set_audio_int_bus_parent(afe, CLK_CLK26M);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_MUX_AUDIOINTBUS],
aud_clks[CLK_CLK26M], ret);
goto EXIT;
}
ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H],
afe_priv->clk[CLK_TOP_APLL2_CK]);
if (ret) {
dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLK_TOP_MUX_AUDIO_H],
aud_clks[CLK_TOP_APLL2_CK], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_AFE], ret);
goto EXIT;
}
EXIT:
return ret;
}
void mt8192_afe_disable_clock(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
dev_info(afe->dev, "%s()\n", __func__);
clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
mt8192_set_audio_int_bus_parent(afe, CLK_CLK26M);
clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]);
clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
}
int mt8192_apll1_enable(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
/* setting for APLL */
apll1_mux_setting(afe, true);
ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_APLL22M], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_APLL1_TUNER], ret);
goto EXIT;
}
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
0x0000FFF7, 0x00000832);
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_22M_ON_MASK_SFT,
0x1 << AFE_22M_ON_SFT);
EXIT:
return ret;
}
void mt8192_apll1_disable(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_22M_ON_MASK_SFT,
0x0 << AFE_22M_ON_SFT);
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
apll1_mux_setting(afe, false);
}
int mt8192_apll2_enable(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
/* setting for APLL */
apll2_mux_setting(afe, true);
ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_APLL24M], ret);
goto EXIT;
}
ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
if (ret) {
dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
__func__, aud_clks[CLK_APLL2_TUNER], ret);
goto EXIT;
}
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
0x0000FFF7, 0x00000634);
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_24M_ON_MASK_SFT,
0x1 << AFE_24M_ON_SFT);
EXIT:
return ret;
}
void mt8192_apll2_disable(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
AFE_24M_ON_MASK_SFT,
0x0 << AFE_24M_ON_SFT);
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
apll2_mux_setting(afe, false);
}
int mt8192_get_apll_rate(struct mtk_base_afe *afe, int apll)
{
return (apll == MT8192_APLL1) ? 180633600 : 196608000;
}
int mt8192_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
{
return ((rate % 8000) == 0) ? MT8192_APLL2 : MT8192_APLL1;
}
int mt8192_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
{
if (strcmp(name, APLL1_W_NAME) == 0)
return MT8192_APLL1;
else
return MT8192_APLL2;
}
/* mck */
struct mt8192_mck_div {
int m_sel_id;
int div_clk_id;
/* below will be deprecated */
int div_pdn_reg;
int div_pdn_mask_sft;
int div_reg;
int div_mask_sft;
int div_mask;
int div_sft;
int div_apll_sel_reg;
int div_apll_sel_mask_sft;
int div_apll_sel_sft;
};
static const struct mt8192_mck_div mck_div[MT8192_MCK_NUM] = {
[MT8192_I2S0_MCK] = {
.m_sel_id = CLK_TOP_I2S0_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV0,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV0_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_2,
.div_mask_sft = APLL12_CK_DIV0_MASK_SFT,
.div_mask = APLL12_CK_DIV0_MASK,
.div_sft = APLL12_CK_DIV0_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S0_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S0_MCK_SEL_SFT,
},
[MT8192_I2S1_MCK] = {
.m_sel_id = CLK_TOP_I2S1_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV1,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV1_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_2,
.div_mask_sft = APLL12_CK_DIV1_MASK_SFT,
.div_mask = APLL12_CK_DIV1_MASK,
.div_sft = APLL12_CK_DIV1_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S1_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S1_MCK_SEL_SFT,
},
[MT8192_I2S2_MCK] = {
.m_sel_id = CLK_TOP_I2S2_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV2,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV2_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_2,
.div_mask_sft = APLL12_CK_DIV2_MASK_SFT,
.div_mask = APLL12_CK_DIV2_MASK,
.div_sft = APLL12_CK_DIV2_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S2_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S2_MCK_SEL_SFT,
},
[MT8192_I2S3_MCK] = {
.m_sel_id = CLK_TOP_I2S3_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV3,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV3_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_2,
.div_mask_sft = APLL12_CK_DIV3_MASK_SFT,
.div_mask = APLL12_CK_DIV3_MASK,
.div_sft = APLL12_CK_DIV3_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S3_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S3_MCK_SEL_SFT,
},
[MT8192_I2S4_MCK] = {
.m_sel_id = CLK_TOP_I2S4_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV4,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV4_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_3,
.div_mask_sft = APLL12_CK_DIV4_MASK_SFT,
.div_mask = APLL12_CK_DIV4_MASK,
.div_sft = APLL12_CK_DIV4_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S4_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S4_MCK_SEL_SFT,
},
[MT8192_I2S4_BCK] = {
.m_sel_id = -1,
.div_clk_id = CLK_TOP_APLL12_DIVB,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIVB_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_2,
.div_mask_sft = APLL12_CK_DIVB_MASK_SFT,
.div_mask = APLL12_CK_DIVB_MASK,
.div_sft = APLL12_CK_DIVB_SFT,
},
[MT8192_I2S5_MCK] = {
.m_sel_id = CLK_TOP_I2S5_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV5,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV5_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_3,
.div_mask_sft = APLL12_CK_DIV5_MASK_SFT,
.div_mask = APLL12_CK_DIV5_MASK,
.div_sft = APLL12_CK_DIV5_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S5_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S5_MCK_SEL_SFT,
},
[MT8192_I2S6_MCK] = {
.m_sel_id = CLK_TOP_I2S6_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV6,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV6_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_3,
.div_mask_sft = APLL12_CK_DIV6_MASK_SFT,
.div_mask = APLL12_CK_DIV6_MASK,
.div_sft = APLL12_CK_DIV6_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S6_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S6_MCK_SEL_SFT,
},
[MT8192_I2S7_MCK] = {
.m_sel_id = CLK_TOP_I2S7_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV7,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV7_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_4,
.div_mask_sft = APLL12_CK_DIV7_MASK_SFT,
.div_mask = APLL12_CK_DIV7_MASK,
.div_sft = APLL12_CK_DIV7_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S7_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S7_MCK_SEL_SFT,
},
[MT8192_I2S8_MCK] = {
.m_sel_id = CLK_TOP_I2S8_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV8,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV8_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_4,
.div_mask_sft = APLL12_CK_DIV8_MASK_SFT,
.div_mask = APLL12_CK_DIV8_MASK,
.div_sft = APLL12_CK_DIV8_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S8_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S8_MCK_SEL_SFT,
},
[MT8192_I2S9_MCK] = {
.m_sel_id = CLK_TOP_I2S9_M_SEL,
.div_clk_id = CLK_TOP_APLL12_DIV9,
.div_pdn_reg = CLK_AUDDIV_0,
.div_pdn_mask_sft = APLL12_DIV9_PDN_MASK_SFT,
.div_reg = CLK_AUDDIV_4,
.div_mask_sft = APLL12_CK_DIV9_MASK_SFT,
.div_mask = APLL12_CK_DIV9_MASK,
.div_sft = APLL12_CK_DIV9_SFT,
.div_apll_sel_reg = CLK_AUDDIV_0,
.div_apll_sel_mask_sft = APLL_I2S9_MCK_SEL_MASK_SFT,
.div_apll_sel_sft = APLL_I2S9_MCK_SEL_SFT,
},
};
int mt8192_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int apll = mt8192_get_apll_by_rate(afe, rate);
int apll_clk_id = apll == MT8192_APLL1 ?
CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
int m_sel_id = mck_div[mck_id].m_sel_id;
int div_clk_id = mck_div[mck_id].div_clk_id;
int ret;
/* select apll */
if (m_sel_id >= 0) {
ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
if (ret) {
dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
__func__, aud_clks[m_sel_id], ret);
return ret;
}
ret = clk_set_parent(afe_priv->clk[m_sel_id],
afe_priv->clk[apll_clk_id]);
if (ret) {
dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[m_sel_id],
aud_clks[apll_clk_id], ret);
return ret;
}
}
/* enable div, set rate */
ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
if (ret) {
dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
__func__, aud_clks[div_clk_id], ret);
return ret;
}
ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
if (ret) {
dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
__func__, aud_clks[div_clk_id],
rate, ret);
return ret;
}
return 0;
}
void mt8192_mck_disable(struct mtk_base_afe *afe, int mck_id)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int m_sel_id = mck_div[mck_id].m_sel_id;
int div_clk_id = mck_div[mck_id].div_clk_id;
clk_disable_unprepare(afe_priv->clk[div_clk_id]);
if (m_sel_id >= 0)
clk_disable_unprepare(afe_priv->clk[m_sel_id]);
}
int mt8192_init_clock(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct device_node *of_node = afe->dev->of_node;
int i = 0;
afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
GFP_KERNEL);
if (!afe_priv->clk)
return -ENOMEM;
for (i = 0; i < CLK_NUM; i++) {
afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
if (IS_ERR(afe_priv->clk[i])) {
dev_warn(afe->dev, "%s devm_clk_get %s fail, ret %ld\n",
__func__,
aud_clks[i], PTR_ERR(afe_priv->clk[i]));
afe_priv->clk[i] = NULL;
}
}
afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node,
"mediatek,apmixedsys");
if (IS_ERR(afe_priv->apmixedsys)) {
dev_err(afe->dev, "%s() Cannot find apmixedsys controller: %ld\n",
__func__, PTR_ERR(afe_priv->apmixedsys));
return PTR_ERR(afe_priv->apmixedsys);
}
afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node,
"mediatek,topckgen");
if (IS_ERR(afe_priv->topckgen)) {
dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
__func__, PTR_ERR(afe_priv->topckgen));
return PTR_ERR(afe_priv->topckgen);
}
afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node,
"mediatek,infracfg");
if (IS_ERR(afe_priv->infracfg)) {
dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n",
__func__, PTR_ERR(afe_priv->infracfg));
return PTR_ERR(afe_priv->infracfg);
}
return 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* mt8192-afe-clk.h -- Mediatek 8192 afe clock ctrl definition
*
* Copyright (c) 2020 MediaTek Inc.
* Author: Shane Chien <shane.chien@mediatek.com>
*/
#ifndef _MT8192_AFE_CLOCK_CTRL_H_
#define _MT8192_AFE_CLOCK_CTRL_H_
#define AP_PLL_CON3 0x0014
#define APLL1_CON0 0x0318
#define APLL1_CON1 0x031c
#define APLL1_CON2 0x0320
#define APLL1_CON4 0x0328
#define APLL1_TUNER_CON0 0x0040
#define APLL2_CON0 0x032c
#define APLL2_CON1 0x0330
#define APLL2_CON2 0x0334
#define APLL2_CON4 0x033c
#define APLL2_TUNER_CON0 0x0044
#define CLK_CFG_7 0x0080
#define CLK_CFG_8 0x0090
#define CLK_CFG_11 0x00c0
#define CLK_CFG_12 0x00d0
#define CLK_CFG_13 0x00e0
#define CLK_CFG_15 0x0100
#define CLK_AUDDIV_0 0x0320
#define CLK_AUDDIV_2 0x0328
#define CLK_AUDDIV_3 0x0334
#define CLK_AUDDIV_4 0x0338
#define CKSYS_AUD_TOP_CFG 0x032c
#define CKSYS_AUD_TOP_MON 0x0330
#define PERI_BUS_DCM_CTRL 0x0074
#define MODULE_SW_CG_1_STA 0x0094
#define MODULE_SW_CG_2_STA 0x00ac
/* CLK_AUDDIV_0 */
#define APLL12_DIV0_PDN_SFT 0
#define APLL12_DIV0_PDN_MASK 0x1
#define APLL12_DIV0_PDN_MASK_SFT (0x1 << 0)
#define APLL12_DIV1_PDN_SFT 1
#define APLL12_DIV1_PDN_MASK 0x1
#define APLL12_DIV1_PDN_MASK_SFT (0x1 << 1)
#define APLL12_DIV2_PDN_SFT 2
#define APLL12_DIV2_PDN_MASK 0x1
#define APLL12_DIV2_PDN_MASK_SFT (0x1 << 2)
#define APLL12_DIV3_PDN_SFT 3
#define APLL12_DIV3_PDN_MASK 0x1
#define APLL12_DIV3_PDN_MASK_SFT (0x1 << 3)
#define APLL12_DIV4_PDN_SFT 4
#define APLL12_DIV4_PDN_MASK 0x1
#define APLL12_DIV4_PDN_MASK_SFT (0x1 << 4)
#define APLL12_DIVB_PDN_SFT 5
#define APLL12_DIVB_PDN_MASK 0x1
#define APLL12_DIVB_PDN_MASK_SFT (0x1 << 5)
#define APLL12_DIV5_PDN_SFT 6
#define APLL12_DIV5_PDN_MASK 0x1
#define APLL12_DIV5_PDN_MASK_SFT (0x1 << 6)
#define APLL12_DIV6_PDN_SFT 7
#define APLL12_DIV6_PDN_MASK 0x1
#define APLL12_DIV6_PDN_MASK_SFT (0x1 << 7)
#define APLL12_DIV7_PDN_SFT 8
#define APLL12_DIV7_PDN_MASK 0x1
#define APLL12_DIV7_PDN_MASK_SFT (0x1 << 8)
#define APLL12_DIV8_PDN_SFT 9
#define APLL12_DIV8_PDN_MASK 0x1
#define APLL12_DIV8_PDN_MASK_SFT (0x1 << 9)
#define APLL12_DIV9_PDN_SFT 10
#define APLL12_DIV9_PDN_MASK 0x1
#define APLL12_DIV9_PDN_MASK_SFT (0x1 << 10)
#define APLL_I2S0_MCK_SEL_SFT 16
#define APLL_I2S0_MCK_SEL_MASK 0x1
#define APLL_I2S0_MCK_SEL_MASK_SFT (0x1 << 16)
#define APLL_I2S1_MCK_SEL_SFT 17
#define APLL_I2S1_MCK_SEL_MASK 0x1
#define APLL_I2S1_MCK_SEL_MASK_SFT (0x1 << 17)
#define APLL_I2S2_MCK_SEL_SFT 18
#define APLL_I2S2_MCK_SEL_MASK 0x1
#define APLL_I2S2_MCK_SEL_MASK_SFT (0x1 << 18)
#define APLL_I2S3_MCK_SEL_SFT 19
#define APLL_I2S3_MCK_SEL_MASK 0x1
#define APLL_I2S3_MCK_SEL_MASK_SFT (0x1 << 19)
#define APLL_I2S4_MCK_SEL_SFT 20
#define APLL_I2S4_MCK_SEL_MASK 0x1
#define APLL_I2S4_MCK_SEL_MASK_SFT (0x1 << 20)
#define APLL_I2S5_MCK_SEL_SFT 21
#define APLL_I2S5_MCK_SEL_MASK 0x1
#define APLL_I2S5_MCK_SEL_MASK_SFT (0x1 << 21)
#define APLL_I2S6_MCK_SEL_SFT 22
#define APLL_I2S6_MCK_SEL_MASK 0x1
#define APLL_I2S6_MCK_SEL_MASK_SFT (0x1 << 22)
#define APLL_I2S7_MCK_SEL_SFT 23
#define APLL_I2S7_MCK_SEL_MASK 0x1
#define APLL_I2S7_MCK_SEL_MASK_SFT (0x1 << 23)
#define APLL_I2S8_MCK_SEL_SFT 24
#define APLL_I2S8_MCK_SEL_MASK 0x1
#define APLL_I2S8_MCK_SEL_MASK_SFT (0x1 << 24)
#define APLL_I2S9_MCK_SEL_SFT 25
#define APLL_I2S9_MCK_SEL_MASK 0x1
#define APLL_I2S9_MCK_SEL_MASK_SFT (0x1 << 25)
/* CLK_AUDDIV_2 */
#define APLL12_CK_DIV0_SFT 0
#define APLL12_CK_DIV0_MASK 0xff
#define APLL12_CK_DIV0_MASK_SFT (0xff << 0)
#define APLL12_CK_DIV1_SFT 8
#define APLL12_CK_DIV1_MASK 0xff
#define APLL12_CK_DIV1_MASK_SFT (0xff << 8)
#define APLL12_CK_DIV2_SFT 16
#define APLL12_CK_DIV2_MASK 0xff
#define APLL12_CK_DIV2_MASK_SFT (0xff << 16)
#define APLL12_CK_DIV3_SFT 24
#define APLL12_CK_DIV3_MASK 0xff
#define APLL12_CK_DIV3_MASK_SFT (0xff << 24)
/* CLK_AUDDIV_3 */
#define APLL12_CK_DIV4_SFT 0
#define APLL12_CK_DIV4_MASK 0xff
#define APLL12_CK_DIV4_MASK_SFT (0xff << 0)
#define APLL12_CK_DIVB_SFT 8
#define APLL12_CK_DIVB_MASK 0xff
#define APLL12_CK_DIVB_MASK_SFT (0xff << 8)
#define APLL12_CK_DIV5_SFT 16
#define APLL12_CK_DIV5_MASK 0xff
#define APLL12_CK_DIV5_MASK_SFT (0xff << 16)
#define APLL12_CK_DIV6_SFT 24
#define APLL12_CK_DIV6_MASK 0xff
#define APLL12_CK_DIV6_MASK_SFT (0xff << 24)
/* CLK_AUDDIV_4 */
#define APLL12_CK_DIV7_SFT 0
#define APLL12_CK_DIV7_MASK 0xff
#define APLL12_CK_DIV7_MASK_SFT (0xff << 0)
#define APLL12_CK_DIV8_SFT 8
#define APLL12_CK_DIV8_MASK 0xff
#define APLL12_CK_DIV8_MASK_SFT (0xff << 0)
#define APLL12_CK_DIV9_SFT 16
#define APLL12_CK_DIV9_MASK 0xff
#define APLL12_CK_DIV9_MASK_SFT (0xff << 0)
/* AUD_TOP_CFG */
#define AUD_TOP_CFG_SFT 0
#define AUD_TOP_CFG_MASK 0xffffffff
#define AUD_TOP_CFG_MASK_SFT (0xffffffff << 0)
/* AUD_TOP_MON */
#define AUD_TOP_MON_SFT 0
#define AUD_TOP_MON_MASK 0xffffffff
#define AUD_TOP_MON_MASK_SFT (0xffffffff << 0)
/* CLK_AUDDIV_3 */
#define APLL12_CK_DIV5_MSB_SFT 0
#define APLL12_CK_DIV5_MSB_MASK 0xf
#define APLL12_CK_DIV5_MSB_MASK_SFT (0xf << 0)
#define RESERVED0_SFT 4
#define RESERVED0_MASK 0xfffffff
#define RESERVED0_MASK_SFT (0xfffffff << 4)
/* APLL */
#define APLL1_W_NAME "APLL1"
#define APLL2_W_NAME "APLL2"
enum {
MT8192_APLL1 = 0,
MT8192_APLL2,
};
enum {
CLK_AFE = 0,
CLK_TML,
CLK_APLL22M,
CLK_APLL24M,
CLK_APLL1_TUNER,
CLK_APLL2_TUNER,
CLK_NLE,
CLK_INFRA_SYS_AUDIO,
CLK_INFRA_AUDIO_26M,
CLK_MUX_AUDIO,
CLK_MUX_AUDIOINTBUS,
CLK_TOP_MAINPLL_D4_D4,
/* apll related mux */
CLK_TOP_MUX_AUD_1,
CLK_TOP_APLL1_CK,
CLK_TOP_MUX_AUD_2,
CLK_TOP_APLL2_CK,
CLK_TOP_MUX_AUD_ENG1,
CLK_TOP_APLL1_D4,
CLK_TOP_MUX_AUD_ENG2,
CLK_TOP_APLL2_D4,
CLK_TOP_MUX_AUDIO_H,
CLK_TOP_I2S0_M_SEL,
CLK_TOP_I2S1_M_SEL,
CLK_TOP_I2S2_M_SEL,
CLK_TOP_I2S3_M_SEL,
CLK_TOP_I2S4_M_SEL,
CLK_TOP_I2S5_M_SEL,
CLK_TOP_I2S6_M_SEL,
CLK_TOP_I2S7_M_SEL,
CLK_TOP_I2S8_M_SEL,
CLK_TOP_I2S9_M_SEL,
CLK_TOP_APLL12_DIV0,
CLK_TOP_APLL12_DIV1,
CLK_TOP_APLL12_DIV2,
CLK_TOP_APLL12_DIV3,
CLK_TOP_APLL12_DIV4,
CLK_TOP_APLL12_DIVB,
CLK_TOP_APLL12_DIV5,
CLK_TOP_APLL12_DIV6,
CLK_TOP_APLL12_DIV7,
CLK_TOP_APLL12_DIV8,
CLK_TOP_APLL12_DIV9,
CLK_CLK26M,
CLK_NUM
};
struct mtk_base_afe;
int mt8192_init_clock(struct mtk_base_afe *afe);
int mt8192_afe_enable_clock(struct mtk_base_afe *afe);
void mt8192_afe_disable_clock(struct mtk_base_afe *afe);
int mt8192_apll1_enable(struct mtk_base_afe *afe);
void mt8192_apll1_disable(struct mtk_base_afe *afe);
int mt8192_apll2_enable(struct mtk_base_afe *afe);
void mt8192_apll2_disable(struct mtk_base_afe *afe);
int mt8192_get_apll_rate(struct mtk_base_afe *afe, int apll);
int mt8192_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
int mt8192_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
/* these will be replaced by using CCF */
int mt8192_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
void mt8192_mck_disable(struct mtk_base_afe *afe, int mck_id);
int mt8192_set_audio_int_bus_parent(struct mtk_base_afe *afe,
int clk_id);
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* mt8192-afe-common.h -- Mediatek 8192 audio driver definitions
*
* Copyright (c) 2020 MediaTek Inc.
* Author: Shane Chien <shane.chien@mediatek.com>
*/
#ifndef _MT_8192_AFE_COMMON_H_
#define _MT_8192_AFE_COMMON_H_
#include <linux/list.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "../common/mtk-base-afe.h"
#include "mt8192-reg.h"
enum {
MT8192_MEMIF_DL1,
MT8192_MEMIF_DL12,
MT8192_MEMIF_DL2,
MT8192_MEMIF_DL3,
MT8192_MEMIF_DL4,
MT8192_MEMIF_DL5,
MT8192_MEMIF_DL6,
MT8192_MEMIF_DL7,
MT8192_MEMIF_DL8,
MT8192_MEMIF_DL9,
MT8192_MEMIF_DAI,
MT8192_MEMIF_DAI2,
MT8192_MEMIF_MOD_DAI,
MT8192_MEMIF_VUL12,
MT8192_MEMIF_VUL2,
MT8192_MEMIF_VUL3,
MT8192_MEMIF_VUL4,
MT8192_MEMIF_VUL5,
MT8192_MEMIF_VUL6,
MT8192_MEMIF_AWB,
MT8192_MEMIF_AWB2,
MT8192_MEMIF_HDMI,
MT8192_MEMIF_NUM,
MT8192_DAI_ADDA = MT8192_MEMIF_NUM,
MT8192_DAI_ADDA_CH34,
MT8192_DAI_AP_DMIC,
MT8192_DAI_AP_DMIC_CH34,
MT8192_DAI_VOW,
MT8192_DAI_CONNSYS_I2S,
MT8192_DAI_I2S_0,
MT8192_DAI_I2S_1,
MT8192_DAI_I2S_2,
MT8192_DAI_I2S_3,
MT8192_DAI_I2S_5,
MT8192_DAI_I2S_6,
MT8192_DAI_I2S_7,
MT8192_DAI_I2S_8,
MT8192_DAI_I2S_9,
MT8192_DAI_HW_GAIN_1,
MT8192_DAI_HW_GAIN_2,
MT8192_DAI_SRC_1,
MT8192_DAI_SRC_2,
MT8192_DAI_PCM_1,
MT8192_DAI_PCM_2,
MT8192_DAI_TDM,
MT8192_DAI_NUM,
};
enum {
MT8192_IRQ_0,
MT8192_IRQ_1,
MT8192_IRQ_2,
MT8192_IRQ_3,
MT8192_IRQ_4,
MT8192_IRQ_5,
MT8192_IRQ_6,
MT8192_IRQ_7,
MT8192_IRQ_8,
MT8192_IRQ_9,
MT8192_IRQ_10,
MT8192_IRQ_11,
MT8192_IRQ_12,
MT8192_IRQ_13,
MT8192_IRQ_14,
MT8192_IRQ_15,
MT8192_IRQ_16,
MT8192_IRQ_17,
MT8192_IRQ_18,
MT8192_IRQ_19,
MT8192_IRQ_20,
MT8192_IRQ_21,
MT8192_IRQ_22,
MT8192_IRQ_23,
MT8192_IRQ_24,
MT8192_IRQ_25,
MT8192_IRQ_26,
MT8192_IRQ_31, /* used only for TDM */
MT8192_IRQ_NUM,
};
enum {
MTKAIF_PROTOCOL_1 = 0,
MTKAIF_PROTOCOL_2,
MTKAIF_PROTOCOL_2_CLK_P2,
};
enum {
MTK_AFE_ADDA_DL_GAIN_MUTE = 0,
MTK_AFE_ADDA_DL_GAIN_NORMAL = 0xf74f,
/* SA suggest apply -0.3db to audio/speech path */
};
/* MCLK */
enum {
MT8192_I2S0_MCK = 0,
MT8192_I2S1_MCK,
MT8192_I2S2_MCK,
MT8192_I2S3_MCK,
MT8192_I2S4_MCK,
MT8192_I2S4_BCK,
MT8192_I2S5_MCK,
MT8192_I2S6_MCK,
MT8192_I2S7_MCK,
MT8192_I2S8_MCK,
MT8192_I2S9_MCK,
MT8192_MCK_NUM,
};
struct clk;
struct mt8192_afe_private {
struct clk **clk;
struct regmap *topckgen;
struct regmap *apmixedsys;
struct regmap *infracfg;
int stf_positive_gain_db;
int pm_runtime_bypass_reg_ctl;
/* dai */
bool dai_on[MT8192_DAI_NUM];
void *dai_priv[MT8192_DAI_NUM];
/* adda */
int mtkaif_protocol;
int mtkaif_chosen_phase[4];
int mtkaif_phase_cycle[4];
int mtkaif_calibration_num_phase;
int mtkaif_dmic;
int mtkaif_dmic_ch34;
int mtkaif_adda6_only;
/* mck */
int mck_rate[MT8192_MCK_NUM];
};
int mt8192_dai_adda_register(struct mtk_base_afe *afe);
int mt8192_dai_i2s_register(struct mtk_base_afe *afe);
int mt8192_dai_hw_gain_register(struct mtk_base_afe *afe);
int mt8192_dai_src_register(struct mtk_base_afe *afe);
int mt8192_dai_pcm_register(struct mtk_base_afe *afe);
int mt8192_dai_tdm_register(struct mtk_base_afe *afe);
unsigned int mt8192_general_rate_transform(struct device *dev,
unsigned int rate);
unsigned int mt8192_rate_transform(struct device *dev,
unsigned int rate, int aud_blk);
int mt8192_dai_set_priv(struct mtk_base_afe *afe, int id,
int priv_size, const void *priv_data);
#endif
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio Control
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/pm_runtime.h>
#include "mt8192-afe-common.h"
enum {
MTK_AFE_RATE_8K = 0,
MTK_AFE_RATE_11K = 1,
MTK_AFE_RATE_12K = 2,
MTK_AFE_RATE_384K = 3,
MTK_AFE_RATE_16K = 4,
MTK_AFE_RATE_22K = 5,
MTK_AFE_RATE_24K = 6,
MTK_AFE_RATE_352K = 7,
MTK_AFE_RATE_32K = 8,
MTK_AFE_RATE_44K = 9,
MTK_AFE_RATE_48K = 10,
MTK_AFE_RATE_88K = 11,
MTK_AFE_RATE_96K = 12,
MTK_AFE_RATE_176K = 13,
MTK_AFE_RATE_192K = 14,
MTK_AFE_RATE_260K = 15,
};
enum {
MTK_AFE_DAI_MEMIF_RATE_8K = 0,
MTK_AFE_DAI_MEMIF_RATE_16K = 1,
MTK_AFE_DAI_MEMIF_RATE_32K = 2,
MTK_AFE_DAI_MEMIF_RATE_48K = 3,
};
enum {
MTK_AFE_PCM_RATE_8K = 0,
MTK_AFE_PCM_RATE_16K = 1,
MTK_AFE_PCM_RATE_32K = 2,
MTK_AFE_PCM_RATE_48K = 3,
};
unsigned int mt8192_general_rate_transform(struct device *dev,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_RATE_8K;
case 11025:
return MTK_AFE_RATE_11K;
case 12000:
return MTK_AFE_RATE_12K;
case 16000:
return MTK_AFE_RATE_16K;
case 22050:
return MTK_AFE_RATE_22K;
case 24000:
return MTK_AFE_RATE_24K;
case 32000:
return MTK_AFE_RATE_32K;
case 44100:
return MTK_AFE_RATE_44K;
case 48000:
return MTK_AFE_RATE_48K;
case 88200:
return MTK_AFE_RATE_88K;
case 96000:
return MTK_AFE_RATE_96K;
case 176400:
return MTK_AFE_RATE_176K;
case 192000:
return MTK_AFE_RATE_192K;
case 260000:
return MTK_AFE_RATE_260K;
case 352800:
return MTK_AFE_RATE_352K;
case 384000:
return MTK_AFE_RATE_384K;
default:
dev_warn(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__,
rate, MTK_AFE_RATE_48K);
return MTK_AFE_RATE_48K;
}
}
static unsigned int dai_memif_rate_transform(struct device *dev,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_DAI_MEMIF_RATE_8K;
case 16000:
return MTK_AFE_DAI_MEMIF_RATE_16K;
case 32000:
return MTK_AFE_DAI_MEMIF_RATE_32K;
case 48000:
return MTK_AFE_DAI_MEMIF_RATE_48K;
default:
dev_warn(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__,
rate, MTK_AFE_DAI_MEMIF_RATE_16K);
return MTK_AFE_DAI_MEMIF_RATE_16K;
}
}
static unsigned int pcm_rate_transform(struct device *dev,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_PCM_RATE_8K;
case 16000:
return MTK_AFE_PCM_RATE_16K;
case 32000:
return MTK_AFE_PCM_RATE_32K;
case 48000:
return MTK_AFE_PCM_RATE_48K;
default:
dev_warn(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__,
rate, MTK_AFE_PCM_RATE_32K);
return MTK_AFE_PCM_RATE_32K;
}
}
unsigned int mt8192_rate_transform(struct device *dev,
unsigned int rate, int aud_blk)
{
switch (aud_blk) {
case MT8192_MEMIF_DAI:
case MT8192_MEMIF_MOD_DAI:
return dai_memif_rate_transform(dev, rate);
case MT8192_DAI_PCM_1:
case MT8192_DAI_PCM_2:
return pcm_rate_transform(dev, rate);
default:
return mt8192_general_rate_transform(dev, rate);
}
}
int mt8192_dai_set_priv(struct mtk_base_afe *afe, int id,
int priv_size, const void *priv_data)
{
struct mt8192_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;
}
// SPDX-License-Identifier: GPL-2.0
//
// mt8192-afe-gpio.c -- Mediatek 8192 afe gpio ctrl
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include "mt8192-afe-common.h"
#include "mt8192-afe-gpio.h"
struct pinctrl *aud_pinctrl;
enum mt8192_afe_gpio {
MT8192_AFE_GPIO_DAT_MISO_OFF,
MT8192_AFE_GPIO_DAT_MISO_ON,
MT8192_AFE_GPIO_DAT_MOSI_OFF,
MT8192_AFE_GPIO_DAT_MOSI_ON,
MT8192_AFE_GPIO_DAT_MISO_CH34_OFF,
MT8192_AFE_GPIO_DAT_MISO_CH34_ON,
MT8192_AFE_GPIO_DAT_MOSI_CH34_OFF,
MT8192_AFE_GPIO_DAT_MOSI_CH34_ON,
MT8192_AFE_GPIO_I2S0_OFF,
MT8192_AFE_GPIO_I2S0_ON,
MT8192_AFE_GPIO_I2S1_OFF,
MT8192_AFE_GPIO_I2S1_ON,
MT8192_AFE_GPIO_I2S2_OFF,
MT8192_AFE_GPIO_I2S2_ON,
MT8192_AFE_GPIO_I2S3_OFF,
MT8192_AFE_GPIO_I2S3_ON,
MT8192_AFE_GPIO_I2S5_OFF,
MT8192_AFE_GPIO_I2S5_ON,
MT8192_AFE_GPIO_I2S6_OFF,
MT8192_AFE_GPIO_I2S6_ON,
MT8192_AFE_GPIO_I2S7_OFF,
MT8192_AFE_GPIO_I2S7_ON,
MT8192_AFE_GPIO_I2S8_OFF,
MT8192_AFE_GPIO_I2S8_ON,
MT8192_AFE_GPIO_I2S9_OFF,
MT8192_AFE_GPIO_I2S9_ON,
MT8192_AFE_GPIO_VOW_DAT_OFF,
MT8192_AFE_GPIO_VOW_DAT_ON,
MT8192_AFE_GPIO_VOW_CLK_OFF,
MT8192_AFE_GPIO_VOW_CLK_ON,
MT8192_AFE_GPIO_CLK_MOSI_OFF,
MT8192_AFE_GPIO_CLK_MOSI_ON,
MT8192_AFE_GPIO_TDM_OFF,
MT8192_AFE_GPIO_TDM_ON,
MT8192_AFE_GPIO_GPIO_NUM
};
struct audio_gpio_attr {
const char *name;
bool gpio_prepare;
struct pinctrl_state *gpioctrl;
};
static struct audio_gpio_attr aud_gpios[MT8192_AFE_GPIO_GPIO_NUM] = {
[MT8192_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL},
[MT8192_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL},
[MT8192_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL},
[MT8192_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL},
[MT8192_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL},
[MT8192_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL},
[MT8192_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL},
[MT8192_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL},
[MT8192_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL},
[MT8192_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL},
[MT8192_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL},
[MT8192_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL},
[MT8192_AFE_GPIO_I2S5_OFF] = {"aud_gpio_i2s5_off", false, NULL},
[MT8192_AFE_GPIO_I2S5_ON] = {"aud_gpio_i2s5_on", false, NULL},
[MT8192_AFE_GPIO_I2S6_OFF] = {"aud_gpio_i2s6_off", false, NULL},
[MT8192_AFE_GPIO_I2S6_ON] = {"aud_gpio_i2s6_on", false, NULL},
[MT8192_AFE_GPIO_I2S7_OFF] = {"aud_gpio_i2s7_off", false, NULL},
[MT8192_AFE_GPIO_I2S7_ON] = {"aud_gpio_i2s7_on", false, NULL},
[MT8192_AFE_GPIO_I2S8_OFF] = {"aud_gpio_i2s8_off", false, NULL},
[MT8192_AFE_GPIO_I2S8_ON] = {"aud_gpio_i2s8_on", false, NULL},
[MT8192_AFE_GPIO_I2S9_OFF] = {"aud_gpio_i2s9_off", false, NULL},
[MT8192_AFE_GPIO_I2S9_ON] = {"aud_gpio_i2s9_on", false, NULL},
[MT8192_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL},
[MT8192_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL},
[MT8192_AFE_GPIO_VOW_DAT_OFF] = {"vow_dat_miso_off", false, NULL},
[MT8192_AFE_GPIO_VOW_DAT_ON] = {"vow_dat_miso_on", false, NULL},
[MT8192_AFE_GPIO_VOW_CLK_OFF] = {"vow_clk_miso_off", false, NULL},
[MT8192_AFE_GPIO_VOW_CLK_ON] = {"vow_clk_miso_on", false, NULL},
[MT8192_AFE_GPIO_DAT_MISO_CH34_OFF] = {"aud_dat_miso_ch34_off",
false, NULL},
[MT8192_AFE_GPIO_DAT_MISO_CH34_ON] = {"aud_dat_miso_ch34_on",
false, NULL},
[MT8192_AFE_GPIO_DAT_MOSI_CH34_OFF] = {"aud_dat_mosi_ch34_off",
false, NULL},
[MT8192_AFE_GPIO_DAT_MOSI_CH34_ON] = {"aud_dat_mosi_ch34_on",
false, NULL},
[MT8192_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL},
[MT8192_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL},
};
static DEFINE_MUTEX(gpio_request_mutex);
static int mt8192_afe_gpio_select(struct device *dev,
enum mt8192_afe_gpio type)
{
int ret;
if (type < 0 || type >= MT8192_AFE_GPIO_GPIO_NUM) {
dev_err(dev, "%s(), error, invalid gpio type %d\n",
__func__, type);
return -EINVAL;
}
if (!aud_gpios[type].gpio_prepare) {
dev_warn(dev, "%s(), error, gpio type %d not prepared\n",
__func__, type);
return -EIO;
}
ret = pinctrl_select_state(aud_pinctrl,
aud_gpios[type].gpioctrl);
if (ret) {
dev_dbg(dev, "%s(), error, can not set gpio type %d\n",
__func__, type);
}
return ret;
}
int mt8192_afe_gpio_init(struct device *dev)
{
int i, ret;
aud_pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(aud_pinctrl)) {
ret = PTR_ERR(aud_pinctrl);
dev_err(dev, "%s(), ret %d, cannot get aud_pinctrl!\n",
__func__, ret);
return ret;
}
for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl,
aud_gpios[i].name);
if (IS_ERR(aud_gpios[i].gpioctrl)) {
ret = PTR_ERR(aud_gpios[i].gpioctrl);
dev_dbg(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n",
__func__, aud_gpios[i].name, ret);
} else {
aud_gpios[i].gpio_prepare = true;
}
}
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_CLK_MOSI_ON);
/* gpio status init */
mt8192_afe_gpio_request(dev, false, MT8192_DAI_ADDA, 0);
mt8192_afe_gpio_request(dev, false, MT8192_DAI_ADDA, 1);
return 0;
}
static int mt8192_afe_gpio_adda_dl(struct device *dev, bool enable)
{
if (enable) {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MOSI_ON);
} else {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MOSI_OFF);
}
}
static int mt8192_afe_gpio_adda_ul(struct device *dev, bool enable)
{
if (enable) {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MISO_ON);
} else {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MISO_OFF);
}
}
static int mt8192_afe_gpio_adda_ch34_dl(struct device *dev, bool enable)
{
if (enable) {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MOSI_CH34_ON);
} else {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MOSI_CH34_OFF);
}
}
static int mt8192_afe_gpio_adda_ch34_ul(struct device *dev, bool enable)
{
if (enable) {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MISO_CH34_ON);
} else {
return mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_DAT_MISO_CH34_OFF);
}
}
int mt8192_afe_gpio_request(struct device *dev, bool enable,
int dai, int uplink)
{
mutex_lock(&gpio_request_mutex);
switch (dai) {
case MT8192_DAI_ADDA:
if (uplink)
mt8192_afe_gpio_adda_ul(dev, enable);
else
mt8192_afe_gpio_adda_dl(dev, enable);
break;
case MT8192_DAI_ADDA_CH34:
if (uplink)
mt8192_afe_gpio_adda_ch34_ul(dev, enable);
else
mt8192_afe_gpio_adda_ch34_dl(dev, enable);
break;
case MT8192_DAI_I2S_0:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S0_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S0_OFF);
break;
case MT8192_DAI_I2S_1:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S1_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S1_OFF);
break;
case MT8192_DAI_I2S_2:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S2_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S2_OFF);
break;
case MT8192_DAI_I2S_3:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S3_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S3_OFF);
break;
case MT8192_DAI_I2S_5:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S5_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S5_OFF);
break;
case MT8192_DAI_I2S_6:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S6_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S6_OFF);
break;
case MT8192_DAI_I2S_7:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S7_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S7_OFF);
break;
case MT8192_DAI_I2S_8:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S8_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S8_OFF);
break;
case MT8192_DAI_I2S_9:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S9_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_I2S9_OFF);
break;
case MT8192_DAI_TDM:
if (enable)
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_TDM_ON);
else
mt8192_afe_gpio_select(dev, MT8192_AFE_GPIO_TDM_OFF);
break;
case MT8192_DAI_VOW:
if (enable) {
mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_VOW_CLK_ON);
mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_VOW_DAT_ON);
} else {
mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_VOW_CLK_OFF);
mt8192_afe_gpio_select(dev,
MT8192_AFE_GPIO_VOW_DAT_OFF);
}
break;
default:
mutex_unlock(&gpio_request_mutex);
dev_warn(dev, "%s(), invalid dai %d\n", __func__, dai);
return -EINVAL;
}
mutex_unlock(&gpio_request_mutex);
return 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* mt8192-afe-gpio.h -- Mediatek 8192 afe gpio ctrl definition
*
* Copyright (c) 2020 MediaTek Inc.
* Author: Shane Chien <shane.chien@mediatek.com>
*/
#ifndef _MT8192_AFE_GPIO_H_
#define _MT8192_AFE_GPIO_H_
struct device;
int mt8192_afe_gpio_init(struct device *dev);
int mt8192_afe_gpio_request(struct device *dev, bool enable,
int dai, int uplink);
#endif
// SPDX-License-Identifier: GPL-2.0
//
// Mediatek ALSA SoC AFE platform driver for 8192
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <sound/soc.h>
#include "../common/mtk-afe-fe-dai.h"
#include "../common/mtk-afe-platform-driver.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-clk.h"
#include "mt8192-afe-gpio.h"
#include "mt8192-interconnection.h"
static const struct snd_pcm_hardware mt8192_afe_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE),
.period_bytes_min = 96,
.period_bytes_max = 4 * 48 * 1024,
.periods_min = 2,
.periods_max = 256,
.buffer_bytes_max = 4 * 48 * 1024,
.fifo_size = 0,
};
static int mt8192_memif_fs(struct snd_pcm_substream *substream,
unsigned int rate)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
int id = asoc_rtd_to_cpu(rtd, 0)->id;
return mt8192_rate_transform(afe->dev, rate, id);
}
static int mt8192_get_dai_fs(struct mtk_base_afe *afe,
int dai_id, unsigned int rate)
{
return mt8192_rate_transform(afe->dev, rate, dai_id);
}
static int mt8192_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
return mt8192_general_rate_transform(afe->dev, rate);
}
int mt8192_get_memif_pbuf_size(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if ((runtime->period_size * 1000) / runtime->rate > 10)
return MT8192_MEMIF_PBUF_SIZE_256_BYTES;
else
return MT8192_MEMIF_PBUF_SIZE_32_BYTES;
}
#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000)
#define MTK_PCM_DAI_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 |\
SNDRV_PCM_RATE_48000)
#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver mt8192_memif_dai_driver[] = {
/* FE DAIs: memory intefaces to CPU */
{
.name = "DL1",
.id = MT8192_MEMIF_DL1,
.playback = {
.stream_name = "DL1",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL12",
.id = MT8192_MEMIF_DL12,
.playback = {
.stream_name = "DL12",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL2",
.id = MT8192_MEMIF_DL2,
.playback = {
.stream_name = "DL2",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL3",
.id = MT8192_MEMIF_DL3,
.playback = {
.stream_name = "DL3",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL4",
.id = MT8192_MEMIF_DL4,
.playback = {
.stream_name = "DL4",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL5",
.id = MT8192_MEMIF_DL5,
.playback = {
.stream_name = "DL5",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL6",
.id = MT8192_MEMIF_DL6,
.playback = {
.stream_name = "DL6",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL7",
.id = MT8192_MEMIF_DL7,
.playback = {
.stream_name = "DL7",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL8",
.id = MT8192_MEMIF_DL8,
.playback = {
.stream_name = "DL8",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "DL9",
.id = MT8192_MEMIF_DL9,
.playback = {
.stream_name = "DL9",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL1",
.id = MT8192_MEMIF_VUL12,
.capture = {
.stream_name = "UL1",
.channels_min = 1,
.channels_max = 4,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL2",
.id = MT8192_MEMIF_AWB,
.capture = {
.stream_name = "UL2",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL3",
.id = MT8192_MEMIF_VUL2,
.capture = {
.stream_name = "UL3",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL4",
.id = MT8192_MEMIF_AWB2,
.capture = {
.stream_name = "UL4",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL5",
.id = MT8192_MEMIF_VUL3,
.capture = {
.stream_name = "UL5",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL6",
.id = MT8192_MEMIF_VUL4,
.capture = {
.stream_name = "UL6",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL7",
.id = MT8192_MEMIF_VUL5,
.capture = {
.stream_name = "UL7",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL8",
.id = MT8192_MEMIF_VUL6,
.capture = {
.stream_name = "UL8",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL_MONO_1",
.id = MT8192_MEMIF_MOD_DAI,
.capture = {
.stream_name = "UL_MONO_1",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_DAI_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL_MONO_2",
.id = MT8192_MEMIF_DAI,
.capture = {
.stream_name = "UL_MONO_2",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_DAI_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "UL_MONO_3",
.id = MT8192_MEMIF_DAI2,
.capture = {
.stream_name = "UL_MONO_3",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_DAI_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
{
.name = "HDMI",
.id = MT8192_MEMIF_HDMI,
.playback = {
.stream_name = "HDMI",
.channels_min = 2,
.channels_max = 8,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_afe_fe_ops,
},
};
static int ul_tinyconn_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
unsigned int reg_shift;
unsigned int reg_mask_shift;
dev_info(afe->dev, "%s(), event 0x%x\n", __func__, event);
if (strstr(w->name, "UL1")) {
reg_shift = VUL1_USE_TINY_SFT;
reg_mask_shift = VUL1_USE_TINY_MASK_SFT;
} else if (strstr(w->name, "UL2")) {
reg_shift = VUL2_USE_TINY_SFT;
reg_mask_shift = VUL2_USE_TINY_MASK_SFT;
} else if (strstr(w->name, "UL3")) {
reg_shift = VUL12_USE_TINY_SFT;
reg_mask_shift = VUL12_USE_TINY_MASK_SFT;
} else if (strstr(w->name, "UL4")) {
reg_shift = AWB2_USE_TINY_SFT;
reg_mask_shift = AWB2_USE_TINY_MASK_SFT;
} else {
reg_shift = AWB2_USE_TINY_SFT;
reg_mask_shift = AWB2_USE_TINY_MASK_SFT;
dev_warn(afe->dev, "%s(), err widget name %s, default use UL4",
__func__, w->name);
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
regmap_update_bits(afe->regmap, AFE_MEMIF_CONN, reg_mask_shift,
0x1 << reg_shift);
break;
case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(afe->regmap, AFE_MEMIF_CONN, reg_mask_shift,
0x0 << reg_shift);
break;
default:
break;
}
return 0;
}
/* dma widget & routes*/
static const struct snd_kcontrol_new memif_ul1_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN21,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN21,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN21,
I_ADDA_UL_CH3, 1, 0),
};
static const struct snd_kcontrol_new memif_ul1_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN22,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN22,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN22,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN22,
I_ADDA_UL_CH4, 1, 0),
};
static const struct snd_kcontrol_new memif_ul1_ch3_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN9,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN9,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN9,
I_ADDA_UL_CH3, 1, 0),
};
static const struct snd_kcontrol_new memif_ul1_ch4_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN10,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN10,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN10,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN10,
I_ADDA_UL_CH4, 1, 0),
};
static const struct snd_kcontrol_new memif_ul2_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN5,
I_I2S0_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN5,
I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN5,
I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN5,
I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN5,
I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN5_1,
I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN5_1,
I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN5_1,
I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN5,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN5,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN5,
I_I2S2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S6_CH1", AFE_CONN5_1,
I_I2S6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S8_CH1", AFE_CONN5_1,
I_I2S8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1", AFE_CONN5_1,
I_CONNSYS_I2S_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1", AFE_CONN5_1,
I_SRC_1_OUT_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul2_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN6,
I_I2S0_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN6,
I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN6,
I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN6,
I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN6,
I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN6_1,
I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN6_1,
I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN6_1,
I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN6,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN6,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN6,
I_I2S2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S6_CH2", AFE_CONN6_1,
I_I2S6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S8_CH2", AFE_CONN6_1,
I_I2S8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2", AFE_CONN6_1,
I_CONNSYS_I2S_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2", AFE_CONN6_1,
I_SRC_1_OUT_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul3_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1", AFE_CONN32_1,
I_CONNSYS_I2S_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN32,
I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN32,
I_DL2_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul3_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2", AFE_CONN33_1,
I_CONNSYS_I2S_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul4_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN38,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN38,
I_I2S0_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul4_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN39,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN39,
I_I2S0_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul5_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN44,
I_ADDA_UL_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul5_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN45,
I_ADDA_UL_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul6_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN46,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN46,
I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN46,
I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN46_1,
I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN46,
I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN46,
I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN46_1,
I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN46,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN46,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul6_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN47,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN47,
I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN47,
I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN47_1,
I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN47,
I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN47,
I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN47_1,
I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN47,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN47,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul7_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN48,
I_ADDA_UL_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul7_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN49,
I_ADDA_UL_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul8_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN50,
I_ADDA_UL_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul8_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN51,
I_ADDA_UL_CH2, 1, 0),
};
static const struct snd_kcontrol_new memif_ul_mono_1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN12,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN12,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul_mono_2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN11,
I_ADDA_UL_CH1, 1, 0),
};
static const struct snd_kcontrol_new memif_ul_mono_3_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN35,
I_ADDA_UL_CH1, 1, 0),
};
/* TINYCONN MUX */
enum {
TINYCONN_CH1_MUX_I2S0 = 0x14,
TINYCONN_CH2_MUX_I2S0 = 0x15,
TINYCONN_CH1_MUX_I2S6 = 0x1a,
TINYCONN_CH2_MUX_I2S6 = 0x1b,
TINYCONN_CH1_MUX_I2S8 = 0x1c,
TINYCONN_CH2_MUX_I2S8 = 0x1d,
TINYCONN_MUX_NONE = 0x1f,
};
static const char * const tinyconn_mux_map[] = {
"NONE",
"I2S0_CH1",
"I2S0_CH2",
"I2S6_CH1",
"I2S6_CH2",
"I2S8_CH1",
"I2S8_CH2",
};
static int tinyconn_mux_map_value[] = {
TINYCONN_MUX_NONE,
TINYCONN_CH1_MUX_I2S0,
TINYCONN_CH2_MUX_I2S0,
TINYCONN_CH1_MUX_I2S6,
TINYCONN_CH2_MUX_I2S6,
TINYCONN_CH1_MUX_I2S8,
TINYCONN_CH2_MUX_I2S8,
};
static SOC_VALUE_ENUM_SINGLE_DECL(ul4_tinyconn_ch1_mux_map_enum,
AFE_TINY_CONN0,
O_2_CFG_SFT,
O_2_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static SOC_VALUE_ENUM_SINGLE_DECL(ul4_tinyconn_ch2_mux_map_enum,
AFE_TINY_CONN0,
O_3_CFG_SFT,
O_3_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static const struct snd_kcontrol_new ul4_tinyconn_ch1_mux_control =
SOC_DAPM_ENUM("UL4_TINYCONN_CH1_MUX", ul4_tinyconn_ch1_mux_map_enum);
static const struct snd_kcontrol_new ul4_tinyconn_ch2_mux_control =
SOC_DAPM_ENUM("UL4_TINYCONN_CH2_MUX", ul4_tinyconn_ch2_mux_map_enum);
static const struct snd_soc_dapm_widget mt8192_memif_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("UL1_CH1", SND_SOC_NOPM, 0, 0,
memif_ul1_ch1_mix, ARRAY_SIZE(memif_ul1_ch1_mix)),
SND_SOC_DAPM_MIXER("UL1_CH2", SND_SOC_NOPM, 0, 0,
memif_ul1_ch2_mix, ARRAY_SIZE(memif_ul1_ch2_mix)),
SND_SOC_DAPM_MIXER("UL1_CH3", SND_SOC_NOPM, 0, 0,
memif_ul1_ch3_mix, ARRAY_SIZE(memif_ul1_ch3_mix)),
SND_SOC_DAPM_MIXER("UL1_CH4", SND_SOC_NOPM, 0, 0,
memif_ul1_ch4_mix, ARRAY_SIZE(memif_ul1_ch4_mix)),
SND_SOC_DAPM_MIXER("UL2_CH1", SND_SOC_NOPM, 0, 0,
memif_ul2_ch1_mix, ARRAY_SIZE(memif_ul2_ch1_mix)),
SND_SOC_DAPM_MIXER("UL2_CH2", SND_SOC_NOPM, 0, 0,
memif_ul2_ch2_mix, ARRAY_SIZE(memif_ul2_ch2_mix)),
SND_SOC_DAPM_MIXER("UL3_CH1", SND_SOC_NOPM, 0, 0,
memif_ul3_ch1_mix, ARRAY_SIZE(memif_ul3_ch1_mix)),
SND_SOC_DAPM_MIXER("UL3_CH2", SND_SOC_NOPM, 0, 0,
memif_ul3_ch2_mix, ARRAY_SIZE(memif_ul3_ch2_mix)),
SND_SOC_DAPM_MIXER("UL4_CH1", SND_SOC_NOPM, 0, 0,
memif_ul4_ch1_mix, ARRAY_SIZE(memif_ul4_ch1_mix)),
SND_SOC_DAPM_MIXER("UL4_CH2", SND_SOC_NOPM, 0, 0,
memif_ul4_ch2_mix, ARRAY_SIZE(memif_ul4_ch2_mix)),
SND_SOC_DAPM_MUX_E("UL4_TINYCONN_CH1_MUX", SND_SOC_NOPM, 0, 0,
&ul4_tinyconn_ch1_mux_control,
ul_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MUX_E("UL4_TINYCONN_CH2_MUX", SND_SOC_NOPM, 0, 0,
&ul4_tinyconn_ch2_mux_control,
ul_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER("UL5_CH1", SND_SOC_NOPM, 0, 0,
memif_ul5_ch1_mix, ARRAY_SIZE(memif_ul5_ch1_mix)),
SND_SOC_DAPM_MIXER("UL5_CH2", SND_SOC_NOPM, 0, 0,
memif_ul5_ch2_mix, ARRAY_SIZE(memif_ul5_ch2_mix)),
SND_SOC_DAPM_MIXER("UL6_CH1", SND_SOC_NOPM, 0, 0,
memif_ul6_ch1_mix, ARRAY_SIZE(memif_ul6_ch1_mix)),
SND_SOC_DAPM_MIXER("UL6_CH2", SND_SOC_NOPM, 0, 0,
memif_ul6_ch2_mix, ARRAY_SIZE(memif_ul6_ch2_mix)),
SND_SOC_DAPM_MIXER("UL7_CH1", SND_SOC_NOPM, 0, 0,
memif_ul7_ch1_mix, ARRAY_SIZE(memif_ul7_ch1_mix)),
SND_SOC_DAPM_MIXER("UL7_CH2", SND_SOC_NOPM, 0, 0,
memif_ul7_ch2_mix, ARRAY_SIZE(memif_ul7_ch2_mix)),
SND_SOC_DAPM_MIXER("UL8_CH1", SND_SOC_NOPM, 0, 0,
memif_ul8_ch1_mix, ARRAY_SIZE(memif_ul8_ch1_mix)),
SND_SOC_DAPM_MIXER("UL8_CH2", SND_SOC_NOPM, 0, 0,
memif_ul8_ch2_mix, ARRAY_SIZE(memif_ul8_ch2_mix)),
SND_SOC_DAPM_MIXER("UL_MONO_1_CH1", SND_SOC_NOPM, 0, 0,
memif_ul_mono_1_mix,
ARRAY_SIZE(memif_ul_mono_1_mix)),
SND_SOC_DAPM_MIXER("UL_MONO_2_CH1", SND_SOC_NOPM, 0, 0,
memif_ul_mono_2_mix,
ARRAY_SIZE(memif_ul_mono_2_mix)),
SND_SOC_DAPM_MIXER("UL_MONO_3_CH1", SND_SOC_NOPM, 0, 0,
memif_ul_mono_3_mix,
ARRAY_SIZE(memif_ul_mono_3_mix)),
SND_SOC_DAPM_INPUT("UL1_VIRTUAL_INPUT"),
SND_SOC_DAPM_INPUT("UL2_VIRTUAL_INPUT"),
SND_SOC_DAPM_INPUT("UL6_VIRTUAL_INPUT"),
};
static const struct snd_soc_dapm_route mt8192_memif_routes[] = {
{"UL1", NULL, "UL1_CH1"},
{"UL1", NULL, "UL1_CH2"},
{"UL1", NULL, "UL1_CH3"},
{"UL1", NULL, "UL1_CH4"},
{"UL1_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL1_CH1", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL1_CH1", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
{"UL1_CH2", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL1_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL1_CH2", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
{"UL1_CH2", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
{"UL1_CH3", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL1_CH3", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL1_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
{"UL1_CH4", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL1_CH4", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL1_CH4", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
{"UL1_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
{"UL2", NULL, "UL2_CH1"},
{"UL2", NULL, "UL2_CH2"},
{"UL2_CH1", "I2S0_CH1", "I2S0"},
{"UL2_CH2", "I2S0_CH2", "I2S0"},
{"UL2_CH1", "I2S2_CH1", "I2S2"},
{"UL2_CH2", "I2S2_CH2", "I2S2"},
{"UL2_CH1", "I2S6_CH1", "I2S6"},
{"UL2_CH2", "I2S6_CH2", "I2S6"},
{"UL2_CH1", "I2S8_CH1", "I2S8"},
{"UL2_CH2", "I2S8_CH2", "I2S8"},
{"UL2_CH1", "PCM_1_CAP_CH1", "PCM 1 Capture"},
{"UL2_CH2", "PCM_1_CAP_CH1", "PCM 1 Capture"},
{"UL2_CH1", "PCM_2_CAP_CH1", "PCM 2 Capture"},
{"UL2_CH2", "PCM_2_CAP_CH1", "PCM 2 Capture"},
{"UL_MONO_1", NULL, "UL_MONO_1_CH1"},
{"UL_MONO_1_CH1", "PCM_1_CAP_CH1", "PCM 1 Capture"},
{"UL_MONO_1_CH1", "PCM_2_CAP_CH1", "PCM 2 Capture"},
{"UL_MONO_2", NULL, "UL_MONO_2_CH1"},
{"UL_MONO_2_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL_MONO_3", NULL, "UL_MONO_3_CH1"},
{"UL_MONO_3_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL2_CH1", "CONNSYS_I2S_CH1", "Connsys I2S"},
{"UL2_CH2", "CONNSYS_I2S_CH2", "Connsys I2S"},
{"UL3", NULL, "UL3_CH1"},
{"UL3", NULL, "UL3_CH2"},
{"UL3_CH1", "CONNSYS_I2S_CH1", "Connsys I2S"},
{"UL3_CH2", "CONNSYS_I2S_CH2", "Connsys I2S"},
{"UL4", NULL, "UL4_CH1"},
{"UL4", NULL, "UL4_CH2"},
{"UL4", NULL, "UL4_TINYCONN_CH1_MUX"},
{"UL4", NULL, "UL4_TINYCONN_CH2_MUX"},
{"UL4_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL4_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL4_CH1", "I2S0_CH1", "I2S0"},
{"UL4_CH2", "I2S0_CH2", "I2S0"},
{"UL4_TINYCONN_CH1_MUX", "I2S0_CH1", "I2S0"},
{"UL4_TINYCONN_CH2_MUX", "I2S0_CH2", "I2S0"},
{"UL5", NULL, "UL5_CH1"},
{"UL5", NULL, "UL5_CH2"},
{"UL5_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL5_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL6", NULL, "UL6_CH1"},
{"UL6", NULL, "UL6_CH2"},
{"UL6_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL6_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL6_CH1", "PCM_1_CAP_CH1", "PCM 1 Capture"},
{"UL6_CH2", "PCM_1_CAP_CH1", "PCM 1 Capture"},
{"UL6_CH1", "PCM_2_CAP_CH1", "PCM 2 Capture"},
{"UL6_CH2", "PCM_2_CAP_CH1", "PCM 2 Capture"},
{"UL7", NULL, "UL7_CH1"},
{"UL7", NULL, "UL7_CH2"},
{"UL7_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL7_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
{"UL8", NULL, "UL8_CH1"},
{"UL8", NULL, "UL8_CH2"},
{"UL8_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
{"UL8_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
};
static const struct mtk_base_memif_data memif_data[MT8192_MEMIF_NUM] = {
[MT8192_MEMIF_DL1] = {
.name = "DL1",
.id = MT8192_MEMIF_DL1,
.reg_ofs_base = AFE_DL1_BASE,
.reg_ofs_cur = AFE_DL1_CUR,
.reg_ofs_end = AFE_DL1_END,
.reg_ofs_base_msb = AFE_DL1_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL1_CUR_MSB,
.reg_ofs_end_msb = AFE_DL1_END_MSB,
.fs_reg = AFE_DL1_CON0,
.fs_shift = DL1_MODE_SFT,
.fs_maskbit = DL1_MODE_MASK,
.mono_reg = AFE_DL1_CON0,
.mono_shift = DL1_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL1_ON_SFT,
.hd_reg = AFE_DL1_CON0,
.hd_shift = DL1_HD_MODE_SFT,
.hd_align_reg = AFE_DL1_CON0,
.hd_align_mshift = DL1_HALIGN_SFT,
.pbuf_reg = AFE_DL1_CON0,
.pbuf_shift = DL1_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL1_CON0,
.minlen_shift = DL1_MINLEN_SFT,
},
[MT8192_MEMIF_DL12] = {
.name = "DL12",
.id = MT8192_MEMIF_DL12,
.reg_ofs_base = AFE_DL12_BASE,
.reg_ofs_cur = AFE_DL12_CUR,
.reg_ofs_end = AFE_DL12_END,
.reg_ofs_base_msb = AFE_DL12_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL12_CUR_MSB,
.reg_ofs_end_msb = AFE_DL12_END_MSB,
.fs_reg = AFE_DL12_CON0,
.fs_shift = DL12_MODE_SFT,
.fs_maskbit = DL12_MODE_MASK,
.mono_reg = AFE_DL12_CON0,
.mono_shift = DL12_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL12_ON_SFT,
.hd_reg = AFE_DL12_CON0,
.hd_shift = DL12_HD_MODE_SFT,
.hd_align_reg = AFE_DL12_CON0,
.hd_align_mshift = DL12_HALIGN_SFT,
.pbuf_reg = AFE_DL12_CON0,
.pbuf_shift = DL12_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL12_CON0,
.minlen_shift = DL12_MINLEN_SFT,
},
[MT8192_MEMIF_DL2] = {
.name = "DL2",
.id = MT8192_MEMIF_DL2,
.reg_ofs_base = AFE_DL2_BASE,
.reg_ofs_cur = AFE_DL2_CUR,
.reg_ofs_end = AFE_DL2_END,
.reg_ofs_base_msb = AFE_DL2_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL2_CUR_MSB,
.reg_ofs_end_msb = AFE_DL2_END_MSB,
.fs_reg = AFE_DL2_CON0,
.fs_shift = DL2_MODE_SFT,
.fs_maskbit = DL2_MODE_MASK,
.mono_reg = AFE_DL2_CON0,
.mono_shift = DL2_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL2_ON_SFT,
.hd_reg = AFE_DL2_CON0,
.hd_shift = DL2_HD_MODE_SFT,
.hd_align_reg = AFE_DL2_CON0,
.hd_align_mshift = DL2_HALIGN_SFT,
.pbuf_reg = AFE_DL2_CON0,
.pbuf_shift = DL2_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL2_CON0,
.minlen_shift = DL2_MINLEN_SFT,
},
[MT8192_MEMIF_DL3] = {
.name = "DL3",
.id = MT8192_MEMIF_DL3,
.reg_ofs_base = AFE_DL3_BASE,
.reg_ofs_cur = AFE_DL3_CUR,
.reg_ofs_end = AFE_DL3_END,
.reg_ofs_base_msb = AFE_DL3_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL3_CUR_MSB,
.reg_ofs_end_msb = AFE_DL3_END_MSB,
.fs_reg = AFE_DL3_CON0,
.fs_shift = DL3_MODE_SFT,
.fs_maskbit = DL3_MODE_MASK,
.mono_reg = AFE_DL3_CON0,
.mono_shift = DL3_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL3_ON_SFT,
.hd_reg = AFE_DL3_CON0,
.hd_shift = DL3_HD_MODE_SFT,
.hd_align_reg = AFE_DL3_CON0,
.hd_align_mshift = DL3_HALIGN_SFT,
.pbuf_reg = AFE_DL3_CON0,
.pbuf_shift = DL3_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL3_CON0,
.minlen_shift = DL3_MINLEN_SFT,
},
[MT8192_MEMIF_DL4] = {
.name = "DL4",
.id = MT8192_MEMIF_DL4,
.reg_ofs_base = AFE_DL4_BASE,
.reg_ofs_cur = AFE_DL4_CUR,
.reg_ofs_end = AFE_DL4_END,
.reg_ofs_base_msb = AFE_DL4_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL4_CUR_MSB,
.reg_ofs_end_msb = AFE_DL4_END_MSB,
.fs_reg = AFE_DL4_CON0,
.fs_shift = DL4_MODE_SFT,
.fs_maskbit = DL4_MODE_MASK,
.mono_reg = AFE_DL4_CON0,
.mono_shift = DL4_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL4_ON_SFT,
.hd_reg = AFE_DL4_CON0,
.hd_shift = DL4_HD_MODE_SFT,
.hd_align_reg = AFE_DL4_CON0,
.hd_align_mshift = DL4_HALIGN_SFT,
.pbuf_reg = AFE_DL4_CON0,
.pbuf_shift = DL4_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL4_CON0,
.minlen_shift = DL4_MINLEN_SFT,
},
[MT8192_MEMIF_DL5] = {
.name = "DL5",
.id = MT8192_MEMIF_DL5,
.reg_ofs_base = AFE_DL5_BASE,
.reg_ofs_cur = AFE_DL5_CUR,
.reg_ofs_end = AFE_DL5_END,
.reg_ofs_base_msb = AFE_DL5_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL5_CUR_MSB,
.reg_ofs_end_msb = AFE_DL5_END_MSB,
.fs_reg = AFE_DL5_CON0,
.fs_shift = DL5_MODE_SFT,
.fs_maskbit = DL5_MODE_MASK,
.mono_reg = AFE_DL5_CON0,
.mono_shift = DL5_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL5_ON_SFT,
.hd_reg = AFE_DL5_CON0,
.hd_shift = DL5_HD_MODE_SFT,
.hd_align_reg = AFE_DL5_CON0,
.hd_align_mshift = DL5_HALIGN_SFT,
.pbuf_reg = AFE_DL5_CON0,
.pbuf_shift = DL5_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL5_CON0,
.minlen_shift = DL5_MINLEN_SFT,
},
[MT8192_MEMIF_DL6] = {
.name = "DL6",
.id = MT8192_MEMIF_DL6,
.reg_ofs_base = AFE_DL6_BASE,
.reg_ofs_cur = AFE_DL6_CUR,
.reg_ofs_end = AFE_DL6_END,
.reg_ofs_base_msb = AFE_DL6_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL6_CUR_MSB,
.reg_ofs_end_msb = AFE_DL6_END_MSB,
.fs_reg = AFE_DL6_CON0,
.fs_shift = DL6_MODE_SFT,
.fs_maskbit = DL6_MODE_MASK,
.mono_reg = AFE_DL6_CON0,
.mono_shift = DL6_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL6_ON_SFT,
.hd_reg = AFE_DL6_CON0,
.hd_shift = DL6_HD_MODE_SFT,
.hd_align_reg = AFE_DL6_CON0,
.hd_align_mshift = DL6_HALIGN_SFT,
.pbuf_reg = AFE_DL6_CON0,
.pbuf_shift = DL6_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL6_CON0,
.minlen_shift = DL6_MINLEN_SFT,
},
[MT8192_MEMIF_DL7] = {
.name = "DL7",
.id = MT8192_MEMIF_DL7,
.reg_ofs_base = AFE_DL7_BASE,
.reg_ofs_cur = AFE_DL7_CUR,
.reg_ofs_end = AFE_DL7_END,
.reg_ofs_base_msb = AFE_DL7_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL7_CUR_MSB,
.reg_ofs_end_msb = AFE_DL7_END_MSB,
.fs_reg = AFE_DL7_CON0,
.fs_shift = DL7_MODE_SFT,
.fs_maskbit = DL7_MODE_MASK,
.mono_reg = AFE_DL7_CON0,
.mono_shift = DL7_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL7_ON_SFT,
.hd_reg = AFE_DL7_CON0,
.hd_shift = DL7_HD_MODE_SFT,
.hd_align_reg = AFE_DL7_CON0,
.hd_align_mshift = DL7_HALIGN_SFT,
.pbuf_reg = AFE_DL7_CON0,
.pbuf_shift = DL7_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL7_CON0,
.minlen_shift = DL7_MINLEN_SFT,
},
[MT8192_MEMIF_DL8] = {
.name = "DL8",
.id = MT8192_MEMIF_DL8,
.reg_ofs_base = AFE_DL8_BASE,
.reg_ofs_cur = AFE_DL8_CUR,
.reg_ofs_end = AFE_DL8_END,
.reg_ofs_base_msb = AFE_DL8_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL8_CUR_MSB,
.reg_ofs_end_msb = AFE_DL8_END_MSB,
.fs_reg = AFE_DL8_CON0,
.fs_shift = DL8_MODE_SFT,
.fs_maskbit = DL8_MODE_MASK,
.mono_reg = AFE_DL8_CON0,
.mono_shift = DL8_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL8_ON_SFT,
.hd_reg = AFE_DL8_CON0,
.hd_shift = DL8_HD_MODE_SFT,
.hd_align_reg = AFE_DL8_CON0,
.hd_align_mshift = DL8_HALIGN_SFT,
.pbuf_reg = AFE_DL8_CON0,
.pbuf_shift = DL8_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL8_CON0,
.minlen_shift = DL8_MINLEN_SFT,
},
[MT8192_MEMIF_DL9] = {
.name = "DL9",
.id = MT8192_MEMIF_DL9,
.reg_ofs_base = AFE_DL9_BASE,
.reg_ofs_cur = AFE_DL9_CUR,
.reg_ofs_end = AFE_DL9_END,
.reg_ofs_base_msb = AFE_DL9_BASE_MSB,
.reg_ofs_cur_msb = AFE_DL9_CUR_MSB,
.reg_ofs_end_msb = AFE_DL9_END_MSB,
.fs_reg = AFE_DL9_CON0,
.fs_shift = DL9_MODE_SFT,
.fs_maskbit = DL9_MODE_MASK,
.mono_reg = AFE_DL9_CON0,
.mono_shift = DL9_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DL9_ON_SFT,
.hd_reg = AFE_DL9_CON0,
.hd_shift = DL9_HD_MODE_SFT,
.hd_align_reg = AFE_DL9_CON0,
.hd_align_mshift = DL9_HALIGN_SFT,
.pbuf_reg = AFE_DL9_CON0,
.pbuf_shift = DL9_PBUF_SIZE_SFT,
.minlen_reg = AFE_DL9_CON0,
.minlen_shift = DL9_MINLEN_SFT,
},
[MT8192_MEMIF_DAI] = {
.name = "DAI",
.id = MT8192_MEMIF_DAI,
.reg_ofs_base = AFE_DAI_BASE,
.reg_ofs_cur = AFE_DAI_CUR,
.reg_ofs_end = AFE_DAI_END,
.reg_ofs_base_msb = AFE_DAI_BASE_MSB,
.reg_ofs_cur_msb = AFE_DAI_CUR_MSB,
.reg_ofs_end_msb = AFE_DAI_END_MSB,
.fs_reg = AFE_DAI_CON0,
.fs_shift = DAI_MODE_SFT,
.fs_maskbit = DAI_MODE_MASK,
.mono_reg = AFE_DAI_CON0,
.mono_shift = DAI_DUPLICATE_WR_SFT,
.mono_invert = 1,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DAI_ON_SFT,
.hd_reg = AFE_DAI_CON0,
.hd_shift = DAI_HD_MODE_SFT,
.hd_align_reg = AFE_DAI_CON0,
.hd_align_mshift = DAI_HALIGN_SFT,
},
[MT8192_MEMIF_MOD_DAI] = {
.name = "MOD_DAI",
.id = MT8192_MEMIF_MOD_DAI,
.reg_ofs_base = AFE_MOD_DAI_BASE,
.reg_ofs_cur = AFE_MOD_DAI_CUR,
.reg_ofs_end = AFE_MOD_DAI_END,
.reg_ofs_base_msb = AFE_MOD_DAI_BASE_MSB,
.reg_ofs_cur_msb = AFE_MOD_DAI_CUR_MSB,
.reg_ofs_end_msb = AFE_MOD_DAI_END_MSB,
.fs_reg = AFE_MOD_DAI_CON0,
.fs_shift = MOD_DAI_MODE_SFT,
.fs_maskbit = MOD_DAI_MODE_MASK,
.mono_reg = AFE_MOD_DAI_CON0,
.mono_shift = MOD_DAI_DUPLICATE_WR_SFT,
.mono_invert = 1,
.enable_reg = AFE_DAC_CON0,
.enable_shift = MOD_DAI_ON_SFT,
.hd_reg = AFE_MOD_DAI_CON0,
.hd_shift = MOD_DAI_HD_MODE_SFT,
.hd_align_reg = AFE_MOD_DAI_CON0,
.hd_align_mshift = MOD_DAI_HALIGN_SFT,
},
[MT8192_MEMIF_DAI2] = {
.name = "DAI2",
.id = MT8192_MEMIF_DAI2,
.reg_ofs_base = AFE_DAI2_BASE,
.reg_ofs_cur = AFE_DAI2_CUR,
.reg_ofs_end = AFE_DAI2_END,
.reg_ofs_base_msb = AFE_DAI2_BASE_MSB,
.reg_ofs_cur_msb = AFE_DAI2_CUR_MSB,
.reg_ofs_end_msb = AFE_DAI2_END_MSB,
.fs_reg = AFE_DAI2_CON0,
.fs_shift = DAI2_MODE_SFT,
.fs_maskbit = DAI2_MODE_MASK,
.mono_reg = AFE_DAI2_CON0,
.mono_shift = DAI2_DUPLICATE_WR_SFT,
.mono_invert = 1,
.enable_reg = AFE_DAC_CON0,
.enable_shift = DAI2_ON_SFT,
.hd_reg = AFE_DAI2_CON0,
.hd_shift = DAI2_HD_MODE_SFT,
.hd_align_reg = AFE_DAI2_CON0,
.hd_align_mshift = DAI2_HALIGN_SFT,
},
[MT8192_MEMIF_VUL12] = {
.name = "VUL12",
.id = MT8192_MEMIF_VUL12,
.reg_ofs_base = AFE_VUL12_BASE,
.reg_ofs_cur = AFE_VUL12_CUR,
.reg_ofs_end = AFE_VUL12_END,
.reg_ofs_base_msb = AFE_VUL12_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL12_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL12_END_MSB,
.fs_reg = AFE_VUL12_CON0,
.fs_shift = VUL12_MODE_SFT,
.fs_maskbit = VUL12_MODE_MASK,
.mono_reg = AFE_VUL12_CON0,
.mono_shift = VUL12_MONO_SFT,
.quad_ch_reg = AFE_VUL12_CON0,
.quad_ch_shift = VUL12_4CH_EN_SFT,
.quad_ch_mask = VUL12_4CH_EN_MASK,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL12_ON_SFT,
.hd_reg = AFE_VUL12_CON0,
.hd_shift = VUL12_HD_MODE_SFT,
.hd_align_reg = AFE_VUL12_CON0,
.hd_align_mshift = VUL12_HALIGN_SFT,
},
[MT8192_MEMIF_VUL2] = {
.name = "VUL2",
.id = MT8192_MEMIF_VUL2,
.reg_ofs_base = AFE_VUL2_BASE,
.reg_ofs_cur = AFE_VUL2_CUR,
.reg_ofs_end = AFE_VUL2_END,
.reg_ofs_base_msb = AFE_VUL2_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL2_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL2_END_MSB,
.fs_reg = AFE_VUL2_CON0,
.fs_shift = VUL2_MODE_SFT,
.fs_maskbit = VUL2_MODE_MASK,
.mono_reg = AFE_VUL2_CON0,
.mono_shift = VUL2_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL2_ON_SFT,
.hd_reg = AFE_VUL2_CON0,
.hd_shift = VUL2_HD_MODE_SFT,
.hd_align_reg = AFE_VUL2_CON0,
.hd_align_mshift = VUL2_HALIGN_SFT,
},
[MT8192_MEMIF_AWB] = {
.name = "AWB",
.id = MT8192_MEMIF_AWB,
.reg_ofs_base = AFE_AWB_BASE,
.reg_ofs_cur = AFE_AWB_CUR,
.reg_ofs_end = AFE_AWB_END,
.reg_ofs_base_msb = AFE_AWB_BASE_MSB,
.reg_ofs_cur_msb = AFE_AWB_CUR_MSB,
.reg_ofs_end_msb = AFE_AWB_END_MSB,
.fs_reg = AFE_AWB_CON0,
.fs_shift = AWB_MODE_SFT,
.fs_maskbit = AWB_MODE_MASK,
.mono_reg = AFE_AWB_CON0,
.mono_shift = AWB_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = AWB_ON_SFT,
.hd_reg = AFE_AWB_CON0,
.hd_shift = AWB_HD_MODE_SFT,
.hd_align_reg = AFE_AWB_CON0,
.hd_align_mshift = AWB_HALIGN_SFT,
},
[MT8192_MEMIF_AWB2] = {
.name = "AWB2",
.id = MT8192_MEMIF_AWB2,
.reg_ofs_base = AFE_AWB2_BASE,
.reg_ofs_cur = AFE_AWB2_CUR,
.reg_ofs_end = AFE_AWB2_END,
.reg_ofs_base_msb = AFE_AWB2_BASE_MSB,
.reg_ofs_cur_msb = AFE_AWB2_CUR_MSB,
.reg_ofs_end_msb = AFE_AWB2_END_MSB,
.fs_reg = AFE_AWB2_CON0,
.fs_shift = AWB2_MODE_SFT,
.fs_maskbit = AWB2_MODE_MASK,
.mono_reg = AFE_AWB2_CON0,
.mono_shift = AWB2_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = AWB2_ON_SFT,
.hd_reg = AFE_AWB2_CON0,
.hd_shift = AWB2_HD_MODE_SFT,
.hd_align_reg = AFE_AWB2_CON0,
.hd_align_mshift = AWB2_HALIGN_SFT,
},
[MT8192_MEMIF_VUL3] = {
.name = "VUL3",
.id = MT8192_MEMIF_VUL3,
.reg_ofs_base = AFE_VUL3_BASE,
.reg_ofs_cur = AFE_VUL3_CUR,
.reg_ofs_end = AFE_VUL3_END,
.reg_ofs_base_msb = AFE_VUL3_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL3_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL3_END_MSB,
.fs_reg = AFE_VUL3_CON0,
.fs_shift = VUL3_MODE_SFT,
.fs_maskbit = VUL3_MODE_MASK,
.mono_reg = AFE_VUL3_CON0,
.mono_shift = VUL3_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL3_ON_SFT,
.hd_reg = AFE_VUL3_CON0,
.hd_shift = VUL3_HD_MODE_SFT,
.hd_align_reg = AFE_VUL3_CON0,
.hd_align_mshift = VUL3_HALIGN_SFT,
},
[MT8192_MEMIF_VUL4] = {
.name = "VUL4",
.id = MT8192_MEMIF_VUL4,
.reg_ofs_base = AFE_VUL4_BASE,
.reg_ofs_cur = AFE_VUL4_CUR,
.reg_ofs_end = AFE_VUL4_END,
.reg_ofs_base_msb = AFE_VUL4_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL4_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL4_END_MSB,
.fs_reg = AFE_VUL4_CON0,
.fs_shift = VUL4_MODE_SFT,
.fs_maskbit = VUL4_MODE_MASK,
.mono_reg = AFE_VUL4_CON0,
.mono_shift = VUL4_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL4_ON_SFT,
.hd_reg = AFE_VUL4_CON0,
.hd_shift = VUL4_HD_MODE_SFT,
.hd_align_reg = AFE_VUL4_CON0,
.hd_align_mshift = VUL4_HALIGN_SFT,
},
[MT8192_MEMIF_VUL5] = {
.name = "VUL5",
.id = MT8192_MEMIF_VUL5,
.reg_ofs_base = AFE_VUL5_BASE,
.reg_ofs_cur = AFE_VUL5_CUR,
.reg_ofs_end = AFE_VUL5_END,
.reg_ofs_base_msb = AFE_VUL5_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL5_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL5_END_MSB,
.fs_reg = AFE_VUL5_CON0,
.fs_shift = VUL5_MODE_SFT,
.fs_maskbit = VUL5_MODE_MASK,
.mono_reg = AFE_VUL5_CON0,
.mono_shift = VUL5_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL5_ON_SFT,
.hd_reg = AFE_VUL5_CON0,
.hd_shift = VUL5_HD_MODE_SFT,
.hd_align_reg = AFE_VUL5_CON0,
.hd_align_mshift = VUL5_HALIGN_SFT,
},
[MT8192_MEMIF_VUL6] = {
.name = "VUL6",
.id = MT8192_MEMIF_VUL6,
.reg_ofs_base = AFE_VUL6_BASE,
.reg_ofs_cur = AFE_VUL6_CUR,
.reg_ofs_end = AFE_VUL6_END,
.reg_ofs_base_msb = AFE_VUL6_BASE_MSB,
.reg_ofs_cur_msb = AFE_VUL6_CUR_MSB,
.reg_ofs_end_msb = AFE_VUL6_END_MSB,
.fs_reg = AFE_VUL6_CON0,
.fs_shift = VUL6_MODE_SFT,
.fs_maskbit = VUL6_MODE_MASK,
.mono_reg = AFE_VUL6_CON0,
.mono_shift = VUL6_MONO_SFT,
.enable_reg = AFE_DAC_CON0,
.enable_shift = VUL6_ON_SFT,
.hd_reg = AFE_VUL6_CON0,
.hd_shift = VUL6_HD_MODE_SFT,
.hd_align_reg = AFE_VUL6_CON0,
.hd_align_mshift = VUL6_HALIGN_SFT,
},
[MT8192_MEMIF_HDMI] = {
.name = "HDMI",
.id = MT8192_MEMIF_HDMI,
.reg_ofs_base = AFE_HDMI_OUT_BASE,
.reg_ofs_cur = AFE_HDMI_OUT_CUR,
.reg_ofs_end = AFE_HDMI_OUT_END,
.reg_ofs_base_msb = AFE_HDMI_OUT_BASE_MSB,
.reg_ofs_cur_msb = AFE_HDMI_OUT_CUR_MSB,
.reg_ofs_end_msb = AFE_HDMI_OUT_END_MSB,
.fs_reg = -1,
.fs_shift = -1,
.fs_maskbit = -1,
.mono_reg = -1,
.mono_shift = -1,
.enable_reg = AFE_DAC_CON0,
.enable_shift = HDMI_OUT_ON_SFT,
.hd_reg = AFE_HDMI_OUT_CON0,
.hd_shift = HDMI_OUT_HD_MODE_SFT,
.hd_align_reg = AFE_HDMI_OUT_CON0,
.hd_align_mshift = HDMI_OUT_HALIGN_SFT,
.pbuf_reg = AFE_HDMI_OUT_CON0,
.minlen_reg = AFE_HDMI_OUT_CON0,
.minlen_shift = HDMI_OUT_MINLEN_SFT,
},
};
static const struct mtk_base_irq_data irq_data[MT8192_IRQ_NUM] = {
[MT8192_IRQ_0] = {
.id = MT8192_IRQ_0,
.irq_cnt_reg = AFE_IRQ_MCU_CNT0,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ0_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ0_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ0_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ0_MCU_CLR_SFT,
},
[MT8192_IRQ_1] = {
.id = MT8192_IRQ_1,
.irq_cnt_reg = AFE_IRQ_MCU_CNT1,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ1_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ1_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ1_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ1_MCU_CLR_SFT,
},
[MT8192_IRQ_2] = {
.id = MT8192_IRQ_2,
.irq_cnt_reg = AFE_IRQ_MCU_CNT2,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ2_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ2_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ2_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ2_MCU_CLR_SFT,
},
[MT8192_IRQ_3] = {
.id = MT8192_IRQ_3,
.irq_cnt_reg = AFE_IRQ_MCU_CNT3,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ3_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ3_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ3_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ3_MCU_CLR_SFT,
},
[MT8192_IRQ_4] = {
.id = MT8192_IRQ_4,
.irq_cnt_reg = AFE_IRQ_MCU_CNT4,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ4_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ4_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ4_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ4_MCU_CLR_SFT,
},
[MT8192_IRQ_5] = {
.id = MT8192_IRQ_5,
.irq_cnt_reg = AFE_IRQ_MCU_CNT5,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ5_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ5_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ5_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ5_MCU_CLR_SFT,
},
[MT8192_IRQ_6] = {
.id = MT8192_IRQ_6,
.irq_cnt_reg = AFE_IRQ_MCU_CNT6,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ6_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ6_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ6_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ6_MCU_CLR_SFT,
},
[MT8192_IRQ_7] = {
.id = MT8192_IRQ_7,
.irq_cnt_reg = AFE_IRQ_MCU_CNT7,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON1,
.irq_fs_shift = IRQ7_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ7_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ7_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ7_MCU_CLR_SFT,
},
[MT8192_IRQ_8] = {
.id = MT8192_IRQ_8,
.irq_cnt_reg = AFE_IRQ_MCU_CNT8,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ8_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ8_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ8_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ8_MCU_CLR_SFT,
},
[MT8192_IRQ_9] = {
.id = MT8192_IRQ_9,
.irq_cnt_reg = AFE_IRQ_MCU_CNT9,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ9_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ9_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ9_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ9_MCU_CLR_SFT,
},
[MT8192_IRQ_10] = {
.id = MT8192_IRQ_10,
.irq_cnt_reg = AFE_IRQ_MCU_CNT10,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ10_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ10_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ10_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ10_MCU_CLR_SFT,
},
[MT8192_IRQ_11] = {
.id = MT8192_IRQ_11,
.irq_cnt_reg = AFE_IRQ_MCU_CNT11,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ11_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ11_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ11_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ11_MCU_CLR_SFT,
},
[MT8192_IRQ_12] = {
.id = MT8192_IRQ_12,
.irq_cnt_reg = AFE_IRQ_MCU_CNT12,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ12_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ12_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ12_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ12_MCU_CLR_SFT,
},
[MT8192_IRQ_13] = {
.id = MT8192_IRQ_13,
.irq_cnt_reg = AFE_IRQ_MCU_CNT13,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ13_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ13_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ13_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ13_MCU_CLR_SFT,
},
[MT8192_IRQ_14] = {
.id = MT8192_IRQ_14,
.irq_cnt_reg = AFE_IRQ_MCU_CNT14,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ14_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ14_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ14_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ14_MCU_CLR_SFT,
},
[MT8192_IRQ_15] = {
.id = MT8192_IRQ_15,
.irq_cnt_reg = AFE_IRQ_MCU_CNT15,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON2,
.irq_fs_shift = IRQ15_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ15_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ15_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ15_MCU_CLR_SFT,
},
[MT8192_IRQ_16] = {
.id = MT8192_IRQ_16,
.irq_cnt_reg = AFE_IRQ_MCU_CNT16,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ16_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ16_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ16_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ16_MCU_CLR_SFT,
},
[MT8192_IRQ_17] = {
.id = MT8192_IRQ_17,
.irq_cnt_reg = AFE_IRQ_MCU_CNT17,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ17_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ17_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ17_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ17_MCU_CLR_SFT,
},
[MT8192_IRQ_18] = {
.id = MT8192_IRQ_18,
.irq_cnt_reg = AFE_IRQ_MCU_CNT18,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ18_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ18_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ18_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ18_MCU_CLR_SFT,
},
[MT8192_IRQ_19] = {
.id = MT8192_IRQ_19,
.irq_cnt_reg = AFE_IRQ_MCU_CNT19,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ19_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ19_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ19_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ19_MCU_CLR_SFT,
},
[MT8192_IRQ_20] = {
.id = MT8192_IRQ_20,
.irq_cnt_reg = AFE_IRQ_MCU_CNT20,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ20_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ20_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ20_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ20_MCU_CLR_SFT,
},
[MT8192_IRQ_21] = {
.id = MT8192_IRQ_21,
.irq_cnt_reg = AFE_IRQ_MCU_CNT21,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ21_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ21_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ21_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ21_MCU_CLR_SFT,
},
[MT8192_IRQ_22] = {
.id = MT8192_IRQ_22,
.irq_cnt_reg = AFE_IRQ_MCU_CNT22,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ22_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ22_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ22_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ22_MCU_CLR_SFT,
},
[MT8192_IRQ_23] = {
.id = MT8192_IRQ_23,
.irq_cnt_reg = AFE_IRQ_MCU_CNT23,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON3,
.irq_fs_shift = IRQ23_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ23_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ23_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ23_MCU_CLR_SFT,
},
[MT8192_IRQ_24] = {
.id = MT8192_IRQ_24,
.irq_cnt_reg = AFE_IRQ_MCU_CNT24,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON4,
.irq_fs_shift = IRQ24_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ24_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ24_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ24_MCU_CLR_SFT,
},
[MT8192_IRQ_25] = {
.id = MT8192_IRQ_25,
.irq_cnt_reg = AFE_IRQ_MCU_CNT25,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON4,
.irq_fs_shift = IRQ25_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ25_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ25_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ25_MCU_CLR_SFT,
},
[MT8192_IRQ_26] = {
.id = MT8192_IRQ_26,
.irq_cnt_reg = AFE_IRQ_MCU_CNT26,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = AFE_IRQ_MCU_CON4,
.irq_fs_shift = IRQ26_MCU_MODE_SFT,
.irq_fs_maskbit = IRQ26_MCU_MODE_MASK,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ26_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ26_MCU_CLR_SFT,
},
[MT8192_IRQ_31] = {
.id = MT8192_IRQ_31,
.irq_cnt_reg = AFE_IRQ_MCU_CNT31,
.irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
.irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
.irq_fs_reg = -1,
.irq_fs_shift = -1,
.irq_fs_maskbit = -1,
.irq_en_reg = AFE_IRQ_MCU_CON0,
.irq_en_shift = IRQ31_MCU_ON_SFT,
.irq_clr_reg = AFE_IRQ_MCU_CLR,
.irq_clr_shift = IRQ31_MCU_CLR_SFT,
},
};
static const int memif_irq_usage[MT8192_MEMIF_NUM] = {
[MT8192_MEMIF_DL1] = MT8192_IRQ_0,
[MT8192_MEMIF_DL2] = MT8192_IRQ_1,
[MT8192_MEMIF_DL3] = MT8192_IRQ_2,
[MT8192_MEMIF_DL4] = MT8192_IRQ_3,
[MT8192_MEMIF_DL5] = MT8192_IRQ_4,
[MT8192_MEMIF_DL6] = MT8192_IRQ_5,
[MT8192_MEMIF_DL7] = MT8192_IRQ_6,
[MT8192_MEMIF_DL8] = MT8192_IRQ_7,
[MT8192_MEMIF_DL9] = MT8192_IRQ_8,
[MT8192_MEMIF_DL12] = MT8192_IRQ_9,
[MT8192_MEMIF_DAI] = MT8192_IRQ_10,
[MT8192_MEMIF_MOD_DAI] = MT8192_IRQ_11,
[MT8192_MEMIF_DAI2] = MT8192_IRQ_12,
[MT8192_MEMIF_VUL12] = MT8192_IRQ_13,
[MT8192_MEMIF_VUL2] = MT8192_IRQ_14,
[MT8192_MEMIF_AWB] = MT8192_IRQ_15,
[MT8192_MEMIF_AWB2] = MT8192_IRQ_16,
[MT8192_MEMIF_VUL3] = MT8192_IRQ_17,
[MT8192_MEMIF_VUL4] = MT8192_IRQ_18,
[MT8192_MEMIF_VUL5] = MT8192_IRQ_19,
[MT8192_MEMIF_VUL6] = MT8192_IRQ_20,
[MT8192_MEMIF_HDMI] = MT8192_IRQ_31,
};
static bool mt8192_is_volatile_reg(struct device *dev, unsigned int reg)
{
/* these auto-gen reg has read-only bit, so put it as volatile */
/* volatile reg cannot be cached, so cannot be set when power off */
switch (reg) {
case AUDIO_TOP_CON0: /* reg bit controlled by CCF */
case AUDIO_TOP_CON1: /* reg bit controlled by CCF */
case AUDIO_TOP_CON2:
case AUDIO_TOP_CON3:
case AFE_DL1_CUR_MSB:
case AFE_DL1_CUR:
case AFE_DL1_END:
case AFE_DL2_CUR_MSB:
case AFE_DL2_CUR:
case AFE_DL2_END:
case AFE_DL3_CUR_MSB:
case AFE_DL3_CUR:
case AFE_DL3_END:
case AFE_DL4_CUR_MSB:
case AFE_DL4_CUR:
case AFE_DL4_END:
case AFE_DL12_CUR_MSB:
case AFE_DL12_CUR:
case AFE_DL12_END:
case AFE_ADDA_SRC_DEBUG_MON0:
case AFE_ADDA_SRC_DEBUG_MON1:
case AFE_ADDA_UL_SRC_MON0:
case AFE_ADDA_UL_SRC_MON1:
case AFE_SECURE_CON0:
case AFE_SRAM_BOUND:
case AFE_SECURE_CON1:
case AFE_VUL_CUR_MSB:
case AFE_VUL_CUR:
case AFE_VUL_END:
case AFE_ADDA_3RD_DAC_DL_SDM_FIFO_MON:
case AFE_ADDA_3RD_DAC_DL_SRC_LCH_MON:
case AFE_ADDA_3RD_DAC_DL_SRC_RCH_MON:
case AFE_ADDA_3RD_DAC_DL_SDM_OUT_MON:
case AFE_SIDETONE_MON:
case AFE_SIDETONE_CON0:
case AFE_SIDETONE_COEFF:
case AFE_VUL2_CUR_MSB:
case AFE_VUL2_CUR:
case AFE_VUL2_END:
case AFE_VUL3_CUR_MSB:
case AFE_VUL3_CUR:
case AFE_VUL3_END:
case AFE_I2S_MON:
case AFE_DAC_MON:
case AFE_IRQ0_MCU_CNT_MON:
case AFE_IRQ6_MCU_CNT_MON:
case AFE_VUL4_CUR_MSB:
case AFE_VUL4_CUR:
case AFE_VUL4_END:
case AFE_VUL12_CUR_MSB:
case AFE_VUL12_CUR:
case AFE_VUL12_END:
case AFE_IRQ3_MCU_CNT_MON:
case AFE_IRQ4_MCU_CNT_MON:
case AFE_IRQ_MCU_STATUS:
case AFE_IRQ_MCU_CLR:
case AFE_IRQ_MCU_MON2:
case AFE_IRQ1_MCU_CNT_MON:
case AFE_IRQ2_MCU_CNT_MON:
case AFE_IRQ5_MCU_CNT_MON:
case AFE_IRQ7_MCU_CNT_MON:
case AFE_IRQ_MCU_MISS_CLR:
case AFE_GAIN1_CUR:
case AFE_GAIN2_CUR:
case AFE_SRAM_DELSEL_CON1:
case PCM_INTF_CON2:
case FPGA_CFG0:
case FPGA_CFG1:
case FPGA_CFG2:
case FPGA_CFG3:
case AUDIO_TOP_DBG_MON0:
case AUDIO_TOP_DBG_MON1:
case AFE_IRQ8_MCU_CNT_MON:
case AFE_IRQ11_MCU_CNT_MON:
case AFE_IRQ12_MCU_CNT_MON:
case AFE_IRQ9_MCU_CNT_MON:
case AFE_IRQ10_MCU_CNT_MON:
case AFE_IRQ13_MCU_CNT_MON:
case AFE_IRQ14_MCU_CNT_MON:
case AFE_IRQ15_MCU_CNT_MON:
case AFE_IRQ16_MCU_CNT_MON:
case AFE_IRQ17_MCU_CNT_MON:
case AFE_IRQ18_MCU_CNT_MON:
case AFE_IRQ19_MCU_CNT_MON:
case AFE_IRQ20_MCU_CNT_MON:
case AFE_IRQ21_MCU_CNT_MON:
case AFE_IRQ22_MCU_CNT_MON:
case AFE_IRQ23_MCU_CNT_MON:
case AFE_IRQ24_MCU_CNT_MON:
case AFE_IRQ25_MCU_CNT_MON:
case AFE_IRQ26_MCU_CNT_MON:
case AFE_IRQ31_MCU_CNT_MON:
case AFE_CBIP_MON0:
case AFE_CBIP_SLV_MUX_MON0:
case AFE_CBIP_SLV_DECODER_MON0:
case AFE_ADDA6_MTKAIF_MON0:
case AFE_ADDA6_MTKAIF_MON1:
case AFE_AWB_CUR_MSB:
case AFE_AWB_CUR:
case AFE_AWB_END:
case AFE_AWB2_CUR_MSB:
case AFE_AWB2_CUR:
case AFE_AWB2_END:
case AFE_DAI_CUR_MSB:
case AFE_DAI_CUR:
case AFE_DAI_END:
case AFE_DAI2_CUR_MSB:
case AFE_DAI2_CUR:
case AFE_DAI2_END:
case AFE_ADDA6_SRC_DEBUG_MON0:
case AFE_ADD6A_UL_SRC_MON0:
case AFE_ADDA6_UL_SRC_MON1:
case AFE_MOD_DAI_CUR_MSB:
case AFE_MOD_DAI_CUR:
case AFE_MOD_DAI_END:
case AFE_HDMI_OUT_CUR_MSB:
case AFE_HDMI_OUT_CUR:
case AFE_HDMI_OUT_END:
case AFE_AWB_RCH_MON:
case AFE_AWB_LCH_MON:
case AFE_VUL_RCH_MON:
case AFE_VUL_LCH_MON:
case AFE_VUL12_RCH_MON:
case AFE_VUL12_LCH_MON:
case AFE_VUL2_RCH_MON:
case AFE_VUL2_LCH_MON:
case AFE_DAI_DATA_MON:
case AFE_MOD_DAI_DATA_MON:
case AFE_DAI2_DATA_MON:
case AFE_AWB2_RCH_MON:
case AFE_AWB2_LCH_MON:
case AFE_VUL3_RCH_MON:
case AFE_VUL3_LCH_MON:
case AFE_VUL4_RCH_MON:
case AFE_VUL4_LCH_MON:
case AFE_VUL5_RCH_MON:
case AFE_VUL5_LCH_MON:
case AFE_VUL6_RCH_MON:
case AFE_VUL6_LCH_MON:
case AFE_DL1_RCH_MON:
case AFE_DL1_LCH_MON:
case AFE_DL2_RCH_MON:
case AFE_DL2_LCH_MON:
case AFE_DL12_RCH1_MON:
case AFE_DL12_LCH1_MON:
case AFE_DL12_RCH2_MON:
case AFE_DL12_LCH2_MON:
case AFE_DL3_RCH_MON:
case AFE_DL3_LCH_MON:
case AFE_DL4_RCH_MON:
case AFE_DL4_LCH_MON:
case AFE_DL5_RCH_MON:
case AFE_DL5_LCH_MON:
case AFE_DL6_RCH_MON:
case AFE_DL6_LCH_MON:
case AFE_DL7_RCH_MON:
case AFE_DL7_LCH_MON:
case AFE_DL8_RCH_MON:
case AFE_DL8_LCH_MON:
case AFE_VUL5_CUR_MSB:
case AFE_VUL5_CUR:
case AFE_VUL5_END:
case AFE_VUL6_CUR_MSB:
case AFE_VUL6_CUR:
case AFE_VUL6_END:
case AFE_ADDA_DL_SDM_FIFO_MON:
case AFE_ADDA_DL_SRC_LCH_MON:
case AFE_ADDA_DL_SRC_RCH_MON:
case AFE_ADDA_DL_SDM_OUT_MON:
case AFE_CONNSYS_I2S_MON:
case AFE_ASRC_2CH_CON0:
case AFE_ASRC_2CH_CON2:
case AFE_ASRC_2CH_CON3:
case AFE_ASRC_2CH_CON4:
case AFE_ASRC_2CH_CON5:
case AFE_ASRC_2CH_CON7:
case AFE_ASRC_2CH_CON8:
case AFE_ASRC_2CH_CON12:
case AFE_ASRC_2CH_CON13:
case AFE_DL9_CUR_MSB:
case AFE_DL9_CUR:
case AFE_DL9_END:
case AFE_ADDA_MTKAIF_MON0:
case AFE_ADDA_MTKAIF_MON1:
case AFE_DL_NLE_R_MON0:
case AFE_DL_NLE_R_MON1:
case AFE_DL_NLE_R_MON2:
case AFE_DL_NLE_L_MON0:
case AFE_DL_NLE_L_MON1:
case AFE_DL_NLE_L_MON2:
case AFE_GENERAL1_ASRC_2CH_CON0:
case AFE_GENERAL1_ASRC_2CH_CON2:
case AFE_GENERAL1_ASRC_2CH_CON3:
case AFE_GENERAL1_ASRC_2CH_CON4:
case AFE_GENERAL1_ASRC_2CH_CON5:
case AFE_GENERAL1_ASRC_2CH_CON7:
case AFE_GENERAL1_ASRC_2CH_CON8:
case AFE_GENERAL1_ASRC_2CH_CON12:
case AFE_GENERAL1_ASRC_2CH_CON13:
case AFE_GENERAL2_ASRC_2CH_CON0:
case AFE_GENERAL2_ASRC_2CH_CON2:
case AFE_GENERAL2_ASRC_2CH_CON3:
case AFE_GENERAL2_ASRC_2CH_CON4:
case AFE_GENERAL2_ASRC_2CH_CON5:
case AFE_GENERAL2_ASRC_2CH_CON7:
case AFE_GENERAL2_ASRC_2CH_CON8:
case AFE_GENERAL2_ASRC_2CH_CON12:
case AFE_GENERAL2_ASRC_2CH_CON13:
case AFE_DL9_RCH_MON:
case AFE_DL9_LCH_MON:
case AFE_DL5_CUR_MSB:
case AFE_DL5_CUR:
case AFE_DL5_END:
case AFE_DL6_CUR_MSB:
case AFE_DL6_CUR:
case AFE_DL6_END:
case AFE_DL7_CUR_MSB:
case AFE_DL7_CUR:
case AFE_DL7_END:
case AFE_DL8_CUR_MSB:
case AFE_DL8_CUR:
case AFE_DL8_END:
case AFE_PROT_SIDEBAND_MON:
case AFE_DOMAIN_SIDEBAND0_MON:
case AFE_DOMAIN_SIDEBAND1_MON:
case AFE_DOMAIN_SIDEBAND2_MON:
case AFE_DOMAIN_SIDEBAND3_MON:
case AFE_APLL1_TUNER_CFG: /* [20:31] is monitor */
case AFE_APLL2_TUNER_CFG: /* [20:31] is monitor */
case AFE_DAC_CON0:
case AFE_IRQ_MCU_CON0:
case AFE_IRQ_MCU_EN:
return true;
default:
return false;
};
}
static const struct regmap_config mt8192_afe_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.volatile_reg = mt8192_is_volatile_reg,
.max_register = AFE_MAX_REGISTER,
.num_reg_defaults_raw = AFE_MAX_REGISTER,
.cache_type = REGCACHE_FLAT,
};
static irqreturn_t mt8192_afe_irq_handler(int irq_id, void *dev)
{
struct mtk_base_afe *afe = dev;
struct mtk_base_afe_irq *irq;
unsigned int status;
unsigned int status_mcu;
unsigned int mcu_en;
int ret;
int i;
/* get irq that is sent to MCU */
regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en);
ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status);
/* only care IRQ which is sent to MCU */
status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS;
if (ret || status_mcu == 0) {
dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x, mcu_en 0x%x\n",
__func__, ret, status, mcu_en);
goto err_irq;
}
for (i = 0; i < MT8192_MEMIF_NUM; i++) {
struct mtk_base_afe_memif *memif = &afe->memif[i];
if (!memif->substream)
continue;
if (memif->irq_usage < 0)
continue;
irq = &afe->irqs[memif->irq_usage];
if (status_mcu & (1 << irq->irq_data->irq_en_shift))
snd_pcm_period_elapsed(memif->substream);
}
err_irq:
/* clear irq */
regmap_write(afe->regmap,
AFE_IRQ_MCU_CLR,
status_mcu);
return IRQ_HANDLED;
}
static int mt8192_afe_runtime_suspend(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
unsigned int value;
int ret;
dev_info(afe->dev, "%s()\n", __func__);
if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
goto skip_regmap;
/* disable AFE */
regmap_update_bits(afe->regmap, AFE_DAC_CON0, AFE_ON_MASK_SFT, 0x0);
ret = regmap_read_poll_timeout(afe->regmap,
AFE_DAC_MON,
value,
(value & AFE_ON_RETM_MASK_SFT) == 0,
20,
1 * 1000 * 1000);
if (ret)
dev_warn(afe->dev, "%s(), ret %d\n", __func__, ret);
/* make sure all irq status are cleared */
regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, 0xffffffff);
regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, 0xffffffff);
/* reset sgen */
regmap_write(afe->regmap, AFE_SINEGEN_CON0, 0x0);
regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2,
INNER_LOOP_BACK_MODE_MASK_SFT,
0x3f << INNER_LOOP_BACK_MODE_SFT);
/* cache only */
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
skip_regmap:
mt8192_afe_disable_clock(afe);
return 0;
}
static int mt8192_afe_runtime_resume(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int ret;
dev_info(afe->dev, "%s()\n", __func__);
ret = mt8192_afe_enable_clock(afe);
if (ret)
return ret;
if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
goto skip_regmap;
regcache_cache_only(afe->regmap, false);
regcache_sync(afe->regmap);
/* enable audio sys DCM for power saving */
regmap_update_bits(afe_priv->infracfg,
PERI_BUS_DCM_CTRL, 0x1 << 29, 0x1 << 29);
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 0x1 << 29, 0x1 << 29);
/* force cpu use 8_24 format when writing 32bit data */
regmap_update_bits(afe->regmap, AFE_MEMIF_CON0,
CPU_HD_ALIGN_MASK_SFT, 0 << CPU_HD_ALIGN_SFT);
/* set all output port to 24bit */
regmap_write(afe->regmap, AFE_CONN_24BIT, 0xffffffff);
regmap_write(afe->regmap, AFE_CONN_24BIT_1, 0xffffffff);
/* enable AFE */
regmap_update_bits(afe->regmap, AFE_DAC_CON0, AFE_ON_MASK_SFT, 0x1);
skip_regmap:
return 0;
}
static int mt8192_afe_component_probe(struct snd_soc_component *component)
{
return mtk_afe_add_sub_dai_control(component);
}
const struct snd_soc_component_driver mt8192_afe_component = {
.name = AFE_PCM_NAME,
.probe = mt8192_afe_component_probe,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
};
static const struct snd_soc_component_driver mt8192_afe_pcm_component = {
.name = "mt8192-afe-pcm-dai",
};
static int mt8192_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 = mt8192_memif_dai_driver;
dai->num_dai_drivers = ARRAY_SIZE(mt8192_memif_dai_driver);
dai->dapm_widgets = mt8192_memif_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mt8192_memif_widgets);
dai->dapm_routes = mt8192_memif_routes;
dai->num_dapm_routes = ARRAY_SIZE(mt8192_memif_routes);
return 0;
}
typedef int (*dai_register_cb)(struct mtk_base_afe *);
static const dai_register_cb dai_register_cbs[] = {
mt8192_dai_adda_register,
mt8192_dai_i2s_register,
mt8192_dai_pcm_register,
mt8192_dai_tdm_register,
mt8192_dai_memif_register,
};
static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
struct mt8192_afe_private *afe_priv;
struct device *dev;
struct reset_control *rstc;
int i, ret, irq_id;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
if (ret)
return ret;
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;
/* init audio related clock */
ret = mt8192_init_clock(afe);
if (ret) {
dev_err(dev, "init clock error\n");
return ret;
}
/* reset controller to reset audio regs before regmap cache */
rstc = devm_reset_control_get_exclusive(dev, "audiosys");
if (IS_ERR(rstc)) {
ret = PTR_ERR(rstc);
dev_err(dev, "could not get audiosys reset:%d\n", ret);
return ret;
}
ret = reset_control_reset(rstc);
if (ret) {
dev_err(dev, "failed to trigger audio reset:%d\n", ret);
return ret;
}
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev))
goto err_pm_disable;
/* regmap init */
afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(afe->regmap)) {
dev_err(dev, "could not get regmap from parent\n");
return PTR_ERR(afe->regmap);
}
ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config);
if (ret) {
dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret);
return ret;
}
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
pm_runtime_get_sync(&pdev->dev);
ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
if (ret) {
dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
return ret;
}
pm_runtime_put_sync(&pdev->dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
/* init memif */
afe->memif_size = MT8192_MEMIF_NUM;
afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
GFP_KERNEL);
if (!afe->memif)
return -ENOMEM;
for (i = 0; i < afe->memif_size; i++) {
afe->memif[i].data = &memif_data[i];
afe->memif[i].irq_usage = memif_irq_usage[i];
afe->memif[i].const_irq = 1;
}
mutex_init(&afe->irq_alloc_lock); /* needed when dynamic irq */
/* init irq */
afe->irqs_size = MT8192_IRQ_NUM;
afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
GFP_KERNEL);
if (!afe->irqs)
return -ENOMEM;
for (i = 0; i < afe->irqs_size; i++)
afe->irqs[i].irq_data = &irq_data[i];
/* request irq */
irq_id = platform_get_irq(pdev, 0);
if (irq_id < 0)
return irq_id;
ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler,
IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
if (ret) {
dev_err(dev, "could not request_irq for Afe_ISR_Handle\n");
return ret;
}
/* 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);
goto err_pm_disable;
}
}
/* 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);
goto err_pm_disable;
}
/* others */
afe->mtk_afe_hardware = &mt8192_afe_hardware;
afe->memif_fs = mt8192_memif_fs;
afe->irq_fs = mt8192_irq_fs;
afe->get_dai_fs = mt8192_get_dai_fs;
afe->get_memif_pbuf_size = mt8192_get_memif_pbuf_size;
afe->memif_32bit_supported = 1;
afe->runtime_resume = mt8192_afe_runtime_resume;
afe->runtime_suspend = mt8192_afe_runtime_suspend;
/* register platform */
ret = devm_snd_soc_register_component(&pdev->dev,
&mt8192_afe_component, NULL, 0);
if (ret) {
dev_warn(dev, "err_platform\n");
goto err_pm_disable;
}
ret = devm_snd_soc_register_component(&pdev->dev,
&mt8192_afe_pcm_component,
afe->dai_drivers,
afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_dai_component\n");
goto err_pm_disable;
}
return 0;
err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
}
static int mt8192_afe_pcm_dev_remove(struct platform_device *pdev)
{
struct mtk_base_afe *afe = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
mt8192_afe_runtime_suspend(&pdev->dev);
/* disable afe clock */
mt8192_afe_disable_clock(afe);
return 0;
}
static const struct of_device_id mt8192_afe_pcm_dt_match[] = {
{ .compatible = "mediatek,mt8192-audio", },
{},
};
MODULE_DEVICE_TABLE(of, mt8192_afe_pcm_dt_match);
static const struct dev_pm_ops mt8192_afe_pm_ops = {
SET_RUNTIME_PM_OPS(mt8192_afe_runtime_suspend,
mt8192_afe_runtime_resume, NULL)
};
static struct platform_driver mt8192_afe_pcm_driver = {
.driver = {
.name = "mt8192-audio",
.of_match_table = mt8192_afe_pcm_dt_match,
#ifdef CONFIG_PM
.pm = &mt8192_afe_pm_ops,
#endif
},
.probe = mt8192_afe_pcm_dev_probe,
.remove = mt8192_afe_pcm_dev_remove,
};
module_platform_driver(mt8192_afe_pcm_driver);
MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8192");
MODULE_AUTHOR("Shane Chien <shane.chien@mediatek.com>");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio DAI ADDA Control
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/delay.h>
#include <linux/regmap.h>
#include "mt8192-afe-clk.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-gpio.h"
#include "mt8192-interconnection.h"
enum {
UL_IIR_SW = 0,
UL_IIR_5HZ,
UL_IIR_10HZ,
UL_IIR_25HZ,
UL_IIR_50HZ,
UL_IIR_75HZ,
};
enum {
AUDIO_SDM_LEVEL_MUTE = 0,
AUDIO_SDM_LEVEL_NORMAL = 0x1d,
/* if you change level normal */
/* you need to change formula of hp impedance and dc trim too */
};
enum {
AUDIO_SDM_2ND = 0,
AUDIO_SDM_3RD,
};
enum {
DELAY_DATA_MISO1 = 0,
DELAY_DATA_MISO2,
};
enum {
MTK_AFE_ADDA_DL_RATE_8K = 0,
MTK_AFE_ADDA_DL_RATE_11K = 1,
MTK_AFE_ADDA_DL_RATE_12K = 2,
MTK_AFE_ADDA_DL_RATE_16K = 3,
MTK_AFE_ADDA_DL_RATE_22K = 4,
MTK_AFE_ADDA_DL_RATE_24K = 5,
MTK_AFE_ADDA_DL_RATE_32K = 6,
MTK_AFE_ADDA_DL_RATE_44K = 7,
MTK_AFE_ADDA_DL_RATE_48K = 8,
MTK_AFE_ADDA_DL_RATE_96K = 9,
MTK_AFE_ADDA_DL_RATE_192K = 10,
};
enum {
MTK_AFE_ADDA_UL_RATE_8K = 0,
MTK_AFE_ADDA_UL_RATE_16K = 1,
MTK_AFE_ADDA_UL_RATE_32K = 2,
MTK_AFE_ADDA_UL_RATE_48K = 3,
MTK_AFE_ADDA_UL_RATE_96K = 4,
MTK_AFE_ADDA_UL_RATE_192K = 5,
MTK_AFE_ADDA_UL_RATE_48K_HD = 6,
};
#define SDM_AUTO_RESET_THRESHOLD 0x190000
static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_ADDA_DL_RATE_8K;
case 11025:
return MTK_AFE_ADDA_DL_RATE_11K;
case 12000:
return MTK_AFE_ADDA_DL_RATE_12K;
case 16000:
return MTK_AFE_ADDA_DL_RATE_16K;
case 22050:
return MTK_AFE_ADDA_DL_RATE_22K;
case 24000:
return MTK_AFE_ADDA_DL_RATE_24K;
case 32000:
return MTK_AFE_ADDA_DL_RATE_32K;
case 44100:
return MTK_AFE_ADDA_DL_RATE_44K;
case 48000:
return MTK_AFE_ADDA_DL_RATE_48K;
case 96000:
return MTK_AFE_ADDA_DL_RATE_96K;
case 192000:
return MTK_AFE_ADDA_DL_RATE_192K;
default:
dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
__func__, rate);
return MTK_AFE_ADDA_DL_RATE_48K;
}
}
static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe,
unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_ADDA_UL_RATE_8K;
case 16000:
return MTK_AFE_ADDA_UL_RATE_16K;
case 32000:
return MTK_AFE_ADDA_UL_RATE_32K;
case 48000:
return MTK_AFE_ADDA_UL_RATE_48K;
case 96000:
return MTK_AFE_ADDA_UL_RATE_96K;
case 192000:
return MTK_AFE_ADDA_UL_RATE_192K;
default:
dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
__func__, rate);
return MTK_AFE_ADDA_UL_RATE_48K;
}
}
/* dai component */
static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN3, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN3_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN3_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN3_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN3_1, I_DL8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN3,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN3,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1", AFE_CONN3_1,
I_SRC_1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH1", AFE_CONN3_1,
I_SRC_2_OUT_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN4, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN4_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN4_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN4_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN4_1, I_DL8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN4,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN4,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4,
I_PCM_2_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2", AFE_CONN4_1,
I_SRC_1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH2", AFE_CONN4_1,
I_SRC_2_OUT_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_adda_dl_ch3_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN52, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN52, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN52, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN52, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN52_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN52_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN52_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN52,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN52,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN52,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN52,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN52,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN52,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_adda_dl_ch4_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN53, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN53, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN53, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN53, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN53, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN53, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN53, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN53_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN53_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN53_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN53,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN53,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN53,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN53,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN53,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN53,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN53,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN53,
I_PCM_2_CAP_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_stf_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN19,
I_ADDA_UL_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_stf_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN20,
I_ADDA_UL_CH2, 1, 0),
};
enum {
SUPPLY_SEQ_ADDA_AFE_ON,
SUPPLY_SEQ_ADDA_DL_ON,
SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
SUPPLY_SEQ_ADDA_MTKAIF_CFG,
SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
SUPPLY_SEQ_ADDA_FIFO,
SUPPLY_SEQ_ADDA_AP_DMIC,
SUPPLY_SEQ_ADDA_UL_ON,
};
static int mtk_adda_ul_src_dmic(struct mtk_base_afe *afe, int id)
{
unsigned int reg;
switch (id) {
case MT8192_DAI_ADDA:
case MT8192_DAI_AP_DMIC:
reg = AFE_ADDA_UL_SRC_CON0;
break;
case MT8192_DAI_ADDA_CH34:
case MT8192_DAI_AP_DMIC_CH34:
reg = AFE_ADDA6_UL_SRC_CON0;
break;
default:
return -EINVAL;
}
/* dmic mode, 3.25M*/
regmap_update_bits(afe->regmap, reg,
DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT,
0x0);
regmap_update_bits(afe->regmap, reg,
DMIC_LOW_POWER_MODE_CTL_MASK_SFT,
0x0);
/* turn on dmic, ch1, ch2 */
regmap_update_bits(afe->regmap, reg,
UL_SDM_3_LEVEL_CTL_MASK_SFT,
0x1 << UL_SDM_3_LEVEL_CTL_SFT);
regmap_update_bits(afe->regmap, reg,
UL_MODE_3P25M_CH1_CTL_MASK_SFT,
0x1 << UL_MODE_3P25M_CH1_CTL_SFT);
regmap_update_bits(afe->regmap, reg,
UL_MODE_3P25M_CH2_CTL_MASK_SFT,
0x1 << UL_MODE_3P25M_CH2_CTL_SFT);
return 0;
}
static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int mtkaif_dmic = afe_priv->mtkaif_dmic;
dev_info(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n",
__func__, w->name, event, mtkaif_dmic);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1);
/* update setting to dmic */
if (mtkaif_dmic) {
/* mtkaif_rxif_data_mode = 1, dmic */
regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
0x1, 0x1);
/* dmic mode, 3.25M*/
regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
MTKAIF_RXIF_VOICE_MODE_MASK_SFT,
0x0);
mtk_adda_ul_src_dmic(afe, MT8192_DAI_ADDA);
}
break;
case SND_SOC_DAPM_POST_PMD:
/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
usleep_range(125, 135);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 1);
break;
default:
break;
}
return 0;
}
static int mtk_adda_ch34_ul_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int mtkaif_dmic = afe_priv->mtkaif_dmic_ch34;
int mtkaif_adda6_only = afe_priv->mtkaif_adda6_only;
dev_info(afe->dev,
"%s(), name %s, event 0x%x, mtkaif_dmic %d, mtkaif_adda6_only %d\n",
__func__, w->name, event, mtkaif_dmic, mtkaif_adda6_only);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34,
1);
/* update setting to dmic */
if (mtkaif_dmic) {
/* mtkaif_rxif_data_mode = 1, dmic */
regmap_update_bits(afe->regmap,
AFE_ADDA6_MTKAIF_RX_CFG0,
0x1, 0x1);
/* dmic mode, 3.25M*/
regmap_update_bits(afe->regmap,
AFE_ADDA6_MTKAIF_RX_CFG0,
MTKAIF_RXIF_VOICE_MODE_MASK_SFT,
0x0);
mtk_adda_ul_src_dmic(afe, MT8192_DAI_ADDA_CH34);
}
/* when using adda6 without adda enabled,
* RG_ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE_SFT need to be set or
* data cannot be received.
*/
if (mtkaif_adda6_only) {
regmap_update_bits(afe->regmap,
AFE_ADDA_MTKAIF_SYNCWORD_CFG,
0x1 << 23, 0x1 << 23);
}
break;
case SND_SOC_DAPM_POST_PMD:
/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
usleep_range(125, 135);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34,
1);
/* reset dmic */
afe_priv->mtkaif_dmic_ch34 = 0;
if (mtkaif_adda6_only) {
regmap_update_bits(afe->regmap,
AFE_ADDA_MTKAIF_SYNCWORD_CFG,
0x1 << 23, 0x0 << 23);
}
break;
default:
break;
}
return 0;
}
static int mtk_adda_pad_top_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2)
regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x38);
else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2)
regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x30);
else
regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x30);
break;
default:
break;
}
return 0;
}
static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int delay_data;
int delay_cycle;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) {
/* set protocol 2 */
regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
0x00010000);
regmap_write(afe->regmap, AFE_ADDA6_MTKAIF_CFG0,
0x00010000);
if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0 &&
(afe_priv->mtkaif_chosen_phase[0] < 0 ||
afe_priv->mtkaif_chosen_phase[1] < 0)) {
dev_warn(afe->dev,
"%s(), mtkaif_chosen_phase[0/1]:%d/%d\n",
__func__,
afe_priv->mtkaif_chosen_phase[0],
afe_priv->mtkaif_chosen_phase[1]);
break;
} else if (strcmp(w->name, "ADDA6_MTKAIF_CFG") == 0 &&
afe_priv->mtkaif_chosen_phase[2] < 0) {
dev_warn(afe->dev,
"%s(), mtkaif_chosen_phase[2]:%d\n",
__func__,
afe_priv->mtkaif_chosen_phase[2]);
break;
}
/* mtkaif_rxif_clkinv_adc inverse for calibration */
regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
MTKAIF_RXIF_CLKINV_ADC_MASK_SFT,
0x1 << MTKAIF_RXIF_CLKINV_ADC_SFT);
regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_CFG0,
MTKAIF_RXIF_CLKINV_ADC_MASK_SFT,
0x1 << MTKAIF_RXIF_CLKINV_ADC_SFT);
/* set delay for ch12 */
if (afe_priv->mtkaif_phase_cycle[0] >=
afe_priv->mtkaif_phase_cycle[1]) {
delay_data = DELAY_DATA_MISO1;
delay_cycle = afe_priv->mtkaif_phase_cycle[0] -
afe_priv->mtkaif_phase_cycle[1];
} else {
delay_data = DELAY_DATA_MISO2;
delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
afe_priv->mtkaif_phase_cycle[0];
}
regmap_update_bits(afe->regmap,
AFE_ADDA_MTKAIF_RX_CFG2,
MTKAIF_RXIF_DELAY_DATA_MASK_SFT,
delay_data <<
MTKAIF_RXIF_DELAY_DATA_SFT);
regmap_update_bits(afe->regmap,
AFE_ADDA_MTKAIF_RX_CFG2,
MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,
delay_cycle <<
MTKAIF_RXIF_DELAY_CYCLE_SFT);
/* set delay between ch3 and ch2 */
if (afe_priv->mtkaif_phase_cycle[2] >=
afe_priv->mtkaif_phase_cycle[1]) {
delay_data = DELAY_DATA_MISO1; /* ch3 */
delay_cycle = afe_priv->mtkaif_phase_cycle[2] -
afe_priv->mtkaif_phase_cycle[1];
} else {
delay_data = DELAY_DATA_MISO2; /* ch2 */
delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
afe_priv->mtkaif_phase_cycle[2];
}
regmap_update_bits(afe->regmap,
AFE_ADDA6_MTKAIF_RX_CFG2,
MTKAIF_RXIF_DELAY_DATA_MASK_SFT,
delay_data <<
MTKAIF_RXIF_DELAY_DATA_SFT);
regmap_update_bits(afe->regmap,
AFE_ADDA6_MTKAIF_RX_CFG2,
MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,
delay_cycle <<
MTKAIF_RXIF_DELAY_CYCLE_SFT);
} else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) {
regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
0x00010000);
regmap_write(afe->regmap, AFE_ADDA6_MTKAIF_CFG0,
0x00010000);
} else {
regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);
regmap_write(afe->regmap, AFE_ADDA6_MTKAIF_CFG0, 0x0);
}
break;
default:
break;
}
return 0;
}
static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0);
break;
case SND_SOC_DAPM_POST_PMD:
/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
usleep_range(125, 135);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 0);
break;
default:
break;
}
return 0;
}
static int mtk_adda_ch34_dl_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34,
0);
break;
case SND_SOC_DAPM_POST_PMD:
/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
usleep_range(125, 135);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34,
0);
break;
default:
break;
}
return 0;
}
/* stf */
static int stf_positive_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
ucontrol->value.integer.value[0] = afe_priv->stf_positive_gain_db;
return 0;
}
static int stf_positive_gain_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int gain_db = ucontrol->value.integer.value[0];
afe_priv->stf_positive_gain_db = gain_db;
if (gain_db >= 0 && gain_db <= 24) {
regmap_update_bits(afe->regmap,
AFE_SIDETONE_GAIN,
POSITIVE_GAIN_MASK_SFT,
(gain_db / 6) << POSITIVE_GAIN_SFT);
} else {
dev_warn(afe->dev, "%s(), gain_db %d invalid\n",
__func__, gain_db);
}
return 0;
}
static int mt8192_adda_dmic_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic;
return 0;
}
static int mt8192_adda_dmic_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dmic_on;
dmic_on = ucontrol->value.integer.value[0];
dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
__func__, kcontrol->id.name, dmic_on);
afe_priv->mtkaif_dmic = dmic_on;
afe_priv->mtkaif_dmic_ch34 = dmic_on;
return 0;
}
static int mt8192_adda6_only_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
ucontrol->value.integer.value[0] = afe_priv->mtkaif_adda6_only;
return 0;
}
static int mt8192_adda6_only_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int mtkaif_adda6_only;
mtkaif_adda6_only = ucontrol->value.integer.value[0];
dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
__func__, kcontrol->id.name, mtkaif_adda6_only);
afe_priv->mtkaif_adda6_only = mtkaif_adda6_only;
return 0;
}
static const struct snd_kcontrol_new mtk_adda_controls[] = {
SOC_SINGLE("Sidetone_Gain", AFE_SIDETONE_GAIN,
SIDE_TONE_GAIN_SFT, SIDE_TONE_GAIN_MASK, 0),
SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 100, 0,
stf_positive_gain_get, stf_positive_gain_set),
SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1,
DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0),
SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC Switch", 0,
mt8192_adda_dmic_get, mt8192_adda_dmic_set),
SOC_SINGLE_BOOL_EXT("MTKAIF_ADDA6_ONLY Switch", 0,
mt8192_adda6_only_get, mt8192_adda6_only_set),
};
static const struct snd_kcontrol_new stf_ctl =
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
static const u16 stf_coeff_table_16k[] = {
0x049C, 0x09E8, 0x09E0, 0x089C,
0xFF54, 0xF488, 0xEAFC, 0xEBAC,
0xfA40, 0x17AC, 0x3D1C, 0x6028,
0x7538
};
static const u16 stf_coeff_table_32k[] = {
0xFE52, 0x0042, 0x00C5, 0x0194,
0x029A, 0x03B7, 0x04BF, 0x057D,
0x05BE, 0x0555, 0x0426, 0x0230,
0xFF92, 0xFC89, 0xF973, 0xF6C6,
0xF500, 0xF49D, 0xF603, 0xF970,
0xFEF3, 0x065F, 0x0F4F, 0x1928,
0x2329, 0x2C80, 0x345E, 0x3A0D,
0x3D08
};
static const u16 stf_coeff_table_48k[] = {
0x0401, 0xFFB0, 0xFF5A, 0xFECE,
0xFE10, 0xFD28, 0xFC21, 0xFB08,
0xF9EF, 0xF8E8, 0xF80A, 0xF76C,
0xF724, 0xF746, 0xF7E6, 0xF90F,
0xFACC, 0xFD1E, 0xFFFF, 0x0364,
0x0737, 0x0B62, 0x0FC1, 0x1431,
0x188A, 0x1CA4, 0x2056, 0x237D,
0x25F9, 0x27B0, 0x2890
};
static int mtk_stf_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
size_t half_tap_num;
const u16 *stf_coeff_table;
unsigned int ul_rate, reg_value;
size_t coef_addr;
regmap_read(afe->regmap, AFE_ADDA_UL_SRC_CON0, &ul_rate);
ul_rate = ul_rate >> UL_VOICE_MODE_CH1_CH2_CTL_SFT;
ul_rate = ul_rate & UL_VOICE_MODE_CH1_CH2_CTL_MASK;
if (ul_rate == MTK_AFE_ADDA_UL_RATE_48K) {
half_tap_num = ARRAY_SIZE(stf_coeff_table_48k);
stf_coeff_table = stf_coeff_table_48k;
} else if (ul_rate == MTK_AFE_ADDA_UL_RATE_32K) {
half_tap_num = ARRAY_SIZE(stf_coeff_table_32k);
stf_coeff_table = stf_coeff_table_32k;
} else {
half_tap_num = ARRAY_SIZE(stf_coeff_table_16k);
stf_coeff_table = stf_coeff_table_16k;
}
regmap_read(afe->regmap, AFE_SIDETONE_CON1, &reg_value);
dev_info(afe->dev, "%s(), name %s, event 0x%x, ul_rate 0x%x, AFE_SIDETONE_CON1 0x%x\n",
__func__, w->name, event, ul_rate, reg_value);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* set side tone gain = 0 */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_GAIN,
SIDE_TONE_GAIN_MASK_SFT,
0);
regmap_update_bits(afe->regmap,
AFE_SIDETONE_GAIN,
POSITIVE_GAIN_MASK_SFT,
0);
/* don't bypass stf */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_CON1,
0x1f << 27,
0x0);
/* set stf half tap num */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_CON1,
SIDE_TONE_HALF_TAP_NUM_MASK_SFT,
half_tap_num << SIDE_TONE_HALF_TAP_NUM_SFT);
/* set side tone coefficient */
regmap_read(afe->regmap, AFE_SIDETONE_CON0, &reg_value);
for (coef_addr = 0; coef_addr < half_tap_num; coef_addr++) {
bool old_w_ready = (reg_value >> W_RDY_SFT) & 0x1;
bool new_w_ready = 0;
int try_cnt = 0;
regmap_update_bits(afe->regmap,
AFE_SIDETONE_CON0,
0x39FFFFF,
(1 << R_W_EN_SFT) |
(1 << R_W_SEL_SFT) |
(0 << SEL_CH2_SFT) |
(coef_addr <<
SIDE_TONE_COEFFICIENT_ADDR_SFT) |
stf_coeff_table[coef_addr]);
/* wait until flag write_ready changed */
for (try_cnt = 0; try_cnt < 10; try_cnt++) {
regmap_read(afe->regmap,
AFE_SIDETONE_CON0, &reg_value);
new_w_ready = (reg_value >> W_RDY_SFT) & 0x1;
/* flip => ok */
if (new_w_ready == old_w_ready) {
udelay(3);
if (try_cnt == 9) {
dev_warn(afe->dev,
"%s(), write coeff not ready",
__func__);
}
} else {
break;
}
}
/* need write -> read -> write to write next coeff */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_CON0,
R_W_SEL_MASK_SFT,
0x0);
}
break;
case SND_SOC_DAPM_POST_PMD:
/* bypass stf */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_CON1,
0x1f << 27,
0x1f << 27);
/* set side tone gain = 0 */
regmap_update_bits(afe->regmap,
AFE_SIDETONE_GAIN,
SIDE_TONE_GAIN_MASK_SFT,
0);
regmap_update_bits(afe->regmap,
AFE_SIDETONE_GAIN,
POSITIVE_GAIN_MASK_SFT,
0);
break;
default:
break;
}
return 0;
}
/* stf mux */
enum {
STF_SRC_ADDA_ADDA6 = 0,
STF_SRC_O19O20,
};
static const char *const stf_o19o20_mux_map[] = {
"ADDA_ADDA6",
"O19O20",
};
static int stf_o19o20_mux_map_value[] = {
STF_SRC_ADDA_ADDA6,
STF_SRC_O19O20,
};
static SOC_VALUE_ENUM_SINGLE_DECL(stf_o19o20_mux_map_enum,
AFE_SIDETONE_CON1,
STF_SOURCE_FROM_O19O20_SFT,
STF_SOURCE_FROM_O19O20_MASK,
stf_o19o20_mux_map,
stf_o19o20_mux_map_value);
static const struct snd_kcontrol_new stf_o19O20_mux_control =
SOC_DAPM_ENUM("STF_O19O20_MUX", stf_o19o20_mux_map_enum);
enum {
STF_SRC_ADDA = 0,
STF_SRC_ADDA6,
};
static const char *const stf_adda_mux_map[] = {
"ADDA",
"ADDA6",
};
static int stf_adda_mux_map_value[] = {
STF_SRC_ADDA,
STF_SRC_ADDA6,
};
static SOC_VALUE_ENUM_SINGLE_DECL(stf_adda_mux_map_enum,
AFE_SIDETONE_CON1,
STF_O19O20_OUT_EN_SEL_SFT,
STF_O19O20_OUT_EN_SEL_MASK,
stf_adda_mux_map,
stf_adda_mux_map_value);
static const struct snd_kcontrol_new stf_adda_mux_control =
SOC_DAPM_ENUM("STF_ADDA_MUX", stf_adda_mux_map_enum);
/* ADDA UL MUX */
enum {
ADDA_UL_MUX_MTKAIF = 0,
ADDA_UL_MUX_AP_DMIC,
ADDA_UL_MUX_MASK = 0x1,
};
static const char * const adda_ul_mux_map[] = {
"MTKAIF", "AP_DMIC"
};
static int adda_ul_map_value[] = {
ADDA_UL_MUX_MTKAIF,
ADDA_UL_MUX_AP_DMIC,
};
static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum,
SND_SOC_NOPM,
0,
ADDA_UL_MUX_MASK,
adda_ul_mux_map,
adda_ul_map_value);
static const struct snd_kcontrol_new adda_ul_mux_control =
SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum);
static const struct snd_kcontrol_new adda_ch34_ul_mux_control =
SOC_DAPM_ENUM("ADDA_CH34_UL_MUX Select", adda_ul_mux_map_enum);
static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch1_mix,
ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch2_mix,
ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
SND_SOC_DAPM_MIXER("ADDA_DL_CH3", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch3_mix,
ARRAY_SIZE(mtk_adda_dl_ch3_mix)),
SND_SOC_DAPM_MIXER("ADDA_DL_CH4", SND_SOC_NOPM, 0, 0,
mtk_adda_dl_ch4_mix,
ARRAY_SIZE(mtk_adda_dl_ch4_mix)),
SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
AFE_ADDA_DL_SRC2_CON0,
DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,
mtk_adda_dl_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Playback Enable",
SUPPLY_SEQ_ADDA_DL_ON,
AFE_ADDA_3RD_DAC_DL_SRC2_CON0,
DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,
mtk_adda_ch34_dl_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
AFE_ADDA_UL_SRC_CON0,
UL_SRC_ON_TMP_CTL_SFT, 0,
mtk_adda_ul_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
AFE_ADDA6_UL_SRC_CON0,
UL_SRC_ON_TMP_CTL_SFT, 0,
mtk_adda_ch34_ul_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("AUD_PAD_TOP", SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
AFE_AUD_PAD_TOP,
RG_RX_FIFO_ON_SFT, 0,
mtk_adda_pad_top_event,
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
SND_SOC_NOPM, 0, 0,
mtk_adda_mtkaif_cfg_event,
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY_S("ADDA6_MTKAIF_CFG", SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
SND_SOC_NOPM, 0, 0,
mtk_adda_mtkaif_cfg_event,
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
AFE_ADDA_UL_SRC_CON0,
UL_AP_DMIC_ON_SFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AP_DMIC_CH34_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
AFE_ADDA6_UL_SRC_CON0,
UL_AP_DMIC_ON_SFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO,
AFE_ADDA_UL_DL_CON0,
AFE_ADDA_FIFO_AUTO_RST_SFT, 1,
NULL, 0),
SND_SOC_DAPM_SUPPLY_S("ADDA_CH34_FIFO", SUPPLY_SEQ_ADDA_FIFO,
AFE_ADDA_UL_DL_CON0,
AFE_ADDA6_FIFO_AUTO_RST_SFT, 1,
NULL, 0),
SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0,
&adda_ul_mux_control),
SND_SOC_DAPM_MUX("ADDA_CH34_UL_Mux", SND_SOC_NOPM, 0, 0,
&adda_ch34_ul_mux_control),
SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"),
SND_SOC_DAPM_INPUT("AP_DMIC_CH34_INPUT"),
/* stf */
SND_SOC_DAPM_SWITCH_E("Sidetone Filter",
AFE_SIDETONE_CON1, SIDE_TONE_ON_SFT, 0,
&stf_ctl,
mtk_stf_event,
SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("STF_O19O20_MUX", SND_SOC_NOPM, 0, 0,
&stf_o19O20_mux_control),
SND_SOC_DAPM_MUX("STF_ADDA_MUX", SND_SOC_NOPM, 0, 0,
&stf_adda_mux_control),
SND_SOC_DAPM_MIXER("STF_CH1", SND_SOC_NOPM, 0, 0,
mtk_stf_ch1_mix,
ARRAY_SIZE(mtk_stf_ch1_mix)),
SND_SOC_DAPM_MIXER("STF_CH2", SND_SOC_NOPM, 0, 0,
mtk_stf_ch2_mix,
ARRAY_SIZE(mtk_stf_ch2_mix)),
SND_SOC_DAPM_OUTPUT("STF_OUTPUT"),
/* clock */
SND_SOC_DAPM_CLOCK_SUPPLY("top_mux_audio_h"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_3rd_dac_clk"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_3rd_dac_predis_clk"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc_clk"),
};
static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
/* playback */
{"ADDA_DL_CH1", "DL1_CH1", "DL1"},
{"ADDA_DL_CH2", "DL1_CH1", "DL1"},
{"ADDA_DL_CH2", "DL1_CH2", "DL1"},
{"ADDA_DL_CH1", "DL12_CH1", "DL12"},
{"ADDA_DL_CH2", "DL12_CH2", "DL12"},
{"ADDA_DL_CH1", "DL6_CH1", "DL6"},
{"ADDA_DL_CH2", "DL6_CH2", "DL6"},
{"ADDA_DL_CH1", "DL8_CH1", "DL8"},
{"ADDA_DL_CH2", "DL8_CH2", "DL8"},
{"ADDA_DL_CH1", "DL2_CH1", "DL2"},
{"ADDA_DL_CH2", "DL2_CH1", "DL2"},
{"ADDA_DL_CH2", "DL2_CH2", "DL2"},
{"ADDA_DL_CH1", "DL3_CH1", "DL3"},
{"ADDA_DL_CH2", "DL3_CH1", "DL3"},
{"ADDA_DL_CH2", "DL3_CH2", "DL3"},
{"ADDA_DL_CH1", "DL4_CH1", "DL4"},
{"ADDA_DL_CH2", "DL4_CH2", "DL4"},
{"ADDA_DL_CH1", "DL5_CH1", "DL5"},
{"ADDA_DL_CH2", "DL5_CH2", "DL5"},
{"ADDA Playback", NULL, "ADDA_DL_CH1"},
{"ADDA Playback", NULL, "ADDA_DL_CH2"},
{"ADDA Playback", NULL, "ADDA Enable"},
{"ADDA Playback", NULL, "ADDA Playback Enable"},
{"ADDA_DL_CH3", "DL1_CH1", "DL1"},
{"ADDA_DL_CH4", "DL1_CH1", "DL1"},
{"ADDA_DL_CH4", "DL1_CH2", "DL1"},
{"ADDA_DL_CH3", "DL12_CH1", "DL12"},
{"ADDA_DL_CH4", "DL12_CH2", "DL12"},
{"ADDA_DL_CH3", "DL6_CH1", "DL6"},
{"ADDA_DL_CH4", "DL6_CH2", "DL6"},
{"ADDA_DL_CH3", "DL2_CH1", "DL2"},
{"ADDA_DL_CH4", "DL2_CH1", "DL2"},
{"ADDA_DL_CH4", "DL2_CH2", "DL2"},
{"ADDA_DL_CH3", "DL3_CH1", "DL3"},
{"ADDA_DL_CH4", "DL3_CH1", "DL3"},
{"ADDA_DL_CH4", "DL3_CH2", "DL3"},
{"ADDA_DL_CH3", "DL4_CH1", "DL4"},
{"ADDA_DL_CH4", "DL4_CH2", "DL4"},
{"ADDA_DL_CH3", "DL5_CH1", "DL5"},
{"ADDA_DL_CH4", "DL5_CH2", "DL5"},
{"ADDA CH34 Playback", NULL, "ADDA_DL_CH3"},
{"ADDA CH34 Playback", NULL, "ADDA_DL_CH4"},
{"ADDA CH34 Playback", NULL, "ADDA Enable"},
{"ADDA CH34 Playback", NULL, "ADDA CH34 Playback Enable"},
/* capture */
{"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"},
{"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"},
{"ADDA_CH34_UL_Mux", "MTKAIF", "ADDA CH34 Capture"},
{"ADDA_CH34_UL_Mux", "AP_DMIC", "AP DMIC CH34 Capture"},
{"ADDA Capture", NULL, "ADDA Enable"},
{"ADDA Capture", NULL, "ADDA Capture Enable"},
{"ADDA Capture", NULL, "AUD_PAD_TOP"},
{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
{"AP DMIC Capture", NULL, "ADDA Enable"},
{"AP DMIC Capture", NULL, "ADDA Capture Enable"},
{"AP DMIC Capture", NULL, "ADDA_FIFO"},
{"AP DMIC Capture", NULL, "AP_DMIC_EN"},
{"ADDA CH34 Capture", NULL, "ADDA Enable"},
{"ADDA CH34 Capture", NULL, "ADDA CH34 Capture Enable"},
{"ADDA CH34 Capture", NULL, "AUD_PAD_TOP"},
{"ADDA CH34 Capture", NULL, "ADDA6_MTKAIF_CFG"},
{"AP DMIC CH34 Capture", NULL, "ADDA Enable"},
{"AP DMIC CH34 Capture", NULL, "ADDA CH34 Capture Enable"},
{"AP DMIC CH34 Capture", NULL, "ADDA_CH34_FIFO"},
{"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_EN"},
{"AP DMIC Capture", NULL, "AP_DMIC_INPUT"},
{"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_INPUT"},
/* sidetone filter */
{"STF_ADDA_MUX", "ADDA", "ADDA_UL_Mux"},
{"STF_ADDA_MUX", "ADDA6", "ADDA_CH34_UL_Mux"},
{"STF_O19O20_MUX", "ADDA_ADDA6", "STF_ADDA_MUX"},
{"STF_O19O20_MUX", "O19O20", "STF_CH1"},
{"STF_O19O20_MUX", "O19O20", "STF_CH2"},
{"Sidetone Filter", "Switch", "STF_O19O20_MUX"},
{"STF_OUTPUT", NULL, "Sidetone Filter"},
{"ADDA Playback", NULL, "Sidetone Filter"},
{"ADDA CH34 Playback", NULL, "Sidetone Filter"},
/* clk */
{"ADDA Playback", NULL, "aud_dac_clk"},
{"ADDA Playback", NULL, "aud_dac_predis_clk"},
{"ADDA CH34 Playback", NULL, "aud_3rd_dac_clk"},
{"ADDA CH34 Playback", NULL, "aud_3rd_dac_predis_clk"},
{"ADDA Capture Enable", NULL, "aud_adc_clk"},
{"ADDA CH34 Capture Enable", NULL, "aud_adda6_adc_clk"},
};
/* dai ops */
static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
unsigned int rate = params_rate(params);
int id = dai->id;
dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
__func__,
id,
substream->stream,
rate);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
unsigned int dl_src2_con0 = 0;
unsigned int dl_src2_con1 = 0;
/* set sampling rate */
dl_src2_con0 = adda_dl_rate_transform(afe, rate) <<
DL_2_INPUT_MODE_CTL_SFT;
/* set output mode, UP_SAMPLING_RATE_X8 */
dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT);
/* turn off mute function */
dl_src2_con0 |= (0x01 << DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);
dl_src2_con0 |= (0x01 << DL_2_MUTE_CH1_OFF_CTL_PRE_SFT);
/* set voice input data if input sample rate is 8k or 16k */
if (rate == 8000 || rate == 16000)
dl_src2_con0 |= 0x01 << DL_2_VOICE_MODE_CTL_PRE_SFT;
/* SA suggest apply -0.3db to audio/speech path */
dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL <<
DL_2_GAIN_CTL_PRE_SFT;
/* turn on down-link gain */
dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT);
if (id == MT8192_DAI_ADDA) {
/* clean predistortion */
regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);
regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);
regmap_write(afe->regmap,
AFE_ADDA_DL_SRC2_CON0, dl_src2_con0);
regmap_write(afe->regmap,
AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);
/* set sdm gain */
regmap_update_bits(afe->regmap,
AFE_ADDA_DL_SDM_DCCOMP_CON,
ATTGAIN_CTL_MASK_SFT,
AUDIO_SDM_LEVEL_NORMAL <<
ATTGAIN_CTL_SFT);
/* 2nd sdm */
regmap_update_bits(afe->regmap,
AFE_ADDA_DL_SDM_DCCOMP_CON,
USE_3RD_SDM_MASK_SFT,
AUDIO_SDM_2ND << USE_3RD_SDM_SFT);
/* sdm auto reset */
regmap_write(afe->regmap,
AFE_ADDA_DL_SDM_AUTO_RESET_CON,
SDM_AUTO_RESET_THRESHOLD);
regmap_update_bits(afe->regmap,
AFE_ADDA_DL_SDM_AUTO_RESET_CON,
ADDA_SDM_AUTO_RESET_ONOFF_MASK_SFT,
0x1 << ADDA_SDM_AUTO_RESET_ONOFF_SFT);
} else {
/* clean predistortion */
regmap_write(afe->regmap,
AFE_ADDA_3RD_DAC_PREDIS_CON0, 0);
regmap_write(afe->regmap,
AFE_ADDA_3RD_DAC_PREDIS_CON1, 0);
regmap_write(afe->regmap, AFE_ADDA_3RD_DAC_DL_SRC2_CON0,
dl_src2_con0);
regmap_write(afe->regmap, AFE_ADDA_3RD_DAC_DL_SRC2_CON1,
dl_src2_con1);
/* set sdm gain */
regmap_update_bits(afe->regmap,
AFE_ADDA_3RD_DAC_DL_SDM_DCCOMP_CON,
ATTGAIN_CTL_MASK_SFT,
AUDIO_SDM_LEVEL_NORMAL <<
ATTGAIN_CTL_SFT);
/* 2nd sdm */
regmap_update_bits(afe->regmap,
AFE_ADDA_3RD_DAC_DL_SDM_DCCOMP_CON,
USE_3RD_SDM_MASK_SFT,
AUDIO_SDM_2ND << USE_3RD_SDM_SFT);
/* sdm auto reset */
regmap_write(afe->regmap,
AFE_ADDA_3RD_DAC_DL_SDM_AUTO_RESET_CON,
SDM_AUTO_RESET_THRESHOLD);
regmap_update_bits(afe->regmap,
AFE_ADDA_3RD_DAC_DL_SDM_AUTO_RESET_CON,
ADDA_3RD_DAC_SDM_AUTO_RESET_ONOFF_MASK_SFT,
0x1 << ADDA_3RD_DAC_SDM_AUTO_RESET_ONOFF_SFT);
}
} else {
unsigned int voice_mode = 0;
unsigned int ul_src_con0 = 0; /* default value */
voice_mode = adda_ul_rate_transform(afe, rate);
ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
/* enable iir */
ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
UL_IIR_ON_TMP_CTL_MASK_SFT;
ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
UL_IIRMODE_CTL_MASK_SFT;
switch (id) {
case MT8192_DAI_ADDA:
case MT8192_DAI_AP_DMIC:
/* 35Hz @ 48k */
regmap_write(afe->regmap,
AFE_ADDA_IIR_COEF_02_01, 0x00000000);
regmap_write(afe->regmap,
AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);
regmap_write(afe->regmap,
AFE_ADDA_IIR_COEF_06_05, 0x3FB80000);
regmap_write(afe->regmap,
AFE_ADDA_IIR_COEF_08_07, 0x3FB80000);
regmap_write(afe->regmap,
AFE_ADDA_IIR_COEF_10_09, 0x0000C048);
regmap_write(afe->regmap,
AFE_ADDA_UL_SRC_CON0, ul_src_con0);
/* Using Internal ADC */
regmap_update_bits(afe->regmap,
AFE_ADDA_TOP_CON0,
0x1 << 0,
0x0 << 0);
/* mtkaif_rxif_data_mode = 0, amic */
regmap_update_bits(afe->regmap,
AFE_ADDA_MTKAIF_RX_CFG0,
0x1 << 0,
0x0 << 0);
break;
case MT8192_DAI_ADDA_CH34:
case MT8192_DAI_AP_DMIC_CH34:
/* 35Hz @ 48k */
regmap_write(afe->regmap,
AFE_ADDA6_IIR_COEF_02_01, 0x00000000);
regmap_write(afe->regmap,
AFE_ADDA6_IIR_COEF_04_03, 0x00003FB8);
regmap_write(afe->regmap,
AFE_ADDA6_IIR_COEF_06_05, 0x3FB80000);
regmap_write(afe->regmap,
AFE_ADDA6_IIR_COEF_08_07, 0x3FB80000);
regmap_write(afe->regmap,
AFE_ADDA6_IIR_COEF_10_09, 0x0000C048);
regmap_write(afe->regmap,
AFE_ADDA6_UL_SRC_CON0, ul_src_con0);
/* Using Internal ADC */
regmap_update_bits(afe->regmap,
AFE_ADDA6_TOP_CON0,
0x1 << 0,
0x0 << 0);
/* mtkaif_rxif_data_mode = 0, amic */
regmap_update_bits(afe->regmap,
AFE_ADDA6_MTKAIF_RX_CFG0,
0x1 << 0,
0x0 << 0);
break;
default:
break;
}
/* ap dmic */
switch (id) {
case MT8192_DAI_AP_DMIC:
case MT8192_DAI_AP_DMIC_CH34:
mtk_adda_ul_src_dmic(afe, id);
break;
default:
break;
}
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
.hw_params = mtk_dai_adda_hw_params,
};
/* dai driver */
#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_192000)
#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 |\
SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_192000)
#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
{
.name = "ADDA",
.id = MT8192_DAI_ADDA,
.playback = {
.stream_name = "ADDA Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_PLAYBACK_RATES,
.formats = MTK_ADDA_FORMATS,
},
.capture = {
.stream_name = "ADDA Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_CAPTURE_RATES,
.formats = MTK_ADDA_FORMATS,
},
.ops = &mtk_dai_adda_ops,
},
{
.name = "ADDA_CH34",
.id = MT8192_DAI_ADDA_CH34,
.playback = {
.stream_name = "ADDA CH34 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_PLAYBACK_RATES,
.formats = MTK_ADDA_FORMATS,
},
.capture = {
.stream_name = "ADDA CH34 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_CAPTURE_RATES,
.formats = MTK_ADDA_FORMATS,
},
.ops = &mtk_dai_adda_ops,
},
{
.name = "AP_DMIC",
.id = MT8192_DAI_AP_DMIC,
.capture = {
.stream_name = "AP DMIC Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_CAPTURE_RATES,
.formats = MTK_ADDA_FORMATS,
},
.ops = &mtk_dai_adda_ops,
},
{
.name = "AP_DMIC_CH34",
.id = MT8192_DAI_AP_DMIC_CH34,
.capture = {
.stream_name = "AP DMIC CH34 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_ADDA_CAPTURE_RATES,
.formats = MTK_ADDA_FORMATS,
},
.ops = &mtk_dai_adda_ops,
},
};
int mt8192_dai_adda_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
struct mt8192_afe_private *afe_priv = afe->platform_priv;
dev_info(afe->dev, "%s()\n", __func__);
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_adda_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
dai->controls = mtk_adda_controls;
dai->num_controls = ARRAY_SIZE(mtk_adda_controls);
dai->dapm_widgets = mtk_dai_adda_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
dai->dapm_routes = mtk_dai_adda_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
/* ap dmic priv share with adda */
afe_priv->dai_priv[MT8192_DAI_AP_DMIC] =
afe_priv->dai_priv[MT8192_DAI_ADDA];
afe_priv->dai_priv[MT8192_DAI_AP_DMIC_CH34] =
afe_priv->dai_priv[MT8192_DAI_ADDA_CH34];
return 0;
}
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio DAI I2S Control
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8192-afe-clk.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-gpio.h"
#include "mt8192-interconnection.h"
enum {
I2S_FMT_EIAJ = 0,
I2S_FMT_I2S = 1,
};
enum {
I2S_WLEN_16_BIT = 0,
I2S_WLEN_32_BIT = 1,
};
enum {
I2S_HD_NORMAL = 0,
I2S_HD_LOW_JITTER = 1,
};
enum {
I2S1_SEL_O28_O29 = 0,
I2S1_SEL_O03_O04 = 1,
};
enum {
I2S_IN_PAD_CONNSYS = 0,
I2S_IN_PAD_IO_MUX = 1,
};
struct mtk_afe_i2s_priv {
int id;
int rate; /* for determine which apll to use */
int low_jitter_en;
const char *share_property_name;
int share_i2s_id;
int mclk_id;
int mclk_rate;
int mclk_apll;
};
static unsigned int get_i2s_wlen(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;
}
#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"
#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"
#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"
#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"
#define MTK_AFE_I2S5_KCONTROL_NAME "I2S5_HD_Mux"
#define MTK_AFE_I2S6_KCONTROL_NAME "I2S6_HD_Mux"
#define MTK_AFE_I2S7_KCONTROL_NAME "I2S7_HD_Mux"
#define MTK_AFE_I2S8_KCONTROL_NAME "I2S8_HD_Mux"
#define MTK_AFE_I2S9_KCONTROL_NAME "I2S9_HD_Mux"
#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"
#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"
#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"
#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"
#define I2S5_HD_EN_W_NAME "I2S5_HD_EN"
#define I2S6_HD_EN_W_NAME "I2S6_HD_EN"
#define I2S7_HD_EN_W_NAME "I2S7_HD_EN"
#define I2S8_HD_EN_W_NAME "I2S8_HD_EN"
#define I2S9_HD_EN_W_NAME "I2S9_HD_EN"
#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"
#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"
#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"
#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"
#define I2S5_MCLK_EN_W_NAME "I2S5_MCLK_EN"
#define I2S6_MCLK_EN_W_NAME "I2S6_MCLK_EN"
#define I2S7_MCLK_EN_W_NAME "I2S7_MCLK_EN"
#define I2S8_MCLK_EN_W_NAME "I2S8_MCLK_EN"
#define I2S9_MCLK_EN_W_NAME "I2S9_MCLK_EN"
static int get_i2s_id_by_name(struct mtk_base_afe *afe,
const char *name)
{
if (strncmp(name, "I2S0", 4) == 0)
return MT8192_DAI_I2S_0;
else if (strncmp(name, "I2S1", 4) == 0)
return MT8192_DAI_I2S_1;
else if (strncmp(name, "I2S2", 4) == 0)
return MT8192_DAI_I2S_2;
else if (strncmp(name, "I2S3", 4) == 0)
return MT8192_DAI_I2S_3;
else if (strncmp(name, "I2S5", 4) == 0)
return MT8192_DAI_I2S_5;
else if (strncmp(name, "I2S6", 4) == 0)
return MT8192_DAI_I2S_6;
else if (strncmp(name, "I2S7", 4) == 0)
return MT8192_DAI_I2S_7;
else if (strncmp(name, "I2S8", 4) == 0)
return MT8192_DAI_I2S_8;
else if (strncmp(name, "I2S9", 4) == 0)
return MT8192_DAI_I2S_9;
else
return -EINVAL;
}
static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,
const char *name)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_i2s_id_by_name(afe, name);
if (dai_id < 0)
return NULL;
return afe_priv->dai_priv[dai_id];
}
/* low jitter control */
static const char * const mt8192_i2s_hd_str[] = {
"Normal", "Low_Jitter"
};
static SOC_ENUM_SINGLE_EXT_DECL(mt8192_i2s_enum, mt8192_i2s_hd_str);
static int mt8192_i2s_hd_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return -EINVAL;
}
ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
return 0;
}
static int mt8192_i2s_hd_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int hd_en;
if (ucontrol->value.enumerated.item[0] >= e->items)
return -EINVAL;
hd_en = ucontrol->value.integer.value[0];
dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
__func__, kcontrol->id.name, hd_en);
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return -EINVAL;
}
i2s_priv->low_jitter_en = hd_en;
return 0;
}
static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {
SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S5_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S6_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S7_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S8_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
SOC_ENUM_EXT(MTK_AFE_I2S9_KCONTROL_NAME, mt8192_i2s_enum,
mt8192_i2s_hd_get, mt8192_i2s_hd_set),
};
/* dai component */
/* i2s virtual mux to output widget */
static const char * const i2s_mux_map[] = {
"Normal", "Dummy_Widget",
};
static int i2s_mux_map_value[] = {
0, 1,
};
static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum,
SND_SOC_NOPM,
0,
1,
i2s_mux_map,
i2s_mux_map_value);
static const struct snd_kcontrol_new i2s0_in_mux_control =
SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s8_in_mux_control =
SOC_DAPM_ENUM("I2S8 In Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s1_out_mux_control =
SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s3_out_mux_control =
SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s5_out_mux_control =
SOC_DAPM_ENUM("I2S5 Out Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s7_out_mux_control =
SOC_DAPM_ENUM("I2S7 Out Select", i2s_mux_map_enum);
static const struct snd_kcontrol_new i2s9_out_mux_control =
SOC_DAPM_ENUM("I2S9 Out Select", i2s_mux_map_enum);
/* Tinyconn Mux */
enum {
TINYCONN_CH1_MUX_DL1 = 0x0,
TINYCONN_CH2_MUX_DL1 = 0x1,
TINYCONN_CH1_MUX_DL12 = 0x2,
TINYCONN_CH2_MUX_DL12 = 0x3,
TINYCONN_CH1_MUX_DL2 = 0x4,
TINYCONN_CH2_MUX_DL2 = 0x5,
TINYCONN_CH1_MUX_DL3 = 0x6,
TINYCONN_CH2_MUX_DL3 = 0x7,
TINYCONN_MUX_NONE = 0x1f,
};
static const char * const tinyconn_mux_map[] = {
"NONE",
"DL1_CH1",
"DL1_CH2",
"DL12_CH1",
"DL12_CH2",
"DL2_CH1",
"DL2_CH2",
"DL3_CH1",
"DL3_CH2",
};
static int tinyconn_mux_map_value[] = {
TINYCONN_MUX_NONE,
TINYCONN_CH1_MUX_DL1,
TINYCONN_CH2_MUX_DL1,
TINYCONN_CH1_MUX_DL12,
TINYCONN_CH2_MUX_DL12,
TINYCONN_CH1_MUX_DL2,
TINYCONN_CH2_MUX_DL2,
TINYCONN_CH1_MUX_DL3,
TINYCONN_CH2_MUX_DL3,
};
static SOC_VALUE_ENUM_SINGLE_DECL(i2s1_tinyconn_ch1_mux_map_enum,
AFE_TINY_CONN5,
O_20_CFG_SFT,
O_20_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static const struct snd_kcontrol_new i2s1_tinyconn_ch1_mux_control =
SOC_DAPM_ENUM("i2s1 ch1 tinyconn Select",
i2s1_tinyconn_ch1_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(i2s1_tinyconn_ch2_mux_map_enum,
AFE_TINY_CONN5,
O_21_CFG_SFT,
O_21_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static const struct snd_kcontrol_new i2s1_tinyconn_ch2_mux_control =
SOC_DAPM_ENUM("i2s1 ch2 tinyconn Select",
i2s1_tinyconn_ch2_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(i2s3_tinyconn_ch1_mux_map_enum,
AFE_TINY_CONN5,
O_22_CFG_SFT,
O_22_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static const struct snd_kcontrol_new i2s3_tinyconn_ch1_mux_control =
SOC_DAPM_ENUM("i2s3 ch1 tinyconn Select",
i2s3_tinyconn_ch1_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(i2s3_tinyconn_ch2_mux_map_enum,
AFE_TINY_CONN5,
O_23_CFG_SFT,
O_23_CFG_MASK,
tinyconn_mux_map,
tinyconn_mux_map_value);
static const struct snd_kcontrol_new i2s3_tinyconn_ch2_mux_control =
SOC_DAPM_ENUM("i2s3 ch2 tinyconn Select",
i2s3_tinyconn_ch2_mux_map_enum);
/* i2s in lpbk */
static const char * const i2s_lpbk_mux_map[] = {
"Normal", "Lpbk",
};
static int i2s_lpbk_mux_map_value[] = {
0, 1,
};
static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum,
AFE_I2S_CON,
I2S_LOOPBACK_SFT,
1,
i2s_lpbk_mux_map,
i2s_lpbk_mux_map_value);
static const struct snd_kcontrol_new i2s0_lpbk_mux_control =
SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum,
AFE_I2S_CON2,
I2S3_LOOPBACK_SFT,
1,
i2s_lpbk_mux_map,
i2s_lpbk_mux_map_value);
static const struct snd_kcontrol_new i2s2_lpbk_mux_control =
SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum);
/* interconnection */
static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN0, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN0, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN0, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN0, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN0_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN0_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN0_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN0_1, I_DL8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH1", AFE_CONN0_1, I_DL9_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN0,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN0,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN0,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN0,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN0,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN0,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN1, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN1, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN1, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN1, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN1_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN1_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN1_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN1_1, I_DL8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH2", AFE_CONN1_1, I_DL9_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN1,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN1,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN1,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN1,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN1,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN1,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN1,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN1,
I_PCM_2_CAP_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN28, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN28, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN28, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN28, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN28_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN28_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN28_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN28_1, I_DL8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH1", AFE_CONN28_1, I_DL9_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN28,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN28,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN28,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN28,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN29, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN29, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN29, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN29, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN29_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN29_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN29_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN29_1, I_DL8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH2", AFE_CONN29_1, I_DL9_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN29,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN29,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN29,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN29,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN29,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN29,
I_PCM_2_CAP_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s5_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN30, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN30, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN30, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN30, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN30_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN30_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN30_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN30_1, I_DL8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH1", AFE_CONN30_1, I_DL9_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN30,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN30,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN30,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN30,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s5_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN31, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN31, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN31, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN31, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN31_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN31_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN31_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN31_1, I_DL8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH2", AFE_CONN31_1, I_DL9_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN31,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN31,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN31,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN31,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN31,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN31,
I_PCM_2_CAP_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s7_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN54, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN54, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN54, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN54, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN54_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN54_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN54_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH1", AFE_CONN54_1, I_DL9_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN54,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN54,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN54,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN54,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s7_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN55, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN55, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN55, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN55, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN55_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN55_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN55_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH2", AFE_CONN55_1, I_DL9_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN55,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN55,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN55,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN55,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN55,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN55,
I_PCM_2_CAP_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s9_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN56, I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN56, I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN56, I_DL3_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1", AFE_CONN56, I_DL12_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN56_1, I_DL6_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN56_1, I_DL4_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN56_1, I_DL5_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN56_1, I_DL8_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH1", AFE_CONN56_1, I_DL9_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1", AFE_CONN56,
I_GAIN1_OUT_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN56,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN56,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN56,
I_PCM_2_CAP_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_i2s9_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN57, I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN57, I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN57, I_DL3_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2", AFE_CONN57, I_DL12_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN57_1, I_DL6_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN57_1, I_DL4_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN57_1, I_DL5_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN57_1, I_DL8_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL9_CH2", AFE_CONN57_1, I_DL9_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2", AFE_CONN57,
I_GAIN1_OUT_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN57,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN57,
I_PCM_1_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN57,
I_PCM_2_CAP_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN57,
I_PCM_1_CAP_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN57,
I_PCM_2_CAP_CH2, 1, 0),
};
enum {
SUPPLY_SEQ_APLL,
SUPPLY_SEQ_I2S_MCLK_EN,
SUPPLY_SEQ_I2S_HD_EN,
SUPPLY_SEQ_I2S_EN,
};
static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, w->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return -EINVAL;
}
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, i2s_priv->id, 0);
break;
case SND_SOC_DAPM_POST_PMD:
mt8192_afe_gpio_request(afe->dev, false, i2s_priv->id, 0);
break;
default:
break;
}
return 0;
}
static int mtk_apll_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (strcmp(w->name, APLL1_W_NAME) == 0)
mt8192_apll1_enable(afe);
else
mt8192_apll2_enable(afe);
break;
case SND_SOC_DAPM_POST_PMD:
if (strcmp(w->name, APLL1_W_NAME) == 0)
mt8192_apll1_disable(afe);
else
mt8192_apll2_disable(afe);
break;
default:
break;
}
return 0;
}
static int i2s_out_tinyconn_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
unsigned int reg;
unsigned int reg_shift;
unsigned int reg_mask_shift;
dev_dbg(afe->dev, "%s(), event 0x%x\n", __func__, event);
if (strstr(w->name, "I2S1")) {
reg = AFE_I2S_CON1;
reg_shift = I2S2_32BIT_EN_SFT;
reg_mask_shift = I2S2_32BIT_EN_MASK_SFT;
} else if (strstr(w->name, "I2S3")) {
reg = AFE_I2S_CON3;
reg_shift = I2S4_32BIT_EN_SFT;
reg_mask_shift = I2S4_32BIT_EN_MASK_SFT;
} else if (strstr(w->name, "I2S5")) {
reg = AFE_I2S_CON4;
reg_shift = I2S5_32BIT_EN_SFT;
reg_mask_shift = I2S5_32BIT_EN_MASK_SFT;
} else if (strstr(w->name, "I2S7")) {
reg = AFE_I2S_CON7;
reg_shift = I2S7_32BIT_EN_SFT;
reg_mask_shift = I2S7_32BIT_EN_MASK_SFT;
} else if (strstr(w->name, "I2S9")) {
reg = AFE_I2S_CON9;
reg_shift = I2S9_32BIT_EN_SFT;
reg_mask_shift = I2S9_32BIT_EN_MASK_SFT;
} else {
reg = AFE_I2S_CON1;
reg_shift = I2S2_32BIT_EN_SFT;
reg_mask_shift = I2S2_32BIT_EN_MASK_SFT;
dev_warn(afe->dev, "%s(), error widget name %s, use i2s1\n",
__func__, w->name);
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
regmap_update_bits(afe->regmap, reg, reg_mask_shift,
0x1 << reg_shift);
break;
case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(afe->regmap, reg, reg_mask_shift,
0x0 << reg_shift);
break;
default:
break;
}
return 0;
}
static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
i2s_priv = get_i2s_priv_by_name(afe, w->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return -EINVAL;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
break;
case SND_SOC_DAPM_POST_PMD:
i2s_priv->mclk_rate = 0;
mt8192_mck_disable(afe, i2s_priv->mclk_id);
break;
default:
break;
}
return 0;
}
static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
SND_SOC_DAPM_INPUT("CONNSYS"),
SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0,
mtk_i2s1_ch1_mix,
ARRAY_SIZE(mtk_i2s1_ch1_mix)),
SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0,
mtk_i2s1_ch2_mix,
ARRAY_SIZE(mtk_i2s1_ch2_mix)),
SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0,
mtk_i2s3_ch1_mix,
ARRAY_SIZE(mtk_i2s3_ch1_mix)),
SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0,
mtk_i2s3_ch2_mix,
ARRAY_SIZE(mtk_i2s3_ch2_mix)),
SND_SOC_DAPM_MIXER("I2S5_CH1", SND_SOC_NOPM, 0, 0,
mtk_i2s5_ch1_mix,
ARRAY_SIZE(mtk_i2s5_ch1_mix)),
SND_SOC_DAPM_MIXER("I2S5_CH2", SND_SOC_NOPM, 0, 0,
mtk_i2s5_ch2_mix,
ARRAY_SIZE(mtk_i2s5_ch2_mix)),
SND_SOC_DAPM_MIXER("I2S7_CH1", SND_SOC_NOPM, 0, 0,
mtk_i2s7_ch1_mix,
ARRAY_SIZE(mtk_i2s7_ch1_mix)),
SND_SOC_DAPM_MIXER("I2S7_CH2", SND_SOC_NOPM, 0, 0,
mtk_i2s7_ch2_mix,
ARRAY_SIZE(mtk_i2s7_ch2_mix)),
SND_SOC_DAPM_MIXER("I2S9_CH1", SND_SOC_NOPM, 0, 0,
mtk_i2s9_ch1_mix,
ARRAY_SIZE(mtk_i2s9_ch1_mix)),
SND_SOC_DAPM_MIXER("I2S9_CH2", SND_SOC_NOPM, 0, 0,
mtk_i2s9_ch2_mix,
ARRAY_SIZE(mtk_i2s9_ch2_mix)),
SND_SOC_DAPM_MUX_E("I2S1_TINYCONN_CH1_MUX", SND_SOC_NOPM, 0, 0,
&i2s1_tinyconn_ch1_mux_control,
i2s_out_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MUX_E("I2S1_TINYCONN_CH2_MUX", SND_SOC_NOPM, 0, 0,
&i2s1_tinyconn_ch2_mux_control,
i2s_out_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MUX_E("I2S3_TINYCONN_CH1_MUX", SND_SOC_NOPM, 0, 0,
&i2s3_tinyconn_ch1_mux_control,
i2s_out_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MUX_E("I2S3_TINYCONN_CH2_MUX", SND_SOC_NOPM, 0, 0,
&i2s3_tinyconn_ch2_mux_control,
i2s_out_tinyconn_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
/* i2s en*/
SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON, I2S_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON1, I2S_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON2, I2S_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON3, I2S_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S5_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON4, I2S5_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S6_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON6, I2S6_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S7_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON7, I2S7_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S8_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON8, I2S8_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("I2S9_EN", SUPPLY_SEQ_I2S_EN,
AFE_I2S_CON9, I2S9_EN_SFT, 0,
mtk_i2s_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* i2s hd en */
SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S5_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON4, I2S5_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S6_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON6, I2S6_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S7_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON7, I2S7_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S8_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON8, I2S8_HD_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S(I2S9_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
AFE_I2S_CON9, I2S9_HD_EN_SFT, 0, NULL, 0),
/* i2s mclk en */
SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S5_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S6_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S7_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S8_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(I2S9_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
SND_SOC_NOPM, 0, 0,
mtk_mclk_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* apll */
SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,
SND_SOC_NOPM, 0, 0,
mtk_apll_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,
SND_SOC_NOPM, 0, 0,
mtk_apll_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* allow i2s on without codec on */
SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"),
SND_SOC_DAPM_MUX("I2S1_Out_Mux",
SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control),
SND_SOC_DAPM_MUX("I2S3_Out_Mux",
SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control),
SND_SOC_DAPM_MUX("I2S5_Out_Mux",
SND_SOC_NOPM, 0, 0, &i2s5_out_mux_control),
SND_SOC_DAPM_MUX("I2S7_Out_Mux",
SND_SOC_NOPM, 0, 0, &i2s7_out_mux_control),
SND_SOC_DAPM_MUX("I2S9_Out_Mux",
SND_SOC_NOPM, 0, 0, &i2s9_out_mux_control),
SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"),
SND_SOC_DAPM_MUX("I2S0_In_Mux",
SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control),
SND_SOC_DAPM_MUX("I2S8_In_Mux",
SND_SOC_NOPM, 0, 0, &i2s8_in_mux_control),
/* i2s in lpbk */
SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux",
SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control),
SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux",
SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control),
};
static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return 0;
}
if (i2s_priv->share_i2s_id < 0)
return 0;
return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);
}
static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return 0;
}
if (get_i2s_id_by_name(afe, sink->name) ==
get_i2s_id_by_name(afe, source->name))
return i2s_priv->low_jitter_en;
/* check if share i2s need hd en */
if (i2s_priv->share_i2s_id < 0)
return 0;
if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
return i2s_priv->low_jitter_en;
return 0;
}
static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
int cur_apll;
int i2s_need_apll;
i2s_priv = get_i2s_priv_by_name(afe, w->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return 0;
}
/* which apll */
cur_apll = mt8192_get_apll_by_name(afe, source->name);
/* choose APLL from i2s rate */
i2s_need_apll = mt8192_get_apll_by_rate(afe, i2s_priv->rate);
if (i2s_need_apll == cur_apll)
return 1;
return 0;
}
static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return 0;
}
if (get_i2s_id_by_name(afe, sink->name) ==
get_i2s_id_by_name(afe, source->name))
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
/* check if share i2s need mclk */
if (i2s_priv->share_i2s_id < 0)
return 0;
if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
return 0;
}
static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
int cur_apll;
i2s_priv = get_i2s_priv_by_name(afe, w->name);
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return 0;
}
/* which apll */
cur_apll = mt8192_get_apll_by_name(afe, source->name);
if (i2s_priv->mclk_apll == cur_apll)
return 1;
return 0;
}
static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
{"Connsys I2S", NULL, "CONNSYS"},
/* i2s0 */
{"I2S0", NULL, "I2S0_EN"},
{"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S0", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S0", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s1 */
{"I2S1_CH1", "DL1_CH1", "DL1"},
{"I2S1_CH2", "DL1_CH2", "DL1"},
{"I2S1_TINYCONN_CH1_MUX", "DL1_CH1", "DL1"},
{"I2S1_TINYCONN_CH2_MUX", "DL1_CH2", "DL1"},
{"I2S1_CH1", "DL2_CH1", "DL2"},
{"I2S1_CH2", "DL2_CH2", "DL2"},
{"I2S1_TINYCONN_CH1_MUX", "DL2_CH1", "DL2"},
{"I2S1_TINYCONN_CH2_MUX", "DL2_CH2", "DL2"},
{"I2S1_CH1", "DL3_CH1", "DL3"},
{"I2S1_CH2", "DL3_CH2", "DL3"},
{"I2S1_TINYCONN_CH1_MUX", "DL3_CH1", "DL3"},
{"I2S1_TINYCONN_CH2_MUX", "DL3_CH2", "DL3"},
{"I2S1_CH1", "DL12_CH1", "DL12"},
{"I2S1_CH2", "DL12_CH2", "DL12"},
{"I2S1_TINYCONN_CH1_MUX", "DL12_CH1", "DL12"},
{"I2S1_TINYCONN_CH2_MUX", "DL12_CH2", "DL12"},
{"I2S1_CH1", "DL4_CH1", "DL4"},
{"I2S1_CH2", "DL4_CH2", "DL4"},
{"I2S1_CH1", "DL5_CH1", "DL5"},
{"I2S1_CH2", "DL5_CH2", "DL5"},
{"I2S1_CH1", "DL6_CH1", "DL6"},
{"I2S1_CH2", "DL6_CH2", "DL6"},
{"I2S1_CH1", "DL8_CH1", "DL8"},
{"I2S1_CH2", "DL8_CH2", "DL8"},
{"I2S1", NULL, "I2S1_CH1"},
{"I2S1", NULL, "I2S1_CH2"},
{"I2S1", NULL, "I2S3_TINYCONN_CH1_MUX"},
{"I2S1", NULL, "I2S3_TINYCONN_CH2_MUX"},
{"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S1_EN"},
{"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S1", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S1", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s2 */
{"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S2_EN"},
{"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S2", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S2", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s3 */
{"I2S3_CH1", "DL1_CH1", "DL1"},
{"I2S3_CH2", "DL1_CH2", "DL1"},
{"I2S3_TINYCONN_CH1_MUX", "DL1_CH1", "DL1"},
{"I2S3_TINYCONN_CH2_MUX", "DL1_CH2", "DL1"},
{"I2S3_CH1", "DL2_CH1", "DL2"},
{"I2S3_CH2", "DL2_CH2", "DL2"},
{"I2S3_TINYCONN_CH1_MUX", "DL2_CH1", "DL2"},
{"I2S3_TINYCONN_CH2_MUX", "DL2_CH2", "DL2"},
{"I2S3_CH1", "DL3_CH1", "DL3"},
{"I2S3_CH2", "DL3_CH2", "DL3"},
{"I2S3_TINYCONN_CH1_MUX", "DL3_CH1", "DL3"},
{"I2S3_TINYCONN_CH2_MUX", "DL3_CH2", "DL3"},
{"I2S3_CH1", "DL12_CH1", "DL12"},
{"I2S3_CH2", "DL12_CH2", "DL12"},
{"I2S3_TINYCONN_CH1_MUX", "DL12_CH1", "DL12"},
{"I2S3_TINYCONN_CH2_MUX", "DL12_CH2", "DL12"},
{"I2S3_CH1", "DL4_CH1", "DL4"},
{"I2S3_CH2", "DL4_CH2", "DL4"},
{"I2S3_CH1", "DL5_CH1", "DL5"},
{"I2S3_CH2", "DL5_CH2", "DL5"},
{"I2S3_CH1", "DL6_CH1", "DL6"},
{"I2S3_CH2", "DL6_CH2", "DL6"},
{"I2S3_CH1", "DL8_CH1", "DL8"},
{"I2S3_CH2", "DL8_CH2", "DL8"},
{"I2S3", NULL, "I2S3_CH1"},
{"I2S3", NULL, "I2S3_CH2"},
{"I2S3", NULL, "I2S3_TINYCONN_CH1_MUX"},
{"I2S3", NULL, "I2S3_TINYCONN_CH2_MUX"},
{"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S3_EN"},
{"I2S3", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S3", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S3", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s5 */
{"I2S5_CH1", "DL1_CH1", "DL1"},
{"I2S5_CH2", "DL1_CH2", "DL1"},
{"I2S5_CH1", "DL2_CH1", "DL2"},
{"I2S5_CH2", "DL2_CH2", "DL2"},
{"I2S5_CH1", "DL3_CH1", "DL3"},
{"I2S5_CH2", "DL3_CH2", "DL3"},
{"I2S5_CH1", "DL12_CH1", "DL12"},
{"I2S5_CH2", "DL12_CH2", "DL12"},
{"I2S5_CH1", "DL4_CH1", "DL4"},
{"I2S5_CH2", "DL4_CH2", "DL4"},
{"I2S5_CH1", "DL5_CH1", "DL5"},
{"I2S5_CH2", "DL5_CH2", "DL5"},
{"I2S5_CH1", "DL6_CH1", "DL6"},
{"I2S5_CH2", "DL6_CH2", "DL6"},
{"I2S5_CH1", "DL8_CH1", "DL8"},
{"I2S5_CH2", "DL8_CH2", "DL8"},
{"I2S5", NULL, "I2S5_CH1"},
{"I2S5", NULL, "I2S5_CH2"},
{"I2S5", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S5_EN"},
{"I2S5", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S5", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S5", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S5_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S5_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S5", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S5", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S5_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S5_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s6 */
{"I2S6", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S6_EN"},
{"I2S6", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S6", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S6", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S6_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S6_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S6", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S6", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S6_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S6_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s7 */
{"I2S7", NULL, "I2S7_CH1"},
{"I2S7", NULL, "I2S7_CH2"},
{"I2S7", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S7_EN"},
{"I2S7", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S7", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S7", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S7_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S7_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S7", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S7", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S7_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S7_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s8 */
{"I2S8", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, "I2S8_EN"},
{"I2S8", NULL, "I2S9_EN", mtk_afe_i2s_share_connect},
{"I2S8", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S8", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S8_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S8_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S8", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S8", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S8_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S8_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* i2s9 */
{"I2S9_CH1", "DL1_CH1", "DL1"},
{"I2S9_CH2", "DL1_CH2", "DL1"},
{"I2S9_CH1", "DL2_CH1", "DL2"},
{"I2S9_CH2", "DL2_CH2", "DL2"},
{"I2S9_CH1", "DL3_CH1", "DL3"},
{"I2S9_CH2", "DL3_CH2", "DL3"},
{"I2S9_CH1", "DL12_CH1", "DL12"},
{"I2S9_CH2", "DL12_CH2", "DL12"},
{"I2S9_CH1", "DL4_CH1", "DL4"},
{"I2S9_CH2", "DL4_CH2", "DL4"},
{"I2S9_CH1", "DL5_CH1", "DL5"},
{"I2S9_CH2", "DL5_CH2", "DL5"},
{"I2S9_CH1", "DL6_CH1", "DL6"},
{"I2S9_CH2", "DL6_CH2", "DL6"},
{"I2S9_CH1", "DL8_CH1", "DL8"},
{"I2S9_CH2", "DL8_CH2", "DL8"},
{"I2S9_CH1", "DL9_CH1", "DL9"},
{"I2S9_CH2", "DL9_CH2", "DL9"},
{"I2S9", NULL, "I2S9_CH1"},
{"I2S9", NULL, "I2S9_CH2"},
{"I2S9", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S6_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S7_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S8_EN", mtk_afe_i2s_share_connect},
{"I2S9", NULL, "I2S9_EN"},
{"I2S9", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S6_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S7_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S8_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{"I2S9", NULL, I2S9_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
{I2S9_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
{I2S9_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
{"I2S9", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S7_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S8_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{"I2S9", NULL, I2S9_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
{I2S9_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
{I2S9_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
/* allow i2s on without codec on */
{"I2S0", NULL, "I2S0_In_Mux"},
{"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},
{"I2S8", NULL, "I2S8_In_Mux"},
{"I2S8_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},
{"I2S1_Out_Mux", "Dummy_Widget", "I2S1"},
{"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"},
{"I2S3_Out_Mux", "Dummy_Widget", "I2S3"},
{"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"},
{"I2S5_Out_Mux", "Dummy_Widget", "I2S5"},
{"I2S_DUMMY_OUT", NULL, "I2S5_Out_Mux"},
{"I2S7_Out_Mux", "Dummy_Widget", "I2S7"},
{"I2S_DUMMY_OUT", NULL, "I2S7_Out_Mux"},
{"I2S9_Out_Mux", "Dummy_Widget", "I2S9"},
{"I2S_DUMMY_OUT", NULL, "I2S9_Out_Mux"},
/* i2s in lpbk */
{"I2S0_Lpbk_Mux", "Lpbk", "I2S3"},
{"I2S2_Lpbk_Mux", "Lpbk", "I2S1"},
{"I2S0", NULL, "I2S0_Lpbk_Mux"},
{"I2S2", NULL, "I2S2_Lpbk_Mux"},
};
/* dai ops */
static int mtk_dai_connsys_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
unsigned int rate = params_rate(params);
unsigned int rate_reg = mt8192_rate_transform(afe->dev,
rate, dai->id);
unsigned int i2s_con = 0;
dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
__func__, dai->id, substream->stream, rate);
/* non-inverse, i2s mode, proxy mode, 16bits, from connsys */
i2s_con |= 0 << INV_PAD_CTRL_SFT;
i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
i2s_con |= 1 << I2S_SRC_SFT;
i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT;
i2s_con |= 0 << I2SIN_PAD_SEL_SFT;
regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);
/* use asrc */
regmap_update_bits(afe->regmap,
AFE_CONNSYS_I2S_CON,
I2S_BYPSRC_MASK_SFT,
0x0 << I2S_BYPSRC_SFT);
/* proxy mode, set i2s for asrc */
regmap_update_bits(afe->regmap,
AFE_CONNSYS_I2S_CON,
I2S_MODE_MASK_SFT,
rate_reg << I2S_MODE_SFT);
switch (rate) {
case 32000:
regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);
break;
case 44100:
regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001B9000);
break;
default:
regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x001E0000);
break;
}
/* Calibration setting */
regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x00140000);
regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x00036000);
regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x0002FC00);
regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x00007EF4);
regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0x00FF5986);
/* 0:Stereo 1:Mono */
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON2,
CHSET_IS_MONO_MASK_SFT,
0x0 << CHSET_IS_MONO_SFT);
return 0;
}
static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
dev_dbg(afe->dev, "%s(), cmd %d, stream %d\n",
__func__, cmd, substream->stream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
/* i2s enable */
regmap_update_bits(afe->regmap,
AFE_CONNSYS_I2S_CON,
I2S_EN_MASK_SFT,
0x1 << I2S_EN_SFT);
/* calibrator enable */
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON5,
CALI_EN_MASK_SFT,
0x1 << CALI_EN_SFT);
/* asrc enable */
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON0,
CON0_CHSET_STR_CLR_MASK_SFT,
0x1 << CON0_CHSET_STR_CLR_SFT);
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON0,
CON0_ASM_ON_MASK_SFT,
0x1 << CON0_ASM_ON_SFT);
afe_priv->dai_on[dai->id] = true;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON0,
CON0_ASM_ON_MASK_SFT,
0 << CON0_ASM_ON_SFT);
regmap_update_bits(afe->regmap,
AFE_ASRC_2CH_CON5,
CALI_EN_MASK_SFT,
0 << CALI_EN_SFT);
/* i2s disable */
regmap_update_bits(afe->regmap,
AFE_CONNSYS_I2S_CON,
I2S_EN_MASK_SFT,
0x0 << I2S_EN_SFT);
/* bypass asrc */
regmap_update_bits(afe->regmap,
AFE_CONNSYS_I2S_CON,
I2S_BYPSRC_MASK_SFT,
0x1 << I2S_BYPSRC_SFT);
afe_priv->dai_on[dai->id] = false;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = {
.hw_params = mtk_dai_connsys_i2s_hw_params,
.trigger = mtk_dai_connsys_i2s_trigger,
};
/* i2s */
static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
struct snd_pcm_hw_params *params,
int i2s_id)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];
unsigned int rate = params_rate(params);
unsigned int rate_reg = mt8192_rate_transform(afe->dev,
rate, i2s_id);
snd_pcm_format_t format = params_format(params);
unsigned int i2s_con = 0;
int ret = 0;
dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n",
__func__, i2s_id, rate, format);
if (i2s_priv)
i2s_priv->rate = rate;
else
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
switch (i2s_id) {
case MT8192_DAI_I2S_0:
i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
i2s_con |= rate_reg << I2S_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_1:
i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;
i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON1,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_2:
i2s_con = 8 << I2S3_UPDATE_WORD_SFT;
i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON2,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_3:
i2s_con = rate_reg << I2S4_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON3,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_5:
i2s_con = rate_reg << I2S5_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S5_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S5_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON4,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_6:
i2s_con = rate_reg << I2S6_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S6_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S6_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON6,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_7:
i2s_con = rate_reg << I2S7_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S7_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S7_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON7,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_8:
i2s_con = rate_reg << I2S8_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S8_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S8_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON8,
0xffffeffe, i2s_con);
break;
case MT8192_DAI_I2S_9:
i2s_con = rate_reg << I2S9_OUT_MODE_SFT;
i2s_con |= I2S_FMT_I2S << I2S9_FMT_SFT;
i2s_con |= get_i2s_wlen(format) << I2S9_WLEN_SFT;
regmap_update_bits(afe->regmap, AFE_I2S_CON9,
0xffffeffe, i2s_con);
break;
default:
dev_warn(afe->dev, "%s(), id %d not support\n",
__func__, i2s_id);
return -EINVAL;
}
/* set share i2s */
if (i2s_priv && i2s_priv->share_i2s_id >= 0)
ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);
return ret;
}
static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
return mtk_dai_i2s_config(afe, params, dai->id);
}
static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];
int apll;
int apll_rate;
if (!i2s_priv) {
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
return -EINVAL;
}
if (dir != SND_SOC_CLOCK_OUT) {
dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
return -EINVAL;
}
dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);
apll = mt8192_get_apll_by_rate(afe, freq);
apll_rate = mt8192_get_apll_rate(afe, apll);
if (freq > apll_rate) {
dev_warn(afe->dev, "%s(), freq > apll rate", __func__);
return -EINVAL;
}
if (apll_rate % freq != 0) {
dev_warn(afe->dev, "%s(), APLL can't gen freq Hz", __func__);
return -EINVAL;
}
i2s_priv->mclk_rate = freq;
i2s_priv->mclk_apll = apll;
if (i2s_priv->share_i2s_id > 0) {
struct mtk_afe_i2s_priv *share_i2s_priv;
share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
if (!share_i2s_priv) {
dev_warn(afe->dev, "%s(), share_i2s_priv = NULL",
__func__);
return -EINVAL;
}
share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {
.hw_params = mtk_dai_i2s_hw_params,
.set_sysclk = mtk_dai_i2s_set_sysclk,
};
/* dai driver */
#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\
SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000)
#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
{
.name = "CONNSYS_I2S",
.id = MT8192_DAI_CONNSYS_I2S,
.capture = {
.stream_name = "Connsys I2S",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_CONNSYS_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_connsys_i2s_ops,
},
{
.name = "I2S0",
.id = MT8192_DAI_I2S_0,
.capture = {
.stream_name = "I2S0",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S1",
.id = MT8192_DAI_I2S_1,
.playback = {
.stream_name = "I2S1",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S2",
.id = MT8192_DAI_I2S_2,
.capture = {
.stream_name = "I2S2",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S3",
.id = MT8192_DAI_I2S_3,
.playback = {
.stream_name = "I2S3",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S5",
.id = MT8192_DAI_I2S_5,
.playback = {
.stream_name = "I2S5",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S6",
.id = MT8192_DAI_I2S_6,
.capture = {
.stream_name = "I2S6",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S7",
.id = MT8192_DAI_I2S_7,
.playback = {
.stream_name = "I2S7",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S8",
.id = MT8192_DAI_I2S_8,
.capture = {
.stream_name = "I2S8",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
},
{
.name = "I2S9",
.id = MT8192_DAI_I2S_9,
.playback = {
.stream_name = "I2S9",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_I2S_RATES,
.formats = MTK_I2S_FORMATS,
},
.ops = &mtk_dai_i2s_ops,
}
};
/* this enum is merely for mtk_afe_i2s_priv declare */
enum {
DAI_I2S0 = 0,
DAI_I2S1,
DAI_I2S2,
DAI_I2S3,
DAI_I2S5,
DAI_I2S6,
DAI_I2S7,
DAI_I2S8,
DAI_I2S9,
DAI_I2S_NUM,
};
static const struct mtk_afe_i2s_priv mt8192_i2s_priv[DAI_I2S_NUM] = {
[DAI_I2S0] = {
.id = MT8192_DAI_I2S_0,
.mclk_id = MT8192_I2S0_MCK,
.share_property_name = "i2s0-share",
.share_i2s_id = -1,
},
[DAI_I2S1] = {
.id = MT8192_DAI_I2S_1,
.mclk_id = MT8192_I2S1_MCK,
.share_property_name = "i2s1-share",
.share_i2s_id = -1,
},
[DAI_I2S2] = {
.id = MT8192_DAI_I2S_2,
.mclk_id = MT8192_I2S2_MCK,
.share_property_name = "i2s2-share",
.share_i2s_id = -1,
},
[DAI_I2S3] = {
.id = MT8192_DAI_I2S_3,
.mclk_id = MT8192_I2S3_MCK,
.share_property_name = "i2s3-share",
.share_i2s_id = -1,
},
[DAI_I2S5] = {
.id = MT8192_DAI_I2S_5,
.mclk_id = MT8192_I2S5_MCK,
.share_property_name = "i2s5-share",
.share_i2s_id = -1,
},
[DAI_I2S6] = {
.id = MT8192_DAI_I2S_6,
.mclk_id = MT8192_I2S6_MCK,
.share_property_name = "i2s6-share",
.share_i2s_id = -1,
},
[DAI_I2S7] = {
.id = MT8192_DAI_I2S_7,
.mclk_id = MT8192_I2S7_MCK,
.share_property_name = "i2s7-share",
.share_i2s_id = -1,
},
[DAI_I2S8] = {
.id = MT8192_DAI_I2S_8,
.mclk_id = MT8192_I2S8_MCK,
.share_property_name = "i2s8-share",
.share_i2s_id = -1,
},
[DAI_I2S9] = {
.id = MT8192_DAI_I2S_9,
.mclk_id = MT8192_I2S9_MCK,
.share_property_name = "i2s9-share",
.share_i2s_id = -1,
},
};
int mt8192_dai_i2s_get_share(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
const struct device_node *of_node = afe->dev->of_node;
const char *of_str;
const char *property_name;
struct mtk_afe_i2s_priv *i2s_priv;
int i;
for (i = 0; i < DAI_I2S_NUM; i++) {
i2s_priv = afe_priv->dai_priv[mt8192_i2s_priv[i].id];
property_name = mt8192_i2s_priv[i].share_property_name;
if (of_property_read_string(of_node, property_name, &of_str))
continue;
i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str);
}
return 0;
}
int mt8192_dai_i2s_set_priv(struct mtk_base_afe *afe)
{
int i;
int ret;
for (i = 0; i < DAI_I2S_NUM; i++) {
ret = mt8192_dai_set_priv(afe, mt8192_i2s_priv[i].id,
sizeof(struct mtk_afe_i2s_priv),
&mt8192_i2s_priv[i]);
if (ret)
return ret;
}
return 0;
}
int mt8192_dai_i2s_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
int ret;
dev_dbg(afe->dev, "%s()\n", __func__);
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_i2s_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
dai->controls = mtk_dai_i2s_controls;
dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);
dai->dapm_widgets = mtk_dai_i2s_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
dai->dapm_routes = mtk_dai_i2s_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
/* set all dai i2s private data */
ret = mt8192_dai_i2s_set_priv(afe);
if (ret)
return ret;
/* parse share i2s */
ret = mt8192_dai_i2s_get_share(afe);
if (ret)
return ret;
return 0;
}
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio DAI I2S Control
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
//
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8192-afe-common.h"
#include "mt8192-interconnection.h"
enum AUD_TX_LCH_RPT {
AUD_TX_LCH_RPT_NO_REPEAT = 0,
AUD_TX_LCH_RPT_REPEAT = 1
};
enum AUD_VBT_16K_MODE {
AUD_VBT_16K_MODE_DISABLE = 0,
AUD_VBT_16K_MODE_ENABLE = 1
};
enum AUD_EXT_MODEM {
AUD_EXT_MODEM_SELECT_INTERNAL = 0,
AUD_EXT_MODEM_SELECT_EXTERNAL = 1
};
enum AUD_PCM_SYNC_TYPE {
/* bck sync length = 1 */
AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
/* bck sync length = PCM_INTF_CON1[9:13] */
AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
};
enum AUD_BT_MODE {
AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
};
enum AUD_PCM_AFIFO_SRC {
/* slave mode & external modem uses different crystal */
AUD_PCM_AFIFO_ASRC = 0,
/* slave mode & external modem uses the same crystal */
AUD_PCM_AFIFO_AFIFO = 1
};
enum AUD_PCM_CLOCK_SOURCE {
AUD_PCM_CLOCK_MASTER_MODE = 0,
AUD_PCM_CLOCK_SLAVE_MODE = 1
};
enum AUD_PCM_WLEN {
AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
};
enum AUD_PCM_MODE {
AUD_PCM_MODE_PCM_MODE_8K = 0,
AUD_PCM_MODE_PCM_MODE_16K = 1,
AUD_PCM_MODE_PCM_MODE_32K = 2,
AUD_PCM_MODE_PCM_MODE_48K = 3,
};
enum AUD_PCM_FMT {
AUD_PCM_FMT_I2S = 0,
AUD_PCM_FMT_EIAJ = 1,
AUD_PCM_FMT_PCM_MODE_A = 2,
AUD_PCM_FMT_PCM_MODE_B = 3
};
enum AUD_BCLK_OUT_INV {
AUD_BCLK_OUT_INV_NO_INVERSE = 0,
AUD_BCLK_OUT_INV_INVERSE = 1
};
enum AUD_PCM_EN {
AUD_PCM_EN_DISABLE = 0,
AUD_PCM_EN_ENABLE = 1
};
/* dai component */
static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN7,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN7,
I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN7_1,
I_DL4_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN8,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN8,
I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN8_1,
I_DL4_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_1_playback_ch4_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN27,
I_I2S0_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN27,
I_I2S0_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN27,
I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN27,
I_I2S2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN27,
I_I2S2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN27_1,
I_DL4_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_2_playback_ch1_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN17,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN17,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN17,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN17,
I_DL2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN17_1,
I_DL4_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_2_playback_ch2_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN18,
I_ADDA_UL_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN18,
I_ADDA_UL_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN18,
I_ADDA_UL_CH3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN18,
I_DL2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN18_1,
I_DL4_CH2, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_2_playback_ch3_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN23,
I_ADDA_UL_CH3, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_2_playback_ch4_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN24,
I_I2S0_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN24,
I_I2S0_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN24,
I_DL1_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN24,
I_I2S2_CH1, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN24,
I_I2S2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN24_1,
I_DL4_CH1, 1, 0),
};
static const struct snd_kcontrol_new mtk_pcm_2_playback_ch5_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN25,
I_I2S0_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN25,
I_DL1_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN25,
I_I2S2_CH2, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN25_1,
I_DL4_CH2, 1, 0),
};
static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
return 0;
}
static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0,
mtk_pcm_1_playback_ch1_mix,
ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)),
SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0,
mtk_pcm_1_playback_ch2_mix,
ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)),
SND_SOC_DAPM_MIXER("PCM_1_PB_CH4", SND_SOC_NOPM, 0, 0,
mtk_pcm_1_playback_ch4_mix,
ARRAY_SIZE(mtk_pcm_1_playback_ch4_mix)),
SND_SOC_DAPM_MIXER("PCM_2_PB_CH1", SND_SOC_NOPM, 0, 0,
mtk_pcm_2_playback_ch1_mix,
ARRAY_SIZE(mtk_pcm_2_playback_ch1_mix)),
SND_SOC_DAPM_MIXER("PCM_2_PB_CH2", SND_SOC_NOPM, 0, 0,
mtk_pcm_2_playback_ch2_mix,
ARRAY_SIZE(mtk_pcm_2_playback_ch2_mix)),
SND_SOC_DAPM_MIXER("PCM_2_PB_CH3", SND_SOC_NOPM, 0, 0,
mtk_pcm_2_playback_ch3_mix,
ARRAY_SIZE(mtk_pcm_2_playback_ch3_mix)),
SND_SOC_DAPM_MIXER("PCM_2_PB_CH4", SND_SOC_NOPM, 0, 0,
mtk_pcm_2_playback_ch4_mix,
ARRAY_SIZE(mtk_pcm_2_playback_ch4_mix)),
SND_SOC_DAPM_MIXER("PCM_2_PB_CH5", SND_SOC_NOPM, 0, 0,
mtk_pcm_2_playback_ch5_mix,
ARRAY_SIZE(mtk_pcm_2_playback_ch5_mix)),
SND_SOC_DAPM_SUPPLY("PCM_1_EN",
PCM_INTF_CON1, PCM_EN_SFT, 0,
mtk_pcm_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("PCM_2_EN",
PCM2_INTF_CON, PCM2_EN_SFT, 0,
mtk_pcm_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_INPUT("MD1_TO_AFE"),
SND_SOC_DAPM_INPUT("MD2_TO_AFE"),
SND_SOC_DAPM_OUTPUT("AFE_TO_MD1"),
SND_SOC_DAPM_OUTPUT("AFE_TO_MD2"),
};
static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
{"PCM 1 Playback", NULL, "PCM_1_PB_CH1"},
{"PCM 1 Playback", NULL, "PCM_1_PB_CH2"},
{"PCM 1 Playback", NULL, "PCM_1_PB_CH4"},
{"PCM 2 Playback", NULL, "PCM_2_PB_CH1"},
{"PCM 2 Playback", NULL, "PCM_2_PB_CH2"},
{"PCM 2 Playback", NULL, "PCM_2_PB_CH3"},
{"PCM 2 Playback", NULL, "PCM_2_PB_CH4"},
{"PCM 2 Playback", NULL, "PCM_2_PB_CH5"},
{"PCM 1 Playback", NULL, "PCM_1_EN"},
{"PCM 2 Playback", NULL, "PCM_2_EN"},
{"PCM 1 Capture", NULL, "PCM_1_EN"},
{"PCM 2 Capture", NULL, "PCM_2_EN"},
{"AFE_TO_MD1", NULL, "PCM 2 Playback"},
{"AFE_TO_MD2", NULL, "PCM 1 Playback"},
{"PCM 2 Capture", NULL, "MD1_TO_AFE"},
{"PCM 1 Capture", NULL, "MD2_TO_AFE"},
{"PCM_1_PB_CH1", "DL2_CH1", "DL2"},
{"PCM_1_PB_CH2", "DL2_CH2", "DL2"},
{"PCM_1_PB_CH4", "DL1_CH1", "DL1"},
{"PCM_2_PB_CH1", "DL2_CH1", "DL2"},
{"PCM_2_PB_CH2", "DL2_CH2", "DL2"},
{"PCM_2_PB_CH4", "DL1_CH1", "DL1"},
{"PCM_1_PB_CH1", "DL4_CH1", "DL4"},
{"PCM_1_PB_CH2", "DL4_CH2", "DL4"},
{"PCM_1_PB_CH4", "DL4_CH1", "DL4"},
{"PCM_2_PB_CH1", "DL4_CH1", "DL4"},
{"PCM_2_PB_CH2", "DL4_CH2", "DL4"},
{"PCM_2_PB_CH4", "DL4_CH1", "DL4"},
{"PCM_1_PB_CH4", "I2S0_CH1", "I2S0"},
{"PCM_2_PB_CH4", "I2S2_CH1", "I2S2"},
{"PCM_2_PB_CH5", "DL1_CH2", "DL1"},
{"PCM_2_PB_CH5", "DL4_CH2", "DL4"},
{"PCM_2_PB_CH5", "I2S0_CH2", "I2S0"},
{"PCM_2_PB_CH5", "I2S2_CH2", "I2S2"},
};
/* dai ops */
static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
unsigned int rate = params_rate(params);
unsigned int rate_reg = mt8192_rate_transform(afe->dev, rate, dai->id);
unsigned int pcm_con = 0;
dev_info(afe->dev, "%s(), id %d, stream %d, rate %d, rate_reg %d, widget active p %d, c %d\n",
__func__,
dai->id,
substream->stream,
rate,
rate_reg,
dai->playback_widget->active,
dai->capture_widget->active);
if (dai->playback_widget->active || dai->capture_widget->active)
return 0;
switch (dai->id) {
case MT8192_DAI_PCM_1:
pcm_con |= AUD_BCLK_OUT_INV_NO_INVERSE << PCM_BCLK_OUT_INV_SFT;
pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
pcm_con |= AUD_EXT_MODEM_SELECT_INTERNAL << PCM_EXT_MODEM_SFT;
pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
pcm_con |= AUD_PCM_CLOCK_SLAVE_MODE << PCM_SLAVE_SFT;
pcm_con |= rate_reg << PCM_MODE_SFT;
pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM_FMT_SFT;
regmap_update_bits(afe->regmap, PCM_INTF_CON1,
0xfffffffe, pcm_con);
break;
case MT8192_DAI_PCM_2:
pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM2_TX_LCH_RPT_SFT;
pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM2_VBT_16K_MODE_SFT;
pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM2_BT_MODE_SFT;
pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM2_AFIFO_SFT;
pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM2_WLEN_SFT;
pcm_con |= rate_reg << PCM2_MODE_SFT;
pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM2_FMT_SFT;
regmap_update_bits(afe->regmap, PCM2_INTF_CON,
0xfffffffe, pcm_con);
break;
default:
dev_warn(afe->dev, "%s(), id %d not support\n",
__func__, dai->id);
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
.hw_params = mtk_dai_pcm_hw_params,
};
/* dai driver */
#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 |\
SNDRV_PCM_RATE_48000)
#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
{
.name = "PCM 1",
.id = MT8192_DAI_PCM_1,
.playback = {
.stream_name = "PCM 1 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.capture = {
.stream_name = "PCM 1 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
},
{
.name = "PCM 2",
.id = MT8192_DAI_PCM_2,
.playback = {
.stream_name = "PCM 2 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.capture = {
.stream_name = "PCM 2 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MTK_PCM_RATES,
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
},
};
int mt8192_dai_pcm_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
dev_info(afe->dev, "%s()\n", __func__);
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 0;
}
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio DAI TDM Control
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Shane Chien <shane.chien@mediatek.com>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8192-afe-clk.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-gpio.h"
#include "mt8192-interconnection.h"
struct mtk_afe_tdm_priv {
int id;
int bck_id;
int bck_rate;
int tdm_out_mode;
int bck_invert;
int lck_invert;
int mclk_id;
int mclk_multiple; /* according to sample rate */
int mclk_rate;
int mclk_apll;
};
enum {
TDM_OUT_I2S = 0,
TDM_OUT_DSP_A = 1,
TDM_OUT_DSP_B = 2,
};
enum {
TDM_BCK_NON_INV = 0,
TDM_BCK_INV = 1,
};
enum {
TDM_LCK_NON_INV = 0,
TDM_LCK_INV = 1,
};
enum {
TDM_WLEN_16_BIT = 1,
TDM_WLEN_32_BIT = 2,
};
enum {
TDM_CHANNEL_BCK_16 = 0,
TDM_CHANNEL_BCK_24 = 1,
TDM_CHANNEL_BCK_32 = 2,
};
enum {
TDM_CHANNEL_NUM_2 = 0,
TDM_CHANNEL_NUM_4 = 1,
TDM_CHANNEL_NUM_8 = 2,
};
enum {
TDM_CH_START_O30_O31 = 0,
TDM_CH_START_O32_O33,
TDM_CH_START_O34_O35,
TDM_CH_START_O36_O37,
TDM_CH_ZERO,
};
static unsigned int get_tdm_wlen(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
}
static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) <= 16 ?
TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
}
static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format) - 1;
}
static unsigned int get_tdm_ch(unsigned int ch)
{
switch (ch) {
case 1:
case 2:
return TDM_CHANNEL_NUM_2;
case 3:
case 4:
return TDM_CHANNEL_NUM_4;
case 5:
case 6:
case 7:
case 8:
default:
return TDM_CHANNEL_NUM_8;
}
}
static unsigned int get_tdm_ch_fixup(unsigned int channels)
{
if (channels > 4)
return 8;
else if (channels > 2)
return 4;
else
return 2;
}
static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
unsigned int channels)
{
if (mode == TDM_OUT_DSP_A || mode == TDM_OUT_DSP_B)
return get_tdm_ch_fixup(channels);
else
return 2;
}
/* interconnection */
enum {
HDMI_CONN_CH0 = 0,
HDMI_CONN_CH1,
HDMI_CONN_CH2,
HDMI_CONN_CH3,
HDMI_CONN_CH4,
HDMI_CONN_CH5,
HDMI_CONN_CH6,
HDMI_CONN_CH7,
};
static const char *const hdmi_conn_mux_map[] = {
"CH0", "CH1", "CH2", "CH3",
"CH4", "CH5", "CH6", "CH7",
};
static int hdmi_conn_mux_map_value[] = {
HDMI_CONN_CH0,
HDMI_CONN_CH1,
HDMI_CONN_CH2,
HDMI_CONN_CH3,
HDMI_CONN_CH4,
HDMI_CONN_CH5,
HDMI_CONN_CH6,
HDMI_CONN_CH7,
};
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_0_SFT,
HDMI_O_0_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch0_mux_control =
SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_1_SFT,
HDMI_O_1_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch1_mux_control =
SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_2_SFT,
HDMI_O_2_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch2_mux_control =
SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_3_SFT,
HDMI_O_3_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch3_mux_control =
SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_4_SFT,
HDMI_O_4_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch4_mux_control =
SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_5_SFT,
HDMI_O_5_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch5_mux_control =
SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_6_SFT,
HDMI_O_6_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch6_mux_control =
SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
AFE_HDMI_CONN0,
HDMI_O_7_SFT,
HDMI_O_7_MASK,
hdmi_conn_mux_map,
hdmi_conn_mux_map_value);
static const struct snd_kcontrol_new hdmi_ch7_mux_control =
SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
enum {
SUPPLY_SEQ_APLL,
SUPPLY_SEQ_TDM_MCK_EN,
SUPPLY_SEQ_TDM_BCK_EN,
SUPPLY_SEQ_TDM_EN,
};
static int get_tdm_id_by_name(const char *name)
{
return MT8192_DAI_TDM;
}
static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
if (!tdm_priv) {
dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
return -EINVAL;
}
dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
__func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
break;
case SND_SOC_DAPM_POST_PMD:
mt8192_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
break;
default:
break;
}
return 0;
}
static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
if (!tdm_priv) {
dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
return -EINVAL;
}
dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
__func__, w->name, event, dai_id);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
break;
case SND_SOC_DAPM_POST_PMD:
mt8192_mck_disable(afe, tdm_priv->bck_id);
break;
default:
break;
}
return 0;
}
static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
if (!tdm_priv) {
dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
return -EINVAL;
}
dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
__func__, w->name, event, dai_id);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
break;
case SND_SOC_DAPM_POST_PMD:
tdm_priv->mclk_rate = 0;
mt8192_mck_disable(afe, tdm_priv->mclk_id);
break;
default:
break;
}
return 0;
}
static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch0_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch1_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch2_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch3_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch4_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch5_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch6_mux_control),
SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch7_mux_control),
SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
AFE_TDM_CON1, TDM_EN_SFT, 0,
mtk_tdm_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
SND_SOC_NOPM, 0, 0,
mtk_tdm_bck_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
SND_SOC_NOPM, 0, 0,
mtk_tdm_mck_en_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = sink;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dai_id = get_tdm_id_by_name(w->name);
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
int cur_apll;
/* which apll */
cur_apll = mt8192_get_apll_by_name(afe, source->name);
return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
}
static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
{"HDMI_CH0_MUX", "CH0", "HDMI"},
{"HDMI_CH0_MUX", "CH1", "HDMI"},
{"HDMI_CH0_MUX", "CH2", "HDMI"},
{"HDMI_CH0_MUX", "CH3", "HDMI"},
{"HDMI_CH0_MUX", "CH4", "HDMI"},
{"HDMI_CH0_MUX", "CH5", "HDMI"},
{"HDMI_CH0_MUX", "CH6", "HDMI"},
{"HDMI_CH0_MUX", "CH7", "HDMI"},
{"HDMI_CH1_MUX", "CH0", "HDMI"},
{"HDMI_CH1_MUX", "CH1", "HDMI"},
{"HDMI_CH1_MUX", "CH2", "HDMI"},
{"HDMI_CH1_MUX", "CH3", "HDMI"},
{"HDMI_CH1_MUX", "CH4", "HDMI"},
{"HDMI_CH1_MUX", "CH5", "HDMI"},
{"HDMI_CH1_MUX", "CH6", "HDMI"},
{"HDMI_CH1_MUX", "CH7", "HDMI"},
{"HDMI_CH2_MUX", "CH0", "HDMI"},
{"HDMI_CH2_MUX", "CH1", "HDMI"},
{"HDMI_CH2_MUX", "CH2", "HDMI"},
{"HDMI_CH2_MUX", "CH3", "HDMI"},
{"HDMI_CH2_MUX", "CH4", "HDMI"},
{"HDMI_CH2_MUX", "CH5", "HDMI"},
{"HDMI_CH2_MUX", "CH6", "HDMI"},
{"HDMI_CH2_MUX", "CH7", "HDMI"},
{"HDMI_CH3_MUX", "CH0", "HDMI"},
{"HDMI_CH3_MUX", "CH1", "HDMI"},
{"HDMI_CH3_MUX", "CH2", "HDMI"},
{"HDMI_CH3_MUX", "CH3", "HDMI"},
{"HDMI_CH3_MUX", "CH4", "HDMI"},
{"HDMI_CH3_MUX", "CH5", "HDMI"},
{"HDMI_CH3_MUX", "CH6", "HDMI"},
{"HDMI_CH3_MUX", "CH7", "HDMI"},
{"HDMI_CH4_MUX", "CH0", "HDMI"},
{"HDMI_CH4_MUX", "CH1", "HDMI"},
{"HDMI_CH4_MUX", "CH2", "HDMI"},
{"HDMI_CH4_MUX", "CH3", "HDMI"},
{"HDMI_CH4_MUX", "CH4", "HDMI"},
{"HDMI_CH4_MUX", "CH5", "HDMI"},
{"HDMI_CH4_MUX", "CH6", "HDMI"},
{"HDMI_CH4_MUX", "CH7", "HDMI"},
{"HDMI_CH5_MUX", "CH0", "HDMI"},
{"HDMI_CH5_MUX", "CH1", "HDMI"},
{"HDMI_CH5_MUX", "CH2", "HDMI"},
{"HDMI_CH5_MUX", "CH3", "HDMI"},
{"HDMI_CH5_MUX", "CH4", "HDMI"},
{"HDMI_CH5_MUX", "CH5", "HDMI"},
{"HDMI_CH5_MUX", "CH6", "HDMI"},
{"HDMI_CH5_MUX", "CH7", "HDMI"},
{"HDMI_CH6_MUX", "CH0", "HDMI"},
{"HDMI_CH6_MUX", "CH1", "HDMI"},
{"HDMI_CH6_MUX", "CH2", "HDMI"},
{"HDMI_CH6_MUX", "CH3", "HDMI"},
{"HDMI_CH6_MUX", "CH4", "HDMI"},
{"HDMI_CH6_MUX", "CH5", "HDMI"},
{"HDMI_CH6_MUX", "CH6", "HDMI"},
{"HDMI_CH6_MUX", "CH7", "HDMI"},
{"HDMI_CH7_MUX", "CH0", "HDMI"},
{"HDMI_CH7_MUX", "CH1", "HDMI"},
{"HDMI_CH7_MUX", "CH2", "HDMI"},
{"HDMI_CH7_MUX", "CH3", "HDMI"},
{"HDMI_CH7_MUX", "CH4", "HDMI"},
{"HDMI_CH7_MUX", "CH5", "HDMI"},
{"HDMI_CH7_MUX", "CH6", "HDMI"},
{"HDMI_CH7_MUX", "CH7", "HDMI"},
{"TDM", NULL, "HDMI_CH0_MUX"},
{"TDM", NULL, "HDMI_CH1_MUX"},
{"TDM", NULL, "HDMI_CH2_MUX"},
{"TDM", NULL, "HDMI_CH3_MUX"},
{"TDM", NULL, "HDMI_CH4_MUX"},
{"TDM", NULL, "HDMI_CH5_MUX"},
{"TDM", NULL, "HDMI_CH6_MUX"},
{"TDM", NULL, "HDMI_CH7_MUX"},
{"TDM", NULL, "aud_tdm_clk"},
{"TDM", NULL, "TDM_BCK"},
{"TDM", NULL, "TDM_EN"},
{"TDM_BCK", NULL, "TDM_MCK"},
{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
};
/* dai ops */
static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
struct mtk_afe_tdm_priv *tdm_priv,
int freq)
{
int apll;
int apll_rate;
apll = mt8192_get_apll_by_rate(afe, freq);
apll_rate = mt8192_get_apll_rate(afe, apll);
if (!freq || freq > apll_rate) {
dev_warn(afe->dev,
"%s(), freq(%d Hz) invalid\n", __func__, freq);
return -EINVAL;
}
if (apll_rate % freq != 0) {
dev_warn(afe->dev,
"%s(), APLL cannot generate %d Hz", __func__, freq);
return -EINVAL;
}
tdm_priv->mclk_rate = freq;
tdm_priv->mclk_apll = apll;
return 0;
}
static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int tdm_id = dai->id;
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
unsigned int rate = params_rate(params);
unsigned int channels = params_channels(params);
unsigned int out_channels_per_sdata =
get_tdm_ch_per_sdata(tdm_out_mode, channels);
snd_pcm_format_t format = params_format(params);
unsigned int tdm_con = 0;
/* calculate mclk_rate, if not set explicitly */
if (!tdm_priv->mclk_rate) {
tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
mtk_dai_tdm_cal_mclk(afe,
tdm_priv,
tdm_priv->mclk_rate);
}
/* calculate bck */
tdm_priv->bck_rate = rate *
out_channels_per_sdata *
snd_pcm_format_physical_width(format);
if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
__func__,
tdm_id, rate, channels, format,
tdm_priv->mclk_rate, tdm_priv->bck_rate);
dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
__func__, out_channels_per_sdata);
/* set tdm */
if (tdm_priv->bck_invert)
tdm_con |= 1 << BCK_INVERSE_SFT;
if (tdm_priv->lck_invert)
tdm_con |= 1 << LRCK_INVERSE_SFT;
if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
tdm_con |= 1 << DELAY_DATA_SFT;
tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
} else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) {
tdm_con |= 0 << DELAY_DATA_SFT;
tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
} else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) {
tdm_con |= 1 << DELAY_DATA_SFT;
tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
}
tdm_con |= 1 << LEFT_ALIGN_SFT;
tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
if (out_channels_per_sdata == 2) {
switch (channels) {
case 1:
case 2:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 3:
case 4:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 5:
case 6:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
break;
case 7:
case 8:
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
break;
default:
tdm_con = 0;
}
} else {
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
}
regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
HDMI_CH_NUM_MASK_SFT,
channels << HDMI_CH_NUM_SFT);
return 0;
}
static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
if (!tdm_priv) {
dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
return -EINVAL;
}
if (dir != SND_SOC_CLOCK_OUT) {
dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
return -EINVAL;
}
dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
}
static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
if (!tdm_priv) {
dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
return -EINVAL;
}
/* DAI mode*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
tdm_priv->tdm_out_mode = TDM_OUT_I2S;
break;
case SND_SOC_DAIFMT_DSP_A:
tdm_priv->tdm_out_mode = TDM_OUT_DSP_A;
break;
case SND_SOC_DAIFMT_DSP_B:
tdm_priv->tdm_out_mode = TDM_OUT_DSP_B;
break;
default:
tdm_priv->tdm_out_mode = TDM_OUT_I2S;
}
/* DAI clock inversion*/
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
tdm_priv->bck_invert = TDM_BCK_NON_INV;
tdm_priv->lck_invert = TDM_LCK_NON_INV;
break;
case SND_SOC_DAIFMT_NB_IF:
tdm_priv->bck_invert = TDM_BCK_NON_INV;
tdm_priv->lck_invert = TDM_LCK_INV;
break;
case SND_SOC_DAIFMT_IB_NF:
tdm_priv->bck_invert = TDM_BCK_INV;
tdm_priv->lck_invert = TDM_LCK_NON_INV;
break;
case SND_SOC_DAIFMT_IB_IF:
default:
tdm_priv->bck_invert = TDM_BCK_INV;
tdm_priv->lck_invert = TDM_LCK_INV;
break;
}
return 0;
}
static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
.hw_params = mtk_dai_tdm_hw_params,
.set_sysclk = mtk_dai_tdm_set_sysclk,
.set_fmt = mtk_dai_tdm_set_fmt,
};
/* dai driver */
#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000)
#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
{
.name = "TDM",
.id = MT8192_DAI_TDM,
.playback = {
.stream_name = "TDM",
.channels_min = 2,
.channels_max = 8,
.rates = MTK_TDM_RATES,
.formats = MTK_TDM_FORMATS,
},
.ops = &mtk_dai_tdm_ops,
},
};
static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
{
struct mtk_afe_tdm_priv *tdm_priv;
tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
GFP_KERNEL);
if (!tdm_priv)
return NULL;
tdm_priv->mclk_multiple = 128;
tdm_priv->bck_id = MT8192_I2S4_BCK;
tdm_priv->mclk_id = MT8192_I2S4_MCK;
tdm_priv->id = MT8192_DAI_TDM;
return tdm_priv;
}
int mt8192_dai_tdm_register(struct mtk_base_afe *afe)
{
struct mt8192_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_tdm_priv *tdm_priv;
struct mtk_base_afe_dai *dai;
dev_info(afe->dev, "%s()\n", __func__);
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
list_add(&dai->list, &afe->sub_dais);
dai->dai_drivers = mtk_dai_tdm_driver;
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
dai->dapm_widgets = mtk_dai_tdm_widgets;
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
dai->dapm_routes = mtk_dai_tdm_routes;
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
tdm_priv = init_tdm_priv_data(afe);
if (!tdm_priv)
return -ENOMEM;
afe_priv->dai_priv[MT8192_DAI_TDM] = tdm_priv;
return 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Mediatek MT8192 audio driver interconnection definition
*
* Copyright (c) 2020 MediaTek Inc.
* Author: Shane Chien <shane.chien@mediatek.com>
*/
#ifndef _MT8192_INTERCONNECTION_H_
#define _MT8192_INTERCONNECTION_H_
/* in port define */
#define I_I2S0_CH1 0
#define I_I2S0_CH2 1
#define I_ADDA_UL_CH1 3
#define I_ADDA_UL_CH2 4
#define I_DL1_CH1 5
#define I_DL1_CH2 6
#define I_DL2_CH1 7
#define I_DL2_CH2 8
#define I_PCM_1_CAP_CH1 9
#define I_GAIN1_OUT_CH1 10
#define I_GAIN1_OUT_CH2 11
#define I_GAIN2_OUT_CH1 12
#define I_GAIN2_OUT_CH2 13
#define I_PCM_2_CAP_CH1 14
#define I_ADDA_UL_CH3 17
#define I_ADDA_UL_CH4 18
#define I_DL12_CH1 19
#define I_DL12_CH2 20
#define I_PCM_2_CAP_CH2 21
#define I_PCM_1_CAP_CH2 22
#define I_DL3_CH1 23
#define I_DL3_CH2 24
#define I_I2S2_CH1 25
#define I_I2S2_CH2 26
#define I_I2S2_CH3 27
#define I_I2S2_CH4 28
/* in port define >= 32 */
#define I_32_OFFSET 32
#define I_CONNSYS_I2S_CH1 (34 - I_32_OFFSET)
#define I_CONNSYS_I2S_CH2 (35 - I_32_OFFSET)
#define I_SRC_1_OUT_CH1 (36 - I_32_OFFSET)
#define I_SRC_1_OUT_CH2 (37 - I_32_OFFSET)
#define I_SRC_2_OUT_CH1 (38 - I_32_OFFSET)
#define I_SRC_2_OUT_CH2 (39 - I_32_OFFSET)
#define I_DL4_CH1 (40 - I_32_OFFSET)
#define I_DL4_CH2 (41 - I_32_OFFSET)
#define I_DL5_CH1 (42 - I_32_OFFSET)
#define I_DL5_CH2 (43 - I_32_OFFSET)
#define I_DL6_CH1 (44 - I_32_OFFSET)
#define I_DL6_CH2 (45 - I_32_OFFSET)
#define I_DL7_CH1 (46 - I_32_OFFSET)
#define I_DL7_CH2 (47 - I_32_OFFSET)
#define I_DL8_CH1 (48 - I_32_OFFSET)
#define I_DL8_CH2 (49 - I_32_OFFSET)
#define I_DL9_CH1 (50 - I_32_OFFSET)
#define I_DL9_CH2 (51 - I_32_OFFSET)
#define I_I2S6_CH1 (52 - I_32_OFFSET)
#define I_I2S6_CH2 (53 - I_32_OFFSET)
#define I_I2S8_CH1 (54 - I_32_OFFSET)
#define I_I2S8_CH2 (55 - I_32_OFFSET)
#endif
// SPDX-License-Identifier: GPL-2.0
//
// mt8192-mt6359-rt1015-rt5682.c --
// MT8192-MT6359-RT1015-RT6358 ALSA SoC machine driver
//
// Copyright (c) 2020 MediaTek Inc.
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
//
#include <linux/input.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/rt5682.h>
#include <sound/soc.h>
#include "../../codecs/mt6359.h"
#include "../../codecs/rt1015.h"
#include "../../codecs/rt5682.h"
#include "../common/mtk-afe-platform-driver.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-clk.h"
#include "mt8192-afe-gpio.h"
#define RT1015_CODEC_DAI "rt1015-aif"
#define RT1015_DEV0_NAME "rt1015.1-0028"
#define RT1015_DEV1_NAME "rt1015.1-0029"
#define RT5682_CODEC_DAI "rt5682-aif1"
#define RT5682_DEV0_NAME "rt5682.1-001a"
static struct snd_soc_jack headset_jack;
static const struct snd_soc_dapm_widget
mt8192_mt6359_rt1015_rt5682_widgets[] = {
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = {
/* speaker */
{ "Left Spk", NULL, "Left SPO" },
{ "Right Spk", NULL, "Right SPO" },
/* headset */
{ "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" },
{ "IN1P", NULL, "Headset Mic" },
};
static const struct snd_kcontrol_new mt8192_mt6359_rt1015_rt5682_controls[] = {
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
unsigned int rate = params_rate(params);
unsigned int mclk_fs_ratio = 128;
unsigned int mclk_fs = rate * mclk_fs_ratio;
int ret, i;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
if (ret) {
dev_err(card->dev, "failed to set bclk ratio\n");
return ret;
}
ret = snd_soc_dai_set_pll(codec_dai, 0,
RT1015_PLL_S_BCLK,
params_rate(params) * 64,
params_rate(params) * 256);
if (ret) {
dev_err(card->dev, "failed to set pll\n");
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai,
RT1015_SCLK_S_PLL,
params_rate(params) * 256,
SND_SOC_CLOCK_IN);
if (ret) {
dev_err(card->dev, "failed to set sysclk\n");
return ret;
}
}
return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
}
static int mt8192_rt5682_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
unsigned int rate = params_rate(params);
unsigned int mclk_fs_ratio = 128;
unsigned int mclk_fs = rate * mclk_fs_ratio;
int bitwidth;
int ret;
bitwidth = snd_pcm_format_width(params_format(params));
if (bitwidth < 0) {
dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
return bitwidth;
}
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
if (ret) {
dev_err(card->dev, "failed to set tdm slot\n");
return ret;
}
ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
RT5682_PLL1_S_BCLK1,
params_rate(params) * 64,
params_rate(params) * 512);
if (ret) {
dev_err(card->dev, "failed to set pll\n");
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai,
RT5682_SCLK_S_PLL1,
params_rate(params) * 512,
SND_SOC_CLOCK_IN);
if (ret) {
dev_err(card->dev, "failed to set sysclk\n");
return ret;
}
return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
}
static const struct snd_soc_ops mt8192_rt1015_i2s_ops = {
.hw_params = mt8192_rt1015_i2s_hw_params,
};
static const struct snd_soc_ops mt8192_rt5682_i2s_ops = {
.hw_params = mt8192_rt5682_i2s_hw_params,
};
static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int phase;
unsigned int monitor;
int test_done_1, test_done_2, test_done_3;
int cycle_1, cycle_2, cycle_3;
int prev_cycle_1, prev_cycle_2, prev_cycle_3;
int chosen_phase_1, chosen_phase_2, chosen_phase_3;
int counter;
int mtkaif_calib_ok;
dev_info(afe->dev, "%s(), start\n", __func__);
pm_runtime_get_sync(afe->dev);
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1);
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0);
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, 1);
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, 0);
mt6359_mtkaif_calibration_enable(cmpnt_codec);
/* set clock protocol 2 */
regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x38);
regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x39);
/* set test type to synchronizer pulse */
regmap_update_bits(afe_priv->topckgen,
CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
mtkaif_calib_ok = true;
afe_priv->mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */
afe_priv->mtkaif_chosen_phase[0] = -1;
afe_priv->mtkaif_chosen_phase[1] = -1;
afe_priv->mtkaif_chosen_phase[2] = -1;
for (phase = 0;
phase <= afe_priv->mtkaif_calibration_num_phase &&
mtkaif_calib_ok;
phase++) {
mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
phase, phase, phase);
regmap_update_bits(afe_priv->topckgen,
CKSYS_AUD_TOP_CFG, 0x1, 0x1);
test_done_1 = 0;
test_done_2 = 0;
test_done_3 = 0;
cycle_1 = -1;
cycle_2 = -1;
cycle_3 = -1;
counter = 0;
while (test_done_1 == 0 ||
test_done_2 == 0 ||
test_done_3 == 0) {
regmap_read(afe_priv->topckgen,
CKSYS_AUD_TOP_MON, &monitor);
test_done_1 = (monitor >> 28) & 0x1;
test_done_2 = (monitor >> 29) & 0x1;
test_done_3 = (monitor >> 30) & 0x1;
if (test_done_1 == 1)
cycle_1 = monitor & 0xf;
if (test_done_2 == 1)
cycle_2 = (monitor >> 4) & 0xf;
if (test_done_3 == 1)
cycle_3 = (monitor >> 8) & 0xf;
/* handle if never test done */
if (++counter > 10000) {
dev_err(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n",
__func__,
cycle_1, cycle_2, cycle_3, monitor);
mtkaif_calib_ok = false;
break;
}
}
if (phase == 0) {
prev_cycle_1 = cycle_1;
prev_cycle_2 = cycle_2;
prev_cycle_3 = cycle_3;
}
if (cycle_1 != prev_cycle_1 &&
afe_priv->mtkaif_chosen_phase[0] < 0) {
afe_priv->mtkaif_chosen_phase[0] = phase - 1;
afe_priv->mtkaif_phase_cycle[0] = prev_cycle_1;
}
if (cycle_2 != prev_cycle_2 &&
afe_priv->mtkaif_chosen_phase[1] < 0) {
afe_priv->mtkaif_chosen_phase[1] = phase - 1;
afe_priv->mtkaif_phase_cycle[1] = prev_cycle_2;
}
if (cycle_3 != prev_cycle_3 &&
afe_priv->mtkaif_chosen_phase[2] < 0) {
afe_priv->mtkaif_chosen_phase[2] = phase - 1;
afe_priv->mtkaif_phase_cycle[2] = prev_cycle_3;
}
regmap_update_bits(afe_priv->topckgen,
CKSYS_AUD_TOP_CFG, 0x1, 0x0);
if (afe_priv->mtkaif_chosen_phase[0] >= 0 &&
afe_priv->mtkaif_chosen_phase[1] >= 0 &&
afe_priv->mtkaif_chosen_phase[2] >= 0)
break;
}
if (afe_priv->mtkaif_chosen_phase[0] < 0)
chosen_phase_1 = 0;
else
chosen_phase_1 = afe_priv->mtkaif_chosen_phase[0];
if (afe_priv->mtkaif_chosen_phase[1] < 0)
chosen_phase_2 = 0;
else
chosen_phase_2 = afe_priv->mtkaif_chosen_phase[1];
if (afe_priv->mtkaif_chosen_phase[2] < 0)
chosen_phase_3 = 0;
else
chosen_phase_3 = afe_priv->mtkaif_chosen_phase[2];
mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
chosen_phase_1,
chosen_phase_2,
chosen_phase_3);
/* disable rx fifo */
regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x38);
mt6359_mtkaif_calibration_disable(cmpnt_codec);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 1);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 0);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 1);
mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 0);
pm_runtime_put(afe->dev);
dev_info(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n",
__func__,
afe_priv->mtkaif_chosen_phase[0],
afe_priv->mtkaif_chosen_phase[1],
afe_priv->mtkaif_chosen_phase[2]);
return 0;
}
static int mt8192_mt6359_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
/* set mtkaif protocol */
mt6359_set_mtkaif_protocol(cmpnt_codec,
MT6359_MTKAIF_PROTOCOL_2_CLK_P2);
afe_priv->mtkaif_protocol = MTKAIF_PROTOCOL_2_CLK_P2;
/* mtkaif calibration */
mt8192_mt6359_mtkaif_calibration(rtd);
return 0;
}
static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
struct snd_soc_jack *jack = &headset_jack;
int ret;
ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3,
jack, NULL, 0);
if (ret) {
dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
return ret;
}
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
if (ret) {
dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
return ret;
}
return 0;
};
static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
/* fix BE i2s format to 32bit, clean param mask first */
snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
0, SNDRV_PCM_FORMAT_LAST);
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
static int
mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
int ret;
static const unsigned int channels[] = {
1, 2, 4
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
static const unsigned int rates[] = {
8000, 16000, 32000, 48000, 96000, 192000
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
struct snd_pcm_runtime *runtime = substream->runtime;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(afe->dev, "hw_constraint_list channels failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(afe->dev, "hw_constraint_list rate failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8192_mt6359_rt1015_rt5682_capture1_ops = {
.startup = mt8192_mt6359_rt1015_rt5682_cap1_startup,
};
/* FE */
SND_SOC_DAILINK_DEFS(playback1,
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback12,
DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback2,
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback3,
DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback4,
DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback5,
DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback6,
DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback7,
DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback8,
DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback9,
DAILINK_COMP_ARRAY(COMP_CPU("DL9")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture1,
DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture2,
DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture3,
DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture4,
DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture5,
DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture6,
DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture7,
DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture8,
DAILINK_COMP_ARRAY(COMP_CPU("UL8")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture_mono1,
DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture_mono2,
DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture_mono3,
DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_3")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback_hdmi,
DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* BE */
SND_SOC_DAILINK_DEFS(primary_codec,
DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
"mt6359-snd-codec-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(primary_codec_ch34,
DAILINK_COMP_ARRAY(COMP_CPU("ADDA_CH34")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
"mt6359-snd-codec-aif2")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(ap_dmic,
DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(ap_dmic_ch34,
DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s0,
DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s1,
DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s2,
DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s3,
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME,
RT1015_CODEC_DAI),
COMP_CODEC(RT1015_DEV1_NAME,
RT1015_CODEC_DAI)),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s5,
DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s6,
DAILINK_COMP_ARRAY(COMP_CPU("I2S6")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s7,
DAILINK_COMP_ARRAY(COMP_CPU("I2S7")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s8,
DAILINK_COMP_ARRAY(COMP_CPU("I2S8")),
DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
RT5682_CODEC_DAI)),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s9,
DAILINK_COMP_ARRAY(COMP_CPU("I2S9")),
DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
RT5682_CODEC_DAI)),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(connsys_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(pcm1,
DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(pcm2,
DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(tdm,
DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link mt8192_mt6359_rt1015_rt5682_dai_links[] = {
/* Front End DAI links */
{
.name = "Playback_1",
.stream_name = "Playback_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback1),
},
{
.name = "Playback_12",
.stream_name = "Playback_12",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback12),
},
{
.name = "Playback_2",
.stream_name = "Playback_2",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback2),
},
{
.name = "Playback_3",
.stream_name = "Playback_3",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback3),
},
{
.name = "Playback_4",
.stream_name = "Playback_4",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback4),
},
{
.name = "Playback_5",
.stream_name = "Playback_5",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback5),
},
{
.name = "Playback_6",
.stream_name = "Playback_6",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback6),
},
{
.name = "Playback_7",
.stream_name = "Playback_7",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback7),
},
{
.name = "Playback_8",
.stream_name = "Playback_8",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback8),
},
{
.name = "Playback_9",
.stream_name = "Playback_9",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback9),
},
{
.name = "Capture_1",
.stream_name = "Capture_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8192_mt6359_rt1015_rt5682_capture1_ops,
SND_SOC_DAILINK_REG(capture1),
},
{
.name = "Capture_2",
.stream_name = "Capture_2",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture2),
},
{
.name = "Capture_3",
.stream_name = "Capture_3",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture3),
},
{
.name = "Capture_4",
.stream_name = "Capture_4",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture4),
},
{
.name = "Capture_5",
.stream_name = "Capture_5",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture5),
},
{
.name = "Capture_6",
.stream_name = "Capture_6",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture6),
},
{
.name = "Capture_7",
.stream_name = "Capture_7",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture7),
},
{
.name = "Capture_8",
.stream_name = "Capture_8",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture8),
},
{
.name = "Capture_Mono_1",
.stream_name = "Capture_Mono_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture_mono1),
},
{
.name = "Capture_Mono_2",
.stream_name = "Capture_Mono_2",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture_mono2),
},
{
.name = "Capture_Mono_3",
.stream_name = "Capture_Mono_3",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture_mono3),
},
{
.name = "playback_hdmi",
.stream_name = "Playback_HDMI",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback_hdmi),
},
/* Back End DAI links */
{
.name = "Primary Codec",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.init = mt8192_mt6359_init,
SND_SOC_DAILINK_REG(primary_codec),
},
{
.name = "Primary Codec CH34",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(primary_codec_ch34),
},
{
.name = "AP_DMIC",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(ap_dmic),
},
{
.name = "AP_DMIC_CH34",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(ap_dmic_ch34),
},
{
.name = "I2S0",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s0),
},
{
.name = "I2S1",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s1),
},
{
.name = "I2S2",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s2),
},
{
.name = "I2S3",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s3),
.ops = &mt8192_rt1015_i2s_ops,
},
{
.name = "I2S5",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s5),
},
{
.name = "I2S6",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s6),
},
{
.name = "I2S7",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s7),
},
{
.name = "I2S8",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.init = mt8192_rt5682_init,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s8),
.ops = &mt8192_rt5682_i2s_ops,
},
{
.name = "I2S9",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s9),
.ops = &mt8192_rt5682_i2s_ops,
},
{
.name = "CONNSYS_I2S",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(connsys_i2s),
},
{
.name = "PCM 1",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "PCM 2",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm2),
},
{
.name = "TDM",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(tdm),
},
};
static struct snd_soc_codec_conf rt1015_amp_conf[] = {
{
.dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
.name_prefix = "Left",
},
{
.dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
.name_prefix = "Right",
},
};
static struct snd_soc_card mt8192_mt6359_rt1015_rt5682_soc_card = {
.name = "mt8192_mt6359_rt1015_rt5682",
.owner = THIS_MODULE,
.dai_link = mt8192_mt6359_rt1015_rt5682_dai_links,
.num_links = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_dai_links),
.controls = mt8192_mt6359_rt1015_rt5682_controls,
.num_controls = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_controls),
.dapm_widgets = mt8192_mt6359_rt1015_rt5682_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_widgets),
.dapm_routes = mt8192_mt6359_rt1015_rt5682_routes,
.num_dapm_routes = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_routes),
.codec_conf = rt1015_amp_conf,
.num_configs = ARRAY_SIZE(rt1015_amp_conf),
};
static int mt8192_mt6359_rt1015_rt5682_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8192_mt6359_rt1015_rt5682_soc_card;
struct device_node *platform_node;
int ret, i;
struct snd_soc_dai_link *dai_link;
card->dev = &pdev->dev;
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
if (!platform_node) {
dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
return -EINVAL;
}
for_each_card_prelinks(card, i, dai_link) {
if (!dai_link->platforms->name)
dai_link->platforms->of_node = platform_node;
}
ret = mt8192_afe_gpio_init(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "init gpio error %d\n", ret);
return ret;
}
return devm_snd_soc_register_card(&pdev->dev, card);
}
#ifdef CONFIG_OF
static const struct of_device_id mt8192_mt6359_rt1015_rt5682_dt_match[] = {
{.compatible = "mediatek,mt8192_mt6359_rt1015_rt5682",},
{}
};
#endif
static const struct dev_pm_ops mt8192_mt6359_rt1015_rt5682_pm_ops = {
.poweroff = snd_soc_poweroff,
.restore = snd_soc_resume,
};
static struct platform_driver mt8192_mt6359_rt1015_rt5682_driver = {
.driver = {
.name = "mt8192_mt6359_rt1015_rt5682",
#ifdef CONFIG_OF
.of_match_table = mt8192_mt6359_rt1015_rt5682_dt_match,
#endif
.pm = &mt8192_mt6359_rt1015_rt5682_pm_ops,
},
.probe = mt8192_mt6359_rt1015_rt5682_dev_probe,
};
module_platform_driver(mt8192_mt6359_rt1015_rt5682_driver);
/* Module information */
MODULE_DESCRIPTION("MT8192-MT6359-RT1015-RT5682 ALSA SoC machine driver");
MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mt8192_mt6359_rt1015_rt5682 soc card");
This source diff could not be displayed because it is too large. You can view the blob instead.
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