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
This commit is contained in:
Коммит
860bfa6d66
|
@ -0,0 +1,100 @@
|
|||
# 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";
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,42 @@
|
|||
# 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:
|
||||
hd_audio = 1;
|
||||
hd_align = 1;
|
||||
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;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# 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
|
|
@ -0,0 +1,669 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/* 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
|
|
@ -0,0 +1,170 @@
|
|||
/* 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
|
|
@ -0,0 +1,163 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/* 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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,409 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,778 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/* 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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче