mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
ASoC: mediatek: Add support for MT8189 SoC
Merge series from Cyril Chao <Cyril.Chao@mediatek.com>: This series of patches adds support for Mediatek AFE of MT8189 SoC.
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt8189-afe-pcm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Audio Front End PCM controller for MT8189
|
||||
|
||||
maintainers:
|
||||
- Darren Ye <darren.ye@mediatek.com>
|
||||
- Cyril Chao <cyril.chao@mediatek.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8189-afe-pcm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,apmixedsys:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: To set up the apll12 tuner
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: mux for audio intbus
|
||||
- description: mux for audio engen1
|
||||
- description: mux for audio engen2
|
||||
- description: mux for audio h
|
||||
- description: audio apll1 clock
|
||||
- description: audio apll2 clock
|
||||
- description: audio apll1 divide4
|
||||
- description: audio apll2 divide4
|
||||
- description: audio apll12 divide for i2sin0
|
||||
- description: audio apll12 divide for i2sin1
|
||||
- description: audio apll12 divide for i2sout0
|
||||
- description: audio apll12 divide for i2sout1
|
||||
- description: audio apll12 divide for fmi2s
|
||||
- description: audio apll12 divide for tdmout mck
|
||||
- description: audio apll12 divide for tdmout bck
|
||||
- description: mux for audio apll1
|
||||
- description: mux for audio apll2
|
||||
- description: mux for i2sin0 mck
|
||||
- description: mux for i2sin1 mck
|
||||
- description: mux for i2sout0 mck
|
||||
- description: mux for i2sout1 mck
|
||||
- description: mux for fmi2s mck
|
||||
- description: mux for tdmout mck
|
||||
- description: 26m clock
|
||||
- description: audio slv clock
|
||||
- description: audio mst clock
|
||||
- description: audio intbus clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: top_aud_intbus
|
||||
- const: top_aud_eng1
|
||||
- const: top_aud_eng2
|
||||
- const: top_aud_h
|
||||
- const: apll1
|
||||
- const: apll2
|
||||
- const: apll1_d4
|
||||
- const: apll2_d4
|
||||
- const: apll12_div_i2sin0
|
||||
- const: apll12_div_i2sin1
|
||||
- const: apll12_div_i2sout0
|
||||
- const: apll12_div_i2sout1
|
||||
- const: apll12_div_fmi2s
|
||||
- const: apll12_div_tdmout_m
|
||||
- const: apll12_div_tdmout_b
|
||||
- const: top_apll1
|
||||
- const: top_apll2
|
||||
- const: top_i2sin0
|
||||
- const: top_i2sin1
|
||||
- const: top_i2sout0
|
||||
- const: top_i2sout1
|
||||
- const: top_fmi2s
|
||||
- const: top_dptx
|
||||
- const: clk26m
|
||||
- const: aud_slv_ck_peri
|
||||
- const: aud_mst_ck_peri
|
||||
- const: aud_intbus_ck_peri
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- memory-region
|
||||
- power-domains
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
afe@11050000 {
|
||||
compatible = "mediatek,mt8189-afe-pcm";
|
||||
reg = <0 0x11050000 0 0x10000>;
|
||||
interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
memory-region = <&afe_dma_mem_reserved>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&aud_pins_default>;
|
||||
power-domains = <&scpsys 1>; //MT8189_POWER_DOMAIN_AUDIO
|
||||
clocks = <&topckgen_clk 23>, //CLK_TOP_AUD_INTBUS_SEL
|
||||
<&topckgen_clk 39>, //CLK_TOP_AUD_ENGEN1_SEL
|
||||
<&topckgen_clk 40>, //CLK_TOP_AUD_ENGEN2_SEL
|
||||
<&topckgen_clk 49>, //CLK_TOP_AUDIO_H_SEL
|
||||
<&topckgen_clk 146>, //CLK_TOP_APLL1
|
||||
<&topckgen_clk 151>, //CLK_TOP_APLL2
|
||||
<&topckgen_clk 148>, //CLK_TOP_APLL1_D4
|
||||
<&topckgen_clk 153>, //CLK_TOP_APLL2_D4
|
||||
<&topckgen_clk 93>, //CLK_TOP_APLL12_CK_DIV_I2SIN0
|
||||
<&topckgen_clk 94>, //CLK_TOP_APLL12_CK_DIV_I2SIN1
|
||||
<&topckgen_clk 95>, //CLK_TOP_APLL12_CK_DIV_I2SOUT0
|
||||
<&topckgen_clk 96>, //CLK_TOP_APLL12_CK_DIV_I2SOUT1
|
||||
<&topckgen_clk 97>, //CLK_TOP_APLL12_CK_DIV_FMI2S
|
||||
<&topckgen_clk 98>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_M
|
||||
<&topckgen_clk 99>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_B
|
||||
<&topckgen_clk 44>, //CLK_TOP_AUD_1_SEL
|
||||
<&topckgen_clk 45>, //CLK_TOP_AUD_2_SEL
|
||||
<&topckgen_clk 78>, //CLK_TOP_APLL_I2SIN0_MCK_SEL
|
||||
<&topckgen_clk 79>, //CLK_TOP_APLL_I2SIN1_MCK_SEL
|
||||
<&topckgen_clk 84>, //CLK_TOP_APLL_I2SOUT0_MCK_SEL
|
||||
<&topckgen_clk 85>, //CLK_TOP_APLL_I2SOUT1_MCK_SEL
|
||||
<&topckgen_clk 90>, //CLK_TOP_APLL_FMI2S_MCK_SEL
|
||||
<&topckgen_clk 91>, //CLK_TOP_APLL_TDMOUT_MCK_SEL
|
||||
<&topckgen_clk 191>, //CLK_TOP_TCK_26M_MX9
|
||||
<&pericfg_ao_clk 77>, //CLK_PERAO_AUDIO0
|
||||
<&pericfg_ao_clk 78>, //CLK_PERAO_AUDIO1
|
||||
<&pericfg_ao_clk 79>; //CLK_PERAO_AUDIO2
|
||||
clock-names = "top_aud_intbus",
|
||||
"top_aud_eng1",
|
||||
"top_aud_eng2",
|
||||
"top_aud_h",
|
||||
"apll1",
|
||||
"apll2",
|
||||
"apll1_d4",
|
||||
"apll2_d4",
|
||||
"apll12_div_i2sin0",
|
||||
"apll12_div_i2sin1",
|
||||
"apll12_div_i2sout0",
|
||||
"apll12_div_i2sout1",
|
||||
"apll12_div_fmi2s",
|
||||
"apll12_div_tdmout_m",
|
||||
"apll12_div_tdmout_b",
|
||||
"top_apll1",
|
||||
"top_apll2",
|
||||
"top_i2sin0",
|
||||
"top_i2sin1",
|
||||
"top_i2sout0",
|
||||
"top_i2sout1",
|
||||
"top_fmi2s",
|
||||
"top_dptx",
|
||||
"clk26m",
|
||||
"aud_slv_ck_peri",
|
||||
"aud_mst_ck_peri",
|
||||
"aud_intbus_ck_peri";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt8189-nau8825.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT8189 ASoC sound card
|
||||
|
||||
maintainers:
|
||||
- Darren Ye <darren.ye@mediatek.com>
|
||||
- Cyril Chao <cyril.chao@mediatek.com>
|
||||
|
||||
allOf:
|
||||
- $ref: sound-card-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8189-nau8825
|
||||
- mediatek,mt8189-rt5650
|
||||
- mediatek,mt8189-rt5682s
|
||||
- mediatek,mt8189-rt5682i
|
||||
- mediatek,mt8189-es8326
|
||||
|
||||
mediatek,platform:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of MT8189 ASoC platform.
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
description:
|
||||
Container for dai-link level properties and CODEC sub-nodes.
|
||||
|
||||
properties:
|
||||
link-name:
|
||||
description:
|
||||
This property corresponds to the name of the BE dai-link to which
|
||||
we are going to update parameters in this node.
|
||||
enum:
|
||||
- TDM_DPTX_BE
|
||||
- I2SOUT0_BE
|
||||
- I2SIN0_BE
|
||||
- I2SOUT1_BE
|
||||
|
||||
codec:
|
||||
description: Holds subnode which indicates codec dai.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
sound-dai:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
dai-format:
|
||||
description: audio format.
|
||||
enum:
|
||||
- i2s
|
||||
- right_j
|
||||
- left_j
|
||||
- dsp_a
|
||||
- dsp_b
|
||||
|
||||
mediatek,clk-provider:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Indicates dai-link clock master.
|
||||
enum:
|
||||
- cpu
|
||||
- codec
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- link-name
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "mediatek,mt8189-nau8825";
|
||||
model = "mt8189_rt9123_8825";
|
||||
mediatek,platform = <&afe>;
|
||||
dai-link-0 {
|
||||
link-name = "I2SOUT1_BE";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&nau8825>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -246,6 +246,37 @@ config SND_SOC_MT8188_MT6359
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8189
|
||||
tristate "ASoC support for Mediatek MT8189 chip"
|
||||
depends on ARCH_MEDIATEK
|
||||
select SND_SOC_MEDIATEK
|
||||
help
|
||||
This adds ASoC driver for Mediatek MT8189 boards
|
||||
that can be used with other codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8189_NAU8825
|
||||
tristate "ASoc Audio driver for MT8189 with NAU8825 and I2S codec"
|
||||
depends on SND_SOC_MT8189
|
||||
depends on I2C
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDMI_CODEC
|
||||
select SND_SOC_NAU8825
|
||||
select SND_SOC_RT5645
|
||||
select SND_SOC_RT9123P
|
||||
select SND_SOC_RT1015P
|
||||
select SND_SOC_RT5682S
|
||||
select SND_SOC_RT5682_I2C
|
||||
select SND_SOC_CS35L41_I2C
|
||||
select SND_SOC_AW88081
|
||||
select SND_SOC_ES8326
|
||||
help
|
||||
This adds support for ASoC machine driver for MediaTek MT8189
|
||||
boards with the NAU8828 and other I2S audio codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8192
|
||||
tristate "ASoC support for Mediatek MT8192 chip"
|
||||
depends on ARCH_MEDIATEK
|
||||
|
||||
@@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_MT8188) += mt8188/
|
||||
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
|
||||
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
|
||||
obj-$(CONFIG_SND_SOC_MT8365) += mt8365/
|
||||
obj-$(CONFIG_SND_SOC_MT8189) += mt8189/
|
||||
|
||||
18
sound/soc/mediatek/mt8189/Makefile
Normal file
18
sound/soc/mediatek/mt8189/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# common include path
|
||||
subdir-ccflags-y += -I$(srctree)/sound/soc/mediatek/common
|
||||
|
||||
# platform driver
|
||||
snd-soc-mt8189-afe-objs += \
|
||||
mt8189-afe-pcm.o \
|
||||
mt8189-afe-clk.o \
|
||||
mt8189-dai-adda.o \
|
||||
mt8189-dai-i2s.o \
|
||||
mt8189-dai-pcm.o \
|
||||
mt8189-dai-tdm.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_MT8189) += snd-soc-mt8189-afe.o
|
||||
|
||||
# machine driver
|
||||
obj-$(CONFIG_SND_SOC_MT8189_NAU8825) += mt8189-nau8825.o
|
||||
750
sound/soc/mediatek/mt8189/mt8189-afe-clk.c
Normal file
750
sound/soc/mediatek/mt8189/mt8189-afe-clk.c
Normal file
@@ -0,0 +1,750 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* mt8189-afe-clk.c -- Mediatek 8189 afe clock ctrl
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include "mt8189-afe-common.h"
|
||||
#include "mt8189-afe-clk.h"
|
||||
|
||||
/* mck */
|
||||
struct mt8189_mck_div {
|
||||
int m_sel_id;
|
||||
int div_clk_id;
|
||||
};
|
||||
|
||||
static const struct mt8189_mck_div mck_div[MT8189_MCK_NUM] = {
|
||||
[MT8189_I2SIN0_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_I2SIN0_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SIN0,
|
||||
},
|
||||
[MT8189_I2SIN1_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_I2SIN1_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SIN1,
|
||||
},
|
||||
[MT8189_I2SOUT0_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_I2SOUT0_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SOUT0,
|
||||
},
|
||||
[MT8189_I2SOUT1_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_I2SOUT1_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_I2SOUT1,
|
||||
},
|
||||
[MT8189_FMI2S_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_FMI2S_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_FMI2S,
|
||||
},
|
||||
[MT8189_TDMOUT_MCK] = {
|
||||
.m_sel_id = MT8189_CLK_TOP_TDMOUT_M_SEL,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M,
|
||||
},
|
||||
[MT8189_TDMOUT_BCK] = {
|
||||
.m_sel_id = -1,
|
||||
.div_clk_id = MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *aud_clks[MT8189_CLK_NUM] = {
|
||||
[MT8189_CLK_TOP_MUX_AUDIOINTBUS] = "top_aud_intbus",
|
||||
[MT8189_CLK_TOP_MUX_AUD_ENG1] = "top_aud_eng1",
|
||||
[MT8189_CLK_TOP_MUX_AUD_ENG2] = "top_aud_eng2",
|
||||
[MT8189_CLK_TOP_MUX_AUDIO_H] = "top_aud_h",
|
||||
/* pll */
|
||||
[MT8189_CLK_TOP_APLL1_CK] = "apll1",
|
||||
[MT8189_CLK_TOP_APLL2_CK] = "apll2",
|
||||
/* divider */
|
||||
[MT8189_CLK_TOP_APLL1_D4] = "apll1_d4",
|
||||
[MT8189_CLK_TOP_APLL2_D4] = "apll2_d4",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_I2SIN0] = "apll12_div_i2sin0",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_I2SIN1] = "apll12_div_i2sin1",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_I2SOUT0] = "apll12_div_i2sout0",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_I2SOUT1] = "apll12_div_i2sout1",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_FMI2S] = "apll12_div_fmi2s",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M] = "apll12_div_tdmout_m",
|
||||
[MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B] = "apll12_div_tdmout_b",
|
||||
/* mux */
|
||||
[MT8189_CLK_TOP_MUX_AUD_1] = "top_apll1",
|
||||
[MT8189_CLK_TOP_MUX_AUD_2] = "top_apll2",
|
||||
[MT8189_CLK_TOP_I2SIN0_M_SEL] = "top_i2sin0",
|
||||
[MT8189_CLK_TOP_I2SIN1_M_SEL] = "top_i2sin1",
|
||||
[MT8189_CLK_TOP_I2SOUT0_M_SEL] = "top_i2sout0",
|
||||
[MT8189_CLK_TOP_I2SOUT1_M_SEL] = "top_i2sout1",
|
||||
[MT8189_CLK_TOP_FMI2S_M_SEL] = "top_fmi2s",
|
||||
[MT8189_CLK_TOP_TDMOUT_M_SEL] = "top_dptx",
|
||||
/* top 26m*/
|
||||
[MT8189_CLK_TOP_CLK26M] = "clk26m",
|
||||
/* peri */
|
||||
[MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI] = "aud_slv_ck_peri",
|
||||
[MT8189_CLK_PERAO_AUDIO_MST_CK_PERI] = "aud_mst_ck_peri",
|
||||
[MT8189_CLK_PERAO_INTBUS_CK_PERI] = "aud_intbus_ck_peri",
|
||||
};
|
||||
|
||||
int mt8189_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
dev_err(afe->dev, "failed to enable clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt8189_afe_enable_clk);
|
||||
|
||||
void mt8189_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
|
||||
{
|
||||
if (clk)
|
||||
clk_disable_unprepare(clk);
|
||||
else
|
||||
dev_dbg(afe->dev, "NULL clk\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt8189_afe_disable_clk);
|
||||
|
||||
static int mt8189_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
|
||||
unsigned int rate)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (clk) {
|
||||
ret = clk_set_rate(clk, rate);
|
||||
if (ret) {
|
||||
dev_err(afe->dev, "failed to set clk rate\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt8189_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
|
||||
struct clk *parent)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (clk && parent) {
|
||||
ret = clk_set_parent(clk, parent);
|
||||
if (ret) {
|
||||
dev_dbg(afe->dev, "failed to set clk parent %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_top_cg_reg(unsigned int cg_type)
|
||||
{
|
||||
switch (cg_type) {
|
||||
case MT8189_AUDIO_26M_EN_ON:
|
||||
case MT8189_AUDIO_F3P25M_EN_ON:
|
||||
case MT8189_AUDIO_APLL1_EN_ON:
|
||||
case MT8189_AUDIO_APLL2_EN_ON:
|
||||
return AUDIO_ENGEN_CON0;
|
||||
case MT8189_CG_AUDIO_HOPPING_CK:
|
||||
case MT8189_CG_AUDIO_F26M_CK:
|
||||
case MT8189_CG_APLL1_CK:
|
||||
case MT8189_CG_APLL2_CK:
|
||||
case MT8189_PDN_APLL_TUNER2:
|
||||
case MT8189_PDN_APLL_TUNER1:
|
||||
return AUDIO_TOP_CON4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_top_cg_mask(unsigned int cg_type)
|
||||
{
|
||||
switch (cg_type) {
|
||||
case MT8189_AUDIO_26M_EN_ON:
|
||||
return AUDIO_26M_EN_ON_MASK_SFT;
|
||||
case MT8189_AUDIO_F3P25M_EN_ON:
|
||||
return AUDIO_F3P25M_EN_ON_MASK_SFT;
|
||||
case MT8189_AUDIO_APLL1_EN_ON:
|
||||
return AUDIO_APLL1_EN_ON_MASK_SFT;
|
||||
case MT8189_AUDIO_APLL2_EN_ON:
|
||||
return AUDIO_APLL2_EN_ON_MASK_SFT;
|
||||
case MT8189_CG_AUDIO_HOPPING_CK:
|
||||
return CG_AUDIO_HOPPING_CK_MASK_SFT;
|
||||
case MT8189_CG_AUDIO_F26M_CK:
|
||||
return CG_AUDIO_F26M_CK_MASK_SFT;
|
||||
case MT8189_CG_APLL1_CK:
|
||||
return CG_APLL1_CK_MASK_SFT;
|
||||
case MT8189_CG_APLL2_CK:
|
||||
return CG_APLL2_CK_MASK_SFT;
|
||||
case MT8189_PDN_APLL_TUNER2:
|
||||
return PDN_APLL_TUNER2_MASK_SFT;
|
||||
case MT8189_PDN_APLL_TUNER1:
|
||||
return PDN_APLL_TUNER1_MASK_SFT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_top_cg_on_val(unsigned int cg_type)
|
||||
{
|
||||
switch (cg_type) {
|
||||
case MT8189_AUDIO_26M_EN_ON:
|
||||
case MT8189_AUDIO_F3P25M_EN_ON:
|
||||
case MT8189_AUDIO_APLL1_EN_ON:
|
||||
case MT8189_AUDIO_APLL2_EN_ON:
|
||||
return get_top_cg_mask(cg_type);
|
||||
case MT8189_CG_AUDIO_HOPPING_CK:
|
||||
case MT8189_CG_AUDIO_F26M_CK:
|
||||
case MT8189_CG_APLL1_CK:
|
||||
case MT8189_CG_APLL2_CK:
|
||||
case MT8189_PDN_APLL_TUNER2:
|
||||
case MT8189_PDN_APLL_TUNER1:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_top_cg_off_val(unsigned int cg_type)
|
||||
{
|
||||
switch (cg_type) {
|
||||
case MT8189_AUDIO_26M_EN_ON:
|
||||
case MT8189_AUDIO_F3P25M_EN_ON:
|
||||
case MT8189_AUDIO_APLL1_EN_ON:
|
||||
case MT8189_AUDIO_APLL2_EN_ON:
|
||||
return 0;
|
||||
case MT8189_CG_AUDIO_HOPPING_CK:
|
||||
case MT8189_CG_AUDIO_F26M_CK:
|
||||
case MT8189_CG_APLL1_CK:
|
||||
case MT8189_CG_APLL2_CK:
|
||||
case MT8189_PDN_APLL_TUNER2:
|
||||
case MT8189_PDN_APLL_TUNER1:
|
||||
return get_top_cg_mask(cg_type);
|
||||
default:
|
||||
return get_top_cg_mask(cg_type);
|
||||
}
|
||||
}
|
||||
|
||||
static int mt8189_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
|
||||
{
|
||||
unsigned int reg = get_top_cg_reg(cg_type);
|
||||
unsigned int mask = get_top_cg_mask(cg_type);
|
||||
unsigned int val = get_top_cg_on_val(cg_type);
|
||||
|
||||
if (!afe->regmap) {
|
||||
dev_err(afe->dev, "afe regmap is null !!!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
|
||||
|
||||
return regmap_update_bits(afe->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static void mt8189_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
|
||||
{
|
||||
unsigned int reg = get_top_cg_reg(cg_type);
|
||||
unsigned int mask = get_top_cg_mask(cg_type);
|
||||
unsigned int val = get_top_cg_off_val(cg_type);
|
||||
|
||||
if (!afe->regmap) {
|
||||
dev_warn(afe->dev, "skip regmap\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
|
||||
regmap_update_bits(afe->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int ret;
|
||||
|
||||
dev_dbg(afe->dev, "enable: %d\n", enable);
|
||||
|
||||
if (enable) {
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud1_parent_err;
|
||||
|
||||
/* 180.6336 / 4 = 45.1584MHz */
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_eng1_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL1_D4]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_eng1_parent_err;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_audio_h_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_audio_h_parent_err;
|
||||
} else {
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
|
||||
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
clk_ck_mux_audio_h_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
clk_ck_mux_audio_h_err:
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
clk_ck_mux_eng1_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG1]);
|
||||
clk_ck_mux_eng1_err:
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
clk_ck_mux_aud1_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int ret;
|
||||
|
||||
dev_dbg(afe->dev, "enable: %d\n", enable);
|
||||
|
||||
if (enable) {
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL2_CK]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud2_parent_err;
|
||||
|
||||
/* 196.608 / 4 = 49.152MHz */
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_eng2_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL2_D4]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_eng2_parent_err;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_audio_h_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL2_CK]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_audio_h_parent_err;
|
||||
} else {
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
|
||||
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
clk_ck_mux_audio_h_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
clk_ck_mux_audio_h_err:
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
clk_ck_mux_eng2_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_ENG2]);
|
||||
clk_ck_mux_eng2_err:
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
clk_ck_mux_aud2_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt8189_afe_disable_apll(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int ret;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud1_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud1_parent_err;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud2_err;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
if (ret)
|
||||
goto clk_ck_mux_aud2_parent_err;
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
|
||||
return 0;
|
||||
|
||||
clk_ck_mux_aud2_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_2]);
|
||||
clk_ck_mux_aud2_err:
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1],
|
||||
afe_priv->clk[MT8189_CLK_TOP_APLL1_CK]);
|
||||
clk_ck_mux_aud1_parent_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUD_1]);
|
||||
clk_ck_mux_aud1_err:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt8189_apll1_enable(struct mtk_base_afe *afe)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* setting for APLL */
|
||||
ret = apll1_mux_setting(afe, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_CG_APLL1_CK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_PDN_APLL_TUNER1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* sel 44.1kHz:1, apll_div:7, upper bound:3 */
|
||||
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
|
||||
XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT |
|
||||
UPPER_BOUND_MASK_SFT,
|
||||
(0x1 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
|
||||
(3 << UPPER_BOUND_SFT));
|
||||
|
||||
/* apll1 freq tuner enable */
|
||||
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
|
||||
FREQ_TUNER_EN_MASK_SFT,
|
||||
0x1 << FREQ_TUNER_EN_SFT);
|
||||
|
||||
/* audio apll1 on */
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_APLL1_EN_ON);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt8189_apll1_disable(struct mtk_base_afe *afe)
|
||||
{
|
||||
/* audio apll1 off */
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_APLL1_EN_ON);
|
||||
|
||||
/* apll1 freq tuner disable */
|
||||
regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
|
||||
FREQ_TUNER_EN_MASK_SFT,
|
||||
0x0);
|
||||
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_PDN_APLL_TUNER1);
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_CG_APLL1_CK);
|
||||
apll1_mux_setting(afe, false);
|
||||
}
|
||||
|
||||
int mt8189_apll2_enable(struct mtk_base_afe *afe)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* setting for APLL */
|
||||
ret = apll2_mux_setting(afe, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_CG_APLL2_CK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_PDN_APLL_TUNER2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* sel 48kHz: 2, apll_div: 7, upper bound: 3*/
|
||||
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
|
||||
XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT |
|
||||
UPPER_BOUND_MASK_SFT,
|
||||
(0x2 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
|
||||
(3 << UPPER_BOUND_SFT));
|
||||
|
||||
/* apll2 freq tuner enable */
|
||||
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
|
||||
FREQ_TUNER_EN_MASK_SFT,
|
||||
0x1 << FREQ_TUNER_EN_SFT);
|
||||
|
||||
/* audio apll2 on */
|
||||
ret = mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_APLL2_EN_ON);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt8189_apll2_disable(struct mtk_base_afe *afe)
|
||||
{
|
||||
/* audio apll2 off */
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_APLL2_EN_ON);
|
||||
|
||||
/* apll2 freq tuner disable */
|
||||
regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
|
||||
FREQ_TUNER_EN_MASK_SFT,
|
||||
0x0);
|
||||
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_PDN_APLL_TUNER2);
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_CG_APLL2_CK);
|
||||
apll2_mux_setting(afe, false);
|
||||
}
|
||||
|
||||
int mt8189_get_apll_rate(struct mtk_base_afe *afe, int apll)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int clk_id;
|
||||
|
||||
if (apll < MT8189_APLL1 || apll > MT8189_APLL2) {
|
||||
dev_warn(afe->dev, "invalid clk id %d\n", apll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (apll == MT8189_APLL1)
|
||||
clk_id = MT8189_CLK_TOP_APLL1_CK;
|
||||
else
|
||||
clk_id = MT8189_CLK_TOP_APLL2_CK;
|
||||
|
||||
return clk_get_rate(afe_priv->clk[clk_id]);
|
||||
}
|
||||
|
||||
int mt8189_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
|
||||
{
|
||||
return (rate % 8000) ? MT8189_APLL1 : MT8189_APLL2;
|
||||
}
|
||||
|
||||
int mt8189_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
|
||||
{
|
||||
if (strcmp(name, APLL1_W_NAME) == 0)
|
||||
return MT8189_APLL1;
|
||||
|
||||
return MT8189_APLL2;
|
||||
}
|
||||
|
||||
int mt8189_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int apll = mt8189_get_apll_by_rate(afe, rate);
|
||||
int apll_clk_id = apll == MT8189_APLL1 ?
|
||||
MT8189_CLK_TOP_MUX_AUD_1 : MT8189_CLK_TOP_MUX_AUD_2;
|
||||
int m_sel_id;
|
||||
int div_clk_id;
|
||||
int ret;
|
||||
|
||||
dev_dbg(afe->dev, "mck_id: %d, rate: %d\n", mck_id, rate);
|
||||
|
||||
if (mck_id >= MT8189_MCK_NUM || mck_id < 0)
|
||||
return -EINVAL;
|
||||
|
||||
m_sel_id = mck_div[mck_id].m_sel_id;
|
||||
div_clk_id = mck_div[mck_id].div_clk_id;
|
||||
|
||||
/* select apll */
|
||||
if (m_sel_id >= 0) {
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[m_sel_id]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_set_clk_parent(afe, afe_priv->clk[m_sel_id],
|
||||
afe_priv->clk[apll_clk_id]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable div, set rate */
|
||||
if (div_clk_id < 0) {
|
||||
dev_err(afe->dev, "invalid div_clk_id %d\n", div_clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[div_clk_id]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt8189_mck_disable(struct mtk_base_afe *afe, int mck_id)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int m_sel_id;
|
||||
int div_clk_id;
|
||||
|
||||
dev_dbg(afe->dev, "mck_id: %d.\n", mck_id);
|
||||
|
||||
if (mck_id < 0) {
|
||||
dev_err(afe->dev, "mck_id = %d < 0\n", mck_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
m_sel_id = mck_div[mck_id].m_sel_id;
|
||||
div_clk_id = mck_div[mck_id].div_clk_id;
|
||||
|
||||
if (div_clk_id < 0) {
|
||||
dev_err(afe->dev, "div_clk_id = %d < 0\n",
|
||||
div_clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[div_clk_id]);
|
||||
|
||||
if (m_sel_id >= 0)
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[m_sel_id]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt8189_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
|
||||
/* bus clock for AFE internal access, like AFE SRAM */
|
||||
mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS]);
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
/* enable audio clock source */
|
||||
mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
mt8189_afe_set_clk_parent(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H],
|
||||
afe_priv->clk[MT8189_CLK_TOP_CLK26M]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt8189_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIO_H]);
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_TOP_MUX_AUDIOINTBUS]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt8189_afe_enable_main_clock(struct mtk_base_afe *afe)
|
||||
{
|
||||
return mt8189_afe_enable_top_cg(afe, MT8189_AUDIO_26M_EN_ON);
|
||||
}
|
||||
|
||||
void mt8189_afe_disable_main_clock(struct mtk_base_afe *afe)
|
||||
{
|
||||
mt8189_afe_disable_top_cg(afe, MT8189_AUDIO_26M_EN_ON);
|
||||
}
|
||||
|
||||
static int mt8189_afe_enable_ao_clock(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int ret;
|
||||
|
||||
/* Peri clock AO enable */
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_INTBUS_CK_PERI]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI]);
|
||||
if (ret)
|
||||
goto err_clk_perao_slv;
|
||||
|
||||
ret = mt8189_afe_enable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_MST_CK_PERI]);
|
||||
if (ret)
|
||||
goto err_clk_perao_mst;
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_perao_mst:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI]);
|
||||
err_clk_perao_slv:
|
||||
mt8189_afe_disable_clk(afe, afe_priv->clk[MT8189_CLK_PERAO_INTBUS_CK_PERI]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt8189_init_clock(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
afe_priv->clk = devm_kcalloc(afe->dev, MT8189_CLK_NUM, sizeof(*afe_priv->clk),
|
||||
GFP_KERNEL);
|
||||
if (!afe_priv->clk)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < MT8189_CLK_NUM; i++) {
|
||||
afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
|
||||
if (IS_ERR(afe_priv->clk[i])) {
|
||||
dev_err(afe->dev, "devm_clk_get %s fail\n", aud_clks[i]);
|
||||
return PTR_ERR(afe_priv->clk[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt8189_afe_disable_apll(afe);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt8189_afe_enable_ao_clock(afe);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
76
sound/soc/mediatek/mt8189/mt8189-afe-clk.h
Normal file
76
sound/soc/mediatek/mt8189/mt8189-afe-clk.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mt8189-afe-clk.h -- Mediatek 8189 afe clock ctrl definition
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MT8189_AFE_CLOCK_CTRL_H_
|
||||
#define _MT8189_AFE_CLOCK_CTRL_H_
|
||||
|
||||
/* APLL */
|
||||
#define APLL1_W_NAME "APLL1"
|
||||
#define APLL2_W_NAME "APLL2"
|
||||
|
||||
enum {
|
||||
MT8189_APLL1,
|
||||
MT8189_APLL2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT8189_CLK_TOP_MUX_AUDIOINTBUS,
|
||||
MT8189_CLK_TOP_MUX_AUD_ENG1,
|
||||
MT8189_CLK_TOP_MUX_AUD_ENG2,
|
||||
MT8189_CLK_TOP_MUX_AUDIO_H,
|
||||
/* pll */
|
||||
MT8189_CLK_TOP_APLL1_CK,
|
||||
MT8189_CLK_TOP_APLL2_CK,
|
||||
/* divider */
|
||||
MT8189_CLK_TOP_APLL1_D4,
|
||||
MT8189_CLK_TOP_APLL2_D4,
|
||||
MT8189_CLK_TOP_APLL12_DIV_I2SIN0,
|
||||
MT8189_CLK_TOP_APLL12_DIV_I2SIN1,
|
||||
MT8189_CLK_TOP_APLL12_DIV_I2SOUT0,
|
||||
MT8189_CLK_TOP_APLL12_DIV_I2SOUT1,
|
||||
MT8189_CLK_TOP_APLL12_DIV_FMI2S,
|
||||
MT8189_CLK_TOP_APLL12_DIV_TDMOUT_M,
|
||||
MT8189_CLK_TOP_APLL12_DIV_TDMOUT_B,
|
||||
/* mux */
|
||||
MT8189_CLK_TOP_MUX_AUD_1,
|
||||
MT8189_CLK_TOP_MUX_AUD_2,
|
||||
MT8189_CLK_TOP_I2SIN0_M_SEL,
|
||||
MT8189_CLK_TOP_I2SIN1_M_SEL,
|
||||
MT8189_CLK_TOP_I2SOUT0_M_SEL,
|
||||
MT8189_CLK_TOP_I2SOUT1_M_SEL,
|
||||
MT8189_CLK_TOP_FMI2S_M_SEL,
|
||||
MT8189_CLK_TOP_TDMOUT_M_SEL,
|
||||
/* top 26m */
|
||||
MT8189_CLK_TOP_CLK26M,
|
||||
/* peri */
|
||||
MT8189_CLK_PERAO_AUDIO_SLV_CK_PERI,
|
||||
MT8189_CLK_PERAO_AUDIO_MST_CK_PERI,
|
||||
MT8189_CLK_PERAO_INTBUS_CK_PERI,
|
||||
MT8189_CLK_NUM,
|
||||
};
|
||||
|
||||
struct mtk_base_afe;
|
||||
|
||||
int mt8189_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
|
||||
int mt8189_mck_disable(struct mtk_base_afe *afe, int mck_id);
|
||||
int mt8189_get_apll_rate(struct mtk_base_afe *afe, int apll);
|
||||
int mt8189_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
|
||||
int mt8189_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
|
||||
int mt8189_init_clock(struct mtk_base_afe *afe);
|
||||
int mt8189_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
|
||||
void mt8189_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
|
||||
int mt8189_apll1_enable(struct mtk_base_afe *afe);
|
||||
void mt8189_apll1_disable(struct mtk_base_afe *afe);
|
||||
int mt8189_apll2_enable(struct mtk_base_afe *afe);
|
||||
void mt8189_apll2_disable(struct mtk_base_afe *afe);
|
||||
int mt8189_afe_enable_main_clock(struct mtk_base_afe *afe);
|
||||
void mt8189_afe_disable_main_clock(struct mtk_base_afe *afe);
|
||||
int mt8189_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
|
||||
int mt8189_afe_disable_reg_rw_clk(struct mtk_base_afe *afe);
|
||||
|
||||
#endif
|
||||
240
sound/soc/mediatek/mt8189/mt8189-afe-common.h
Normal file
240
sound/soc/mediatek/mt8189/mt8189-afe-common.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mt8189-afe-common.h -- Mediatek 8189 audio driver definitions
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MT_8189_AFE_COMMON_H_
|
||||
#define _MT_8189_AFE_COMMON_H_
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "mt8189-reg.h"
|
||||
#include "../common/mtk-base-afe.h"
|
||||
|
||||
enum {
|
||||
MTK_AFE_RATE_8K,
|
||||
MTK_AFE_RATE_11K,
|
||||
MTK_AFE_RATE_12K,
|
||||
MTK_AFE_RATE_384K,
|
||||
MTK_AFE_RATE_16K,
|
||||
MTK_AFE_RATE_22K,
|
||||
MTK_AFE_RATE_24K,
|
||||
MTK_AFE_RATE_352K,
|
||||
MTK_AFE_RATE_32K,
|
||||
MTK_AFE_RATE_44K,
|
||||
MTK_AFE_RATE_48K,
|
||||
MTK_AFE_RATE_88K,
|
||||
MTK_AFE_RATE_96K,
|
||||
MTK_AFE_RATE_176K,
|
||||
MTK_AFE_RATE_192K,
|
||||
MTK_AFE_RATE_260K,
|
||||
};
|
||||
|
||||
/* HW IPM 2.0 */
|
||||
enum {
|
||||
MTK_AFE_IPM2P0_RATE_8K = 0x0,
|
||||
MTK_AFE_IPM2P0_RATE_11K = 0x1,
|
||||
MTK_AFE_IPM2P0_RATE_12K = 0x2,
|
||||
MTK_AFE_IPM2P0_RATE_16K = 0x4,
|
||||
MTK_AFE_IPM2P0_RATE_22K = 0x5,
|
||||
MTK_AFE_IPM2P0_RATE_24K = 0x6,
|
||||
MTK_AFE_IPM2P0_RATE_32K = 0x8,
|
||||
MTK_AFE_IPM2P0_RATE_44K = 0x9,
|
||||
MTK_AFE_IPM2P0_RATE_48K = 0xa,
|
||||
MTK_AFE_IPM2P0_RATE_88K = 0xd,
|
||||
MTK_AFE_IPM2P0_RATE_96K = 0xe,
|
||||
MTK_AFE_IPM2P0_RATE_176K = 0x11,
|
||||
MTK_AFE_IPM2P0_RATE_192K = 0x12,
|
||||
MTK_AFE_IPM2P0_RATE_352K = 0x15,
|
||||
MTK_AFE_IPM2P0_RATE_384K = 0x16,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_DAI_MEMIF_RATE_8K,
|
||||
MTK_AFE_DAI_MEMIF_RATE_16K,
|
||||
MTK_AFE_DAI_MEMIF_RATE_32K,
|
||||
MTK_AFE_DAI_MEMIF_RATE_48K,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_PCM_RATE_8K,
|
||||
MTK_AFE_PCM_RATE_16K,
|
||||
MTK_AFE_PCM_RATE_32K,
|
||||
MTK_AFE_PCM_RATE_48K,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTKAIF_PROTOCOL_1,
|
||||
MTKAIF_PROTOCOL_2,
|
||||
MTKAIF_PROTOCOL_2_CLK_P2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT8189_MEMIF_DL0,
|
||||
MT8189_MEMIF_DL1,
|
||||
MT8189_MEMIF_DL2,
|
||||
MT8189_MEMIF_DL3,
|
||||
MT8189_MEMIF_DL4,
|
||||
MT8189_MEMIF_DL5,
|
||||
MT8189_MEMIF_DL6,
|
||||
MT8189_MEMIF_DL7,
|
||||
MT8189_MEMIF_DL8,
|
||||
MT8189_MEMIF_DL23,
|
||||
MT8189_MEMIF_DL24,
|
||||
MT8189_MEMIF_DL25,
|
||||
MT8189_MEMIF_DL_24CH,
|
||||
MT8189_MEMIF_VUL0,
|
||||
MT8189_MEMIF_VUL1,
|
||||
MT8189_MEMIF_VUL2,
|
||||
MT8189_MEMIF_VUL3,
|
||||
MT8189_MEMIF_VUL4,
|
||||
MT8189_MEMIF_VUL5,
|
||||
MT8189_MEMIF_VUL6,
|
||||
MT8189_MEMIF_VUL7,
|
||||
MT8189_MEMIF_VUL8,
|
||||
MT8189_MEMIF_VUL9,
|
||||
MT8189_MEMIF_VUL10,
|
||||
MT8189_MEMIF_VUL24,
|
||||
MT8189_MEMIF_VUL25,
|
||||
MT8189_MEMIF_VUL_CM0,
|
||||
MT8189_MEMIF_VUL_CM1,
|
||||
MT8189_MEMIF_ETDM_IN0,
|
||||
MT8189_MEMIF_ETDM_IN1,
|
||||
MT8189_MEMIF_HDMI,
|
||||
MT8189_MEMIF_NUM,
|
||||
MT8189_DAI_ADDA = MT8189_MEMIF_NUM,
|
||||
MT8189_DAI_ADDA_CH34,
|
||||
MT8189_DAI_ADDA_CH56,
|
||||
MT8189_DAI_AP_DMIC,
|
||||
MT8189_DAI_AP_DMIC_CH34,
|
||||
MT8189_DAI_I2S_IN0,
|
||||
MT8189_DAI_I2S_IN1,
|
||||
MT8189_DAI_I2S_OUT0,
|
||||
MT8189_DAI_I2S_OUT1,
|
||||
MT8189_DAI_I2S_OUT4,
|
||||
MT8189_DAI_PCM_0,
|
||||
MT8189_DAI_TDM,
|
||||
MT8189_DAI_TDM_DPTX,
|
||||
MT8189_DAI_NUM,
|
||||
};
|
||||
|
||||
/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
|
||||
enum {
|
||||
MT8189_IRQ_0,
|
||||
MT8189_IRQ_1,
|
||||
MT8189_IRQ_2,
|
||||
MT8189_IRQ_3,
|
||||
MT8189_IRQ_4,
|
||||
MT8189_IRQ_5,
|
||||
MT8189_IRQ_6,
|
||||
MT8189_IRQ_7,
|
||||
MT8189_IRQ_8,
|
||||
MT8189_IRQ_9,
|
||||
MT8189_IRQ_10,
|
||||
MT8189_IRQ_11,
|
||||
MT8189_IRQ_12,
|
||||
MT8189_IRQ_13,
|
||||
MT8189_IRQ_14,
|
||||
MT8189_IRQ_15,
|
||||
MT8189_IRQ_16,
|
||||
MT8189_IRQ_17,
|
||||
MT8189_IRQ_18,
|
||||
MT8189_IRQ_19,
|
||||
MT8189_IRQ_20,
|
||||
MT8189_IRQ_21,
|
||||
MT8189_IRQ_22,
|
||||
MT8189_IRQ_23,
|
||||
MT8189_IRQ_24,
|
||||
MT8189_IRQ_25,
|
||||
MT8189_IRQ_26,
|
||||
MT8189_IRQ_31,
|
||||
MT8189_IRQ_NUM,
|
||||
};
|
||||
|
||||
/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
|
||||
enum {
|
||||
MT8189_CUS_IRQ_TDM, /* used only for TDM */
|
||||
MT8189_CUS_IRQ_NUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* AUDIO_ENGEN_CON0 */
|
||||
MT8189_AUDIO_26M_EN_ON,
|
||||
MT8189_AUDIO_F3P25M_EN_ON,
|
||||
MT8189_AUDIO_APLL1_EN_ON,
|
||||
MT8189_AUDIO_APLL2_EN_ON,
|
||||
MT8189_AUDIO_F26M_EN_RST,
|
||||
MT8189_MULTI_USER_RST,
|
||||
MT8189_MULTI_USER_BYPASS,
|
||||
/* AUDIO_TOP_CON4 */
|
||||
MT8189_CG_AUDIO_HOPPING_CK,
|
||||
MT8189_CG_AUDIO_F26M_CK,
|
||||
MT8189_CG_APLL1_CK,
|
||||
MT8189_CG_APLL2_CK,
|
||||
MT8189_PDN_APLL_TUNER2,
|
||||
MT8189_PDN_APLL_TUNER1,
|
||||
MT8189_AUDIO_CG_NUM,
|
||||
};
|
||||
|
||||
/* MCLK */
|
||||
enum {
|
||||
MT8189_I2SIN0_MCK,
|
||||
MT8189_I2SIN1_MCK,
|
||||
MT8189_I2SOUT0_MCK,
|
||||
MT8189_I2SOUT1_MCK,
|
||||
MT8189_FMI2S_MCK,
|
||||
MT8189_TDMOUT_MCK,
|
||||
MT8189_TDMOUT_BCK,
|
||||
MT8189_MCK_NUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
CM0,
|
||||
CM1,
|
||||
CM_NUM,
|
||||
};
|
||||
|
||||
struct clk;
|
||||
|
||||
struct mt8189_afe_private {
|
||||
struct clk **clk;
|
||||
struct regmap *pmic_regmap;
|
||||
|
||||
/* dai */
|
||||
void *dai_priv[MT8189_DAI_NUM];
|
||||
|
||||
/* adda */
|
||||
int mtkaif_protocol;
|
||||
int mtkaif_chosen_phase[4];
|
||||
int mtkaif_phase_cycle[4];
|
||||
int mtkaif_calibration_num_phase;
|
||||
int mtkaif_dmic;
|
||||
int mtkaif_dmic_ch34;
|
||||
|
||||
/* add for vs1 voter */
|
||||
bool is_adda_dl_on;
|
||||
bool is_adda_ul_on;
|
||||
/* adda dl vol idx is at maximum */
|
||||
bool is_adda_dl_max_vol;
|
||||
/* current vote status of vs1 */
|
||||
bool is_mt6363_vote;
|
||||
|
||||
/* mck */
|
||||
int mck_rate[MT8189_MCK_NUM];
|
||||
|
||||
/* channel merge */
|
||||
unsigned int cm_rate[CM_NUM];
|
||||
unsigned int cm_channels;
|
||||
};
|
||||
|
||||
int mt8189_dai_adda_register(struct mtk_base_afe *afe);
|
||||
int mt8189_dai_i2s_register(struct mtk_base_afe *afe);
|
||||
int mt8189_dai_pcm_register(struct mtk_base_afe *afe);
|
||||
int mt8189_dai_tdm_register(struct mtk_base_afe *afe);
|
||||
|
||||
#endif
|
||||
2617
sound/soc/mediatek/mt8189/mt8189-afe-pcm.c
Normal file
2617
sound/soc/mediatek/mt8189/mt8189-afe-pcm.c
Normal file
File diff suppressed because it is too large
Load Diff
1228
sound/soc/mediatek/mt8189/mt8189-dai-adda.c
Normal file
1228
sound/soc/mediatek/mt8189/mt8189-dai-adda.c
Normal file
File diff suppressed because it is too large
Load Diff
1463
sound/soc/mediatek/mt8189/mt8189-dai-i2s.c
Normal file
1463
sound/soc/mediatek/mt8189/mt8189-dai-i2s.c
Normal file
File diff suppressed because it is too large
Load Diff
332
sound/soc/mediatek/mt8189/mt8189-dai-pcm.c
Normal file
332
sound/soc/mediatek/mt8189/mt8189-dai-pcm.c
Normal file
@@ -0,0 +1,332 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MediaTek ALSA SoC Audio DAI I2S Control
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include "mt8189-afe-common.h"
|
||||
#include "mt8189-interconnection.h"
|
||||
#include "mt8189-afe-clk.h"
|
||||
|
||||
enum AUD_TX_LCH_RPT {
|
||||
AUD_TX_LCH_RPT_NO_REPEAT,
|
||||
AUD_TX_LCH_RPT_REPEAT
|
||||
};
|
||||
|
||||
enum AUD_VBT_16K_MODE {
|
||||
AUD_VBT_16K_MODE_DISABLE,
|
||||
AUD_VBT_16K_MODE_ENABLE
|
||||
};
|
||||
|
||||
enum AUD_EXT_MODEM {
|
||||
AUD_EXT_MODEM_SELECT_INTERNAL,
|
||||
AUD_EXT_MODEM_SELECT_EXTERNAL
|
||||
};
|
||||
|
||||
enum AUD_PCM_SYNC_TYPE {
|
||||
/* bck sync length = 1 */
|
||||
AUD_PCM_ONE_BCK_CYCLE_SYNC,
|
||||
/* bck sync length = PCM_INTF_CON1[9:13] */
|
||||
AUD_PCM_EXTENDED_BCK_CYCLE_SYNC
|
||||
};
|
||||
|
||||
enum AUD_BT_MODE {
|
||||
AUD_BT_MODE_DUAL_MIC_ON_TX,
|
||||
AUD_BT_MODE_SINGLE_MIC_ON_TX
|
||||
};
|
||||
|
||||
enum AUD_PCM_AFIFO_SRC {
|
||||
/* slave mode & external modem uses different crystal */
|
||||
AUD_PCM_AFIFO_ASRC,
|
||||
/* slave mode & external modem uses the same crystal */
|
||||
AUD_PCM_AFIFO_AFIFO
|
||||
};
|
||||
|
||||
enum AUD_PCM_CLOCK_SOURCE {
|
||||
AUD_PCM_CLOCK_MASTER_MODE,
|
||||
AUD_PCM_CLOCK_SLAVE_MODE
|
||||
};
|
||||
|
||||
enum AUD_PCM_WLEN {
|
||||
AUD_PCM_WLEN_PCM_32_BCK_CYCLES,
|
||||
AUD_PCM_WLEN_PCM_64_BCK_CYCLES
|
||||
};
|
||||
|
||||
enum AUD_PCM_MODE {
|
||||
AUD_PCM_MODE_PCM_MODE_8K,
|
||||
AUD_PCM_MODE_PCM_MODE_16K,
|
||||
AUD_PCM_MODE_PCM_MODE_32K,
|
||||
AUD_PCM_MODE_PCM_MODE_48K
|
||||
};
|
||||
|
||||
enum AUD_PCM_FMT {
|
||||
AUD_PCM_FMT_I2S,
|
||||
AUD_PCM_FMT_EIAJ,
|
||||
AUD_PCM_FMT_PCM_MODE_A,
|
||||
AUD_PCM_FMT_PCM_MODE_B
|
||||
};
|
||||
|
||||
enum AUD_BCLK_OUT_INV {
|
||||
AUD_BCLK_OUT_INV_NO_INVERSE,
|
||||
AUD_BCLK_OUT_INV_INVERSE
|
||||
};
|
||||
|
||||
enum AUD_PCM_EN {
|
||||
AUD_PCM_EN_DISABLE,
|
||||
AUD_PCM_EN_ENABLE
|
||||
};
|
||||
|
||||
enum AUD_PCM1_1X_EN_DOMAIN {
|
||||
HOPPING_26M,
|
||||
APLL,
|
||||
SLAVE = 6
|
||||
};
|
||||
|
||||
enum AUD_PCM1_1X_EN_SLAVE_MODE {
|
||||
PCM0_SLAVE_1X_EN,
|
||||
PCM1_SLAVE_1X_EN
|
||||
};
|
||||
|
||||
enum {
|
||||
PCM_8K,
|
||||
PCM_16K = 4,
|
||||
PCM_32K = 8,
|
||||
PCM_48K = 10
|
||||
};
|
||||
|
||||
static unsigned int pcm_1x_rate_transform(struct device *dev,
|
||||
unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return PCM_8K;
|
||||
case 16000:
|
||||
return PCM_16K;
|
||||
case 32000:
|
||||
return PCM_32K;
|
||||
case 48000:
|
||||
return PCM_48K;
|
||||
default:
|
||||
dev_warn(dev, "rate %u invalid, use %d!!!\n",
|
||||
rate, PCM_48K);
|
||||
return PCM_48K;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int pcm_rate_transform(struct device *dev,
|
||||
unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return MTK_AFE_PCM_RATE_8K;
|
||||
case 16000:
|
||||
return MTK_AFE_PCM_RATE_16K;
|
||||
case 32000:
|
||||
return MTK_AFE_PCM_RATE_32K;
|
||||
case 48000:
|
||||
return MTK_AFE_PCM_RATE_48K;
|
||||
default:
|
||||
dev_warn(dev, "rate %u invalid, use %d\n",
|
||||
rate, MTK_AFE_PCM_RATE_48K);
|
||||
return MTK_AFE_PCM_RATE_48K;
|
||||
}
|
||||
}
|
||||
|
||||
/* dai component */
|
||||
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch1_mix[] = {
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN096_0,
|
||||
I_ADDA_UL_CH1, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN096_1,
|
||||
I_DL2_CH1, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN096_1,
|
||||
I_DL_24CH_CH1, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch2_mix[] = {
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN097_0,
|
||||
I_ADDA_UL_CH2, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN097_1,
|
||||
I_DL2_CH2, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN097_1,
|
||||
I_DL_24CH_CH2, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new mtk_pcm_0_playback_ch4_mix[] = {
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH1", AFE_CONN099_4,
|
||||
I_I2SIN1_CH1, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH2", AFE_CONN099_4,
|
||||
I_I2SIN1_CH2, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN099_1,
|
||||
I_DL0_CH1, 1, 0),
|
||||
SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN099_1,
|
||||
I_DL_24CH_CH1, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
|
||||
/* inter-connections */
|
||||
SND_SOC_DAPM_MIXER("PCM_0_PB_CH1", SND_SOC_NOPM, 0, 0,
|
||||
mtk_pcm_0_playback_ch1_mix,
|
||||
ARRAY_SIZE(mtk_pcm_0_playback_ch1_mix)),
|
||||
SND_SOC_DAPM_MIXER("PCM_0_PB_CH2", SND_SOC_NOPM, 0, 0,
|
||||
mtk_pcm_0_playback_ch2_mix,
|
||||
ARRAY_SIZE(mtk_pcm_0_playback_ch2_mix)),
|
||||
SND_SOC_DAPM_MIXER("PCM_0_PB_CH4", SND_SOC_NOPM, 0, 0,
|
||||
mtk_pcm_0_playback_ch4_mix,
|
||||
ARRAY_SIZE(mtk_pcm_0_playback_ch4_mix)),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("PCM_0_EN",
|
||||
AFE_PCM0_INTF_CON0, PCM0_EN_SFT, 0,
|
||||
NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("PCM0_CG", AUDIO_TOP_CON0, PDN_PCM0_SFT, 1,
|
||||
NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_INPUT("AFE_PCM_INPUT"),
|
||||
SND_SOC_DAPM_OUTPUT("AFE_PCM_OUTPUT"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
|
||||
{"PCM 0 Playback", NULL, "PCM_0_PB_CH1"},
|
||||
{"PCM 0 Playback", NULL, "PCM_0_PB_CH2"},
|
||||
{"PCM 0 Playback", NULL, "PCM_0_PB_CH4"},
|
||||
|
||||
{"PCM 0 Playback", NULL, "PCM_0_EN"},
|
||||
{"PCM 0 Capture", NULL, "PCM_0_EN"},
|
||||
{"PCM 0 Playback", NULL, "PCM0_CG"},
|
||||
{"PCM 0 Capture", NULL, "PCM0_CG"},
|
||||
|
||||
{"AFE_PCM_OUTPUT", NULL, "PCM 0 Playback"},
|
||||
{"PCM 0 Capture", NULL, "AFE_PCM_INPUT"},
|
||||
|
||||
{"PCM_0_PB_CH1", "DL2_CH1", "DL2"},
|
||||
{"PCM_0_PB_CH2", "DL2_CH2", "DL2"},
|
||||
{"PCM_0_PB_CH4", "DL0_CH1", "DL0"},
|
||||
|
||||
{"PCM_0_PB_CH1", "DL_24CH_CH1", "DL_24CH"},
|
||||
{"PCM_0_PB_CH2", "DL_24CH_CH2", "DL_24CH"},
|
||||
{"PCM_0_PB_CH4", "DL_24CH_CH1", "DL_24CH"},
|
||||
};
|
||||
|
||||
/* dai ops */
|
||||
static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int rate = params_rate(params);
|
||||
unsigned int rate_reg = pcm_rate_transform(afe->dev, rate);
|
||||
unsigned int x_rate_reg = pcm_1x_rate_transform(afe->dev, rate);
|
||||
unsigned int pcm_con0;
|
||||
unsigned int pcm_con1;
|
||||
unsigned int playback_active = 0;
|
||||
unsigned int capture_active = 0;
|
||||
struct snd_soc_dapm_widget *playback_widget =
|
||||
snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
struct snd_soc_dapm_widget *capture_widget =
|
||||
snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_CAPTURE);
|
||||
|
||||
if (playback_widget)
|
||||
playback_active = playback_widget->active;
|
||||
if (capture_widget)
|
||||
capture_active = capture_widget->active;
|
||||
dev_dbg(afe->dev,
|
||||
"id %d, stream %d, rate %d, rate_reg %d, active p %d, c %d\n",
|
||||
dai->id, substream->stream, rate, rate_reg,
|
||||
playback_active, capture_active);
|
||||
|
||||
if (playback_active || capture_active)
|
||||
return 0;
|
||||
switch (dai->id) {
|
||||
case MT8189_DAI_PCM_0:
|
||||
pcm_con0 = AUD_BCLK_OUT_INV_NO_INVERSE << PCM0_BCLK_OUT_INV_SFT;
|
||||
pcm_con0 |= AUD_TX_LCH_RPT_NO_REPEAT << PCM0_TX_LCH_RPT_SFT;
|
||||
pcm_con0 |= AUD_VBT_16K_MODE_DISABLE << PCM0_VBT_16K_MODE_SFT;
|
||||
pcm_con0 |= 0 << PCM0_SYNC_LENGTH_SFT;
|
||||
pcm_con0 |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM0_SYNC_TYPE_SFT;
|
||||
pcm_con0 |= AUD_PCM_AFIFO_AFIFO << PCM0_BYP_ASRC_SFT;
|
||||
pcm_con0 |= AUD_PCM_CLOCK_MASTER_MODE << PCM0_SLAVE_SFT;
|
||||
pcm_con0 |= rate_reg << PCM0_MODE_SFT;
|
||||
pcm_con0 |= AUD_PCM_FMT_I2S << PCM0_FMT_SFT;
|
||||
|
||||
pcm_con1 = AUD_EXT_MODEM_SELECT_INTERNAL << PCM0_EXT_MODEM_SFT;
|
||||
pcm_con1 |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM0_BT_MODE_SFT;
|
||||
pcm_con1 |= HOPPING_26M << PCM0_1X_EN_DOMAIN_SFT;
|
||||
pcm_con1 |= x_rate_reg << PCM0_1X_EN_MODE_SFT;
|
||||
|
||||
regmap_update_bits(afe->regmap, AFE_PCM0_INTF_CON0,
|
||||
~(unsigned int)PCM0_EN_MASK_SFT, pcm_con0);
|
||||
regmap_update_bits(afe->regmap, AFE_PCM0_INTF_CON1,
|
||||
AFE_PCM0_INTF_CON1_MASK_MON_MASK_SFT,
|
||||
pcm_con1);
|
||||
break;
|
||||
default:
|
||||
dev_err(afe->dev, "%s(), id %d not support\n",
|
||||
__func__, dai->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
|
||||
.hw_params = mtk_dai_pcm_hw_params,
|
||||
};
|
||||
|
||||
/* dai driver */
|
||||
#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
|
||||
SNDRV_PCM_RATE_16000 |\
|
||||
SNDRV_PCM_RATE_32000 |\
|
||||
SNDRV_PCM_RATE_48000)
|
||||
|
||||
#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
|
||||
{
|
||||
.name = "PCM 0",
|
||||
.id = MT8189_DAI_PCM_0,
|
||||
.playback = {
|
||||
.stream_name = "PCM 0 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = MTK_PCM_RATES,
|
||||
.formats = MTK_PCM_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "PCM 0 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = MTK_PCM_RATES,
|
||||
.formats = MTK_PCM_FORMATS,
|
||||
},
|
||||
.ops = &mtk_dai_pcm_ops,
|
||||
.symmetric_rate = 1,
|
||||
.symmetric_sample_bits = 1,
|
||||
},
|
||||
};
|
||||
|
||||
int mt8189_dai_pcm_register(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mtk_base_afe_dai *dai;
|
||||
|
||||
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
|
||||
if (!dai)
|
||||
return -ENOMEM;
|
||||
|
||||
dai->dai_drivers = mtk_dai_pcm_driver;
|
||||
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
|
||||
dai->dapm_widgets = mtk_dai_pcm_widgets;
|
||||
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
|
||||
dai->dapm_routes = mtk_dai_pcm_routes;
|
||||
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
|
||||
|
||||
list_add(&dai->list, &afe->sub_dais);
|
||||
|
||||
return 0;
|
||||
}
|
||||
672
sound/soc/mediatek/mt8189/mt8189-dai-tdm.c
Normal file
672
sound/soc/mediatek/mt8189/mt8189-dai-tdm.c
Normal file
@@ -0,0 +1,672 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MediaTek ALSA SoC Audio DAI TDM Control
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include "mt8189-afe-clk.h"
|
||||
#include "mt8189-afe-common.h"
|
||||
#include "mt8189-interconnection.h"
|
||||
|
||||
#define DPTX_CH_EN_MASK_2CH (0x3)
|
||||
#define DPTX_CH_EN_MASK_4CH (0xf)
|
||||
#define DPTX_CH_EN_MASK_6CH (0x3f)
|
||||
#define DPTX_CH_EN_MASK_8CH (0xff)
|
||||
|
||||
enum {
|
||||
SUPPLY_SEQ_APLL,
|
||||
SUPPLY_SEQ_TDM_MCK_EN,
|
||||
SUPPLY_SEQ_TDM_BCK_EN,
|
||||
SUPPLY_SEQ_TDM_DPTX_MCK_EN,
|
||||
SUPPLY_SEQ_TDM_DPTX_BCK_EN,
|
||||
SUPPLY_SEQ_TDM_CG_EN,
|
||||
};
|
||||
|
||||
enum {
|
||||
TDM_WLEN_8_BIT,
|
||||
TDM_WLEN_16_BIT,
|
||||
TDM_WLEN_24_BIT,
|
||||
TDM_WLEN_32_BIT,
|
||||
};
|
||||
|
||||
enum {
|
||||
TDM_CHANNEL_BCK_16,
|
||||
TDM_CHANNEL_BCK_24,
|
||||
TDM_CHANNEL_BCK_32
|
||||
};
|
||||
|
||||
enum {
|
||||
TDM_CHANNEL_NUM_2,
|
||||
TDM_CHANNEL_NUM_4,
|
||||
TDM_CHANNEL_NUM_8
|
||||
};
|
||||
|
||||
enum {
|
||||
TDM_CH_START_O30_O31,
|
||||
TDM_CH_START_O32_O33,
|
||||
TDM_CH_START_O34_O35,
|
||||
TDM_CH_START_O36_O37,
|
||||
TDM_CH_ZERO,
|
||||
};
|
||||
|
||||
enum {
|
||||
DPTX_CHANNEL_2,
|
||||
DPTX_CHANNEL_8,
|
||||
};
|
||||
|
||||
enum {
|
||||
DPTX_WLEN_24_BIT,
|
||||
DPTX_WLEN_16_BIT,
|
||||
};
|
||||
|
||||
struct mtk_afe_tdm_priv {
|
||||
int bck_id;
|
||||
int bck_rate;
|
||||
|
||||
int mclk_id;
|
||||
int mclk_multiple; /* according to sample rate */
|
||||
int mclk_rate;
|
||||
int mclk_apll;
|
||||
};
|
||||
|
||||
static unsigned int get_tdm_wlen(snd_pcm_format_t format)
|
||||
{
|
||||
return snd_pcm_format_physical_width(format) <= 16 ?
|
||||
TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
|
||||
}
|
||||
|
||||
static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
|
||||
{
|
||||
return snd_pcm_format_physical_width(format) <= 16 ?
|
||||
TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
|
||||
}
|
||||
|
||||
static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
|
||||
{
|
||||
return snd_pcm_format_physical_width(format) - 1;
|
||||
}
|
||||
|
||||
static unsigned int get_tdm_ch(unsigned int ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case 1:
|
||||
case 2:
|
||||
return TDM_CHANNEL_NUM_2;
|
||||
case 3:
|
||||
case 4:
|
||||
return TDM_CHANNEL_NUM_4;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
default:
|
||||
return TDM_CHANNEL_NUM_8;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_dptx_ch_enable_mask(unsigned int ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case 1:
|
||||
case 2:
|
||||
return DPTX_CH_EN_MASK_2CH;
|
||||
case 3:
|
||||
case 4:
|
||||
return DPTX_CH_EN_MASK_4CH;
|
||||
case 5:
|
||||
case 6:
|
||||
return DPTX_CH_EN_MASK_6CH;
|
||||
case 7:
|
||||
case 8:
|
||||
return DPTX_CH_EN_MASK_8CH;
|
||||
default:
|
||||
return DPTX_CH_EN_MASK_2CH;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_dptx_ch(unsigned int ch)
|
||||
{
|
||||
if (ch == 2)
|
||||
return DPTX_CHANNEL_2;
|
||||
|
||||
return DPTX_CHANNEL_8;
|
||||
}
|
||||
|
||||
static unsigned int get_dptx_wlen(snd_pcm_format_t format)
|
||||
{
|
||||
return snd_pcm_format_physical_width(format) <= 16 ?
|
||||
DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT;
|
||||
}
|
||||
|
||||
/* interconnection */
|
||||
enum {
|
||||
HDMI_CONN_CH0,
|
||||
HDMI_CONN_CH1,
|
||||
HDMI_CONN_CH2,
|
||||
HDMI_CONN_CH3,
|
||||
HDMI_CONN_CH4,
|
||||
HDMI_CONN_CH5,
|
||||
HDMI_CONN_CH6,
|
||||
HDMI_CONN_CH7,
|
||||
};
|
||||
|
||||
static const char *const hdmi_conn_mux_map[] = {
|
||||
"CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
|
||||
};
|
||||
|
||||
static int hdmi_conn_mux_map_value[] = {
|
||||
HDMI_CONN_CH0, HDMI_CONN_CH1, HDMI_CONN_CH2, HDMI_CONN_CH3,
|
||||
HDMI_CONN_CH4, HDMI_CONN_CH5, HDMI_CONN_CH6, HDMI_CONN_CH7,
|
||||
};
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_0_SFT,
|
||||
HDMI_O_0_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_1_SFT,
|
||||
HDMI_O_1_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_2_SFT,
|
||||
HDMI_O_2_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_3_SFT,
|
||||
HDMI_O_3_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_4_SFT,
|
||||
HDMI_O_4_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_5_SFT,
|
||||
HDMI_O_5_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_6_SFT,
|
||||
HDMI_O_6_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
|
||||
AFE_HDMI_CONN0,
|
||||
HDMI_O_7_SFT,
|
||||
HDMI_O_7_MASK,
|
||||
hdmi_conn_mux_map,
|
||||
hdmi_conn_mux_map_value);
|
||||
|
||||
static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
|
||||
SOC_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum),
|
||||
SOC_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum),
|
||||
};
|
||||
|
||||
static const char *const tdm_out_demux_texts[] = {
|
||||
"NONE", "TDMOUT", "DPTXOUT",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(tdm_out_demux_enum,
|
||||
SND_SOC_NOPM,
|
||||
0,
|
||||
tdm_out_demux_texts);
|
||||
|
||||
static const struct snd_kcontrol_new tdm_out_demux_control =
|
||||
SOC_DAPM_ENUM("TDM Playback Route", tdm_out_demux_enum);
|
||||
|
||||
static int get_tdm_id_by_name(const char *name)
|
||||
{
|
||||
if (strstr(name, "DPTX"))
|
||||
return MT8189_DAI_TDM_DPTX;
|
||||
|
||||
return MT8189_DAI_TDM;
|
||||
}
|
||||
|
||||
static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
|
||||
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, bck: %d\n",
|
||||
w->name, event, dai_id, tdm_priv->bck_rate);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
mt8189_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
mt8189_mck_disable(afe, tdm_priv->bck_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
|
||||
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, mclk %d\n",
|
||||
w->name, event, dai_id, tdm_priv->mclk_rate);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
mt8189_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
tdm_priv->mclk_rate = 0;
|
||||
mt8189_mck_disable(afe, tdm_priv->mclk_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
|
||||
SND_SOC_DAPM_DEMUX("TDM Playback Route", SND_SOC_NOPM, 0, 0,
|
||||
&tdm_out_demux_control),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
|
||||
SND_SOC_NOPM, 0, 0,
|
||||
mtk_tdm_bck_en_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
|
||||
SND_SOC_NOPM, 0, 0,
|
||||
mtk_tdm_mck_en_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN,
|
||||
SND_SOC_NOPM, 0, 0,
|
||||
mtk_tdm_bck_en_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_MCK_EN,
|
||||
SND_SOC_NOPM, 0, 0,
|
||||
mtk_tdm_mck_en_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("TDM_CG", SUPPLY_SEQ_TDM_CG_EN,
|
||||
AUDIO_TOP_CON2, PDN_TDM_OUT_SFT, 1,
|
||||
NULL, 0),
|
||||
};
|
||||
|
||||
static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
|
||||
struct snd_soc_dapm_widget *sink)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
|
||||
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int dai_id = get_tdm_id_by_name(sink->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
int cur_apll;
|
||||
|
||||
/* which apll */
|
||||
cur_apll = mt8189_get_apll_by_name(afe, source->name);
|
||||
|
||||
return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
|
||||
{"TDM Playback Route", NULL, "HDMI"},
|
||||
|
||||
{"TDM", "TDMOUT", "TDM Playback Route"},
|
||||
{"TDM", NULL, "TDM_BCK"},
|
||||
{"TDM", NULL, "TDM_CG"},
|
||||
|
||||
{"TDM_DPTX", "DPTXOUT", "TDM Playback Route"},
|
||||
{"TDM_DPTX", NULL, "TDM_DPTX_BCK"},
|
||||
{"TDM_DPTX", NULL, "TDM_CG"},
|
||||
|
||||
{"TDM_BCK", NULL, "TDM_MCK"},
|
||||
{"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"},
|
||||
{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
|
||||
{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
|
||||
{"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
|
||||
{"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
|
||||
};
|
||||
|
||||
/* dai ops */
|
||||
static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
|
||||
struct mtk_afe_tdm_priv *tdm_priv,
|
||||
int freq)
|
||||
{
|
||||
int apll;
|
||||
int apll_rate;
|
||||
|
||||
apll = mt8189_get_apll_by_rate(afe, freq);
|
||||
apll_rate = mt8189_get_apll_rate(afe, apll);
|
||||
|
||||
if (freq > apll_rate)
|
||||
return -EINVAL;
|
||||
|
||||
if (apll_rate % freq != 0)
|
||||
return -EINVAL;
|
||||
|
||||
tdm_priv->mclk_rate = freq;
|
||||
tdm_priv->mclk_apll = apll;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
int tdm_id = dai->id;
|
||||
struct mtk_afe_tdm_priv *tdm_priv;
|
||||
unsigned int rate = params_rate(params);
|
||||
unsigned int channels = params_channels(params);
|
||||
snd_pcm_format_t format = params_format(params);
|
||||
unsigned int tdm_con;
|
||||
|
||||
if (tdm_id >= MT8189_DAI_NUM || tdm_id < 0)
|
||||
return -EINVAL;
|
||||
|
||||
tdm_priv = afe_priv->dai_priv[tdm_id];
|
||||
|
||||
/* calculate mclk_rate, if not set explicitly */
|
||||
if (!tdm_priv->mclk_rate) {
|
||||
tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
|
||||
mtk_dai_tdm_cal_mclk(afe,
|
||||
tdm_priv,
|
||||
tdm_priv->mclk_rate);
|
||||
}
|
||||
|
||||
/* calculate bck */
|
||||
tdm_priv->bck_rate = rate *
|
||||
channels *
|
||||
snd_pcm_format_physical_width(format);
|
||||
|
||||
if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
|
||||
return -EINVAL;
|
||||
|
||||
if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(afe->dev, "id %d, rate %d, ch %d, fmt %d, mclk %d, bck %d\n",
|
||||
tdm_id, rate, channels, format,
|
||||
tdm_priv->mclk_rate, tdm_priv->bck_rate);
|
||||
|
||||
/* set tdm */
|
||||
tdm_con = 1 << LEFT_ALIGN_SFT;
|
||||
tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
|
||||
tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT;
|
||||
tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
|
||||
tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
|
||||
regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
|
||||
|
||||
/* set dptx */
|
||||
if (tdm_id == MT8189_DAI_TDM_DPTX) {
|
||||
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
|
||||
DPTX_CHANNEL_ENABLE_MASK_SFT,
|
||||
get_dptx_ch_enable_mask(channels) <<
|
||||
DPTX_CHANNEL_ENABLE_SFT);
|
||||
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
|
||||
DPTX_CHANNEL_NUMBER_MASK_SFT,
|
||||
get_dptx_ch(channels) <<
|
||||
DPTX_CHANNEL_NUMBER_SFT);
|
||||
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
|
||||
DPTX_16BIT_MASK_SFT,
|
||||
get_dptx_wlen(format) << DPTX_16BIT_SFT);
|
||||
}
|
||||
switch (channels) {
|
||||
case 1:
|
||||
case 2:
|
||||
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
|
||||
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
|
||||
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
|
||||
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
|
||||
tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
|
||||
tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
|
||||
tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
|
||||
tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
|
||||
break;
|
||||
default:
|
||||
tdm_con = 0;
|
||||
}
|
||||
regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
|
||||
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
|
||||
HDMI_CH_NUM_MASK_SFT,
|
||||
channels << HDMI_CH_NUM_SFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
|
||||
int tdm_id = dai->id;
|
||||
|
||||
dev_dbg(afe->dev, "%s(), cmd %d, tdm_id %d\n", __func__, cmd, tdm_id);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
/* enable Out control */
|
||||
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
|
||||
HDMI_OUT_ON_MASK_SFT,
|
||||
0x1 << HDMI_OUT_ON_SFT);
|
||||
|
||||
/* enable dptx */
|
||||
if (tdm_id == MT8189_DAI_TDM_DPTX) {
|
||||
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
|
||||
DPTX_ON_MASK_SFT, 0x1 <<
|
||||
DPTX_ON_SFT);
|
||||
}
|
||||
|
||||
/* enable tdm */
|
||||
regmap_update_bits(afe->regmap, AFE_TDM_CON1,
|
||||
TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
/* disable tdm */
|
||||
regmap_update_bits(afe->regmap, AFE_TDM_CON1,
|
||||
TDM_EN_MASK_SFT, 0);
|
||||
|
||||
/* disable dptx */
|
||||
if (tdm_id == MT8189_DAI_TDM_DPTX) {
|
||||
regmap_update_bits(afe->regmap, AFE_DPTX_CON,
|
||||
DPTX_ON_MASK_SFT, 0);
|
||||
}
|
||||
|
||||
/* disable Out control */
|
||||
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
|
||||
HDMI_OUT_ON_MASK_SFT, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
struct mtk_afe_tdm_priv *tdm_priv;
|
||||
|
||||
if (dai->id >= MT8189_DAI_NUM || dai->id < 0)
|
||||
return -EINVAL;
|
||||
|
||||
tdm_priv = afe_priv->dai_priv[dai->id];
|
||||
|
||||
if (!tdm_priv)
|
||||
return -EINVAL;
|
||||
|
||||
if (dir != SND_SOC_CLOCK_OUT)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);
|
||||
|
||||
return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
|
||||
.hw_params = mtk_dai_tdm_hw_params,
|
||||
.trigger = mtk_dai_tdm_trigger,
|
||||
.set_sysclk = mtk_dai_tdm_set_sysclk,
|
||||
};
|
||||
|
||||
/* dai driver */
|
||||
#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
|
||||
SNDRV_PCM_RATE_88200 |\
|
||||
SNDRV_PCM_RATE_96000 |\
|
||||
SNDRV_PCM_RATE_176400 |\
|
||||
SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
|
||||
{
|
||||
.name = "TDM",
|
||||
.id = MT8189_DAI_TDM,
|
||||
.playback = {
|
||||
.stream_name = "TDM",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = MTK_TDM_RATES,
|
||||
.formats = MTK_TDM_FORMATS,
|
||||
},
|
||||
.ops = &mtk_dai_tdm_ops,
|
||||
},
|
||||
{
|
||||
.name = "TDM_DPTX",
|
||||
.id = MT8189_DAI_TDM_DPTX,
|
||||
.playback = {
|
||||
.stream_name = "TDM_DPTX",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = MTK_TDM_RATES,
|
||||
.formats = MTK_TDM_FORMATS,
|
||||
},
|
||||
.ops = &mtk_dai_tdm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe,
|
||||
int id)
|
||||
{
|
||||
struct mtk_afe_tdm_priv *tdm_priv;
|
||||
|
||||
tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
|
||||
GFP_KERNEL);
|
||||
if (!tdm_priv)
|
||||
return NULL;
|
||||
|
||||
if (id == MT8189_DAI_TDM_DPTX)
|
||||
tdm_priv->mclk_multiple = 256;
|
||||
else
|
||||
tdm_priv->mclk_multiple = 128;
|
||||
|
||||
tdm_priv->bck_id = MT8189_TDMOUT_BCK;
|
||||
tdm_priv->mclk_id = MT8189_TDMOUT_MCK;
|
||||
|
||||
return tdm_priv;
|
||||
}
|
||||
|
||||
int mt8189_dai_tdm_register(struct mtk_base_afe *afe)
|
||||
{
|
||||
struct mt8189_afe_private *afe_priv = afe->platform_priv;
|
||||
struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv;
|
||||
struct mtk_base_afe_dai *dai;
|
||||
|
||||
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
|
||||
if (!dai)
|
||||
return -ENOMEM;
|
||||
|
||||
dai->dai_drivers = mtk_dai_tdm_driver;
|
||||
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
|
||||
dai->controls = mtk_dai_tdm_controls;
|
||||
dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);
|
||||
dai->dapm_widgets = mtk_dai_tdm_widgets;
|
||||
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
|
||||
dai->dapm_routes = mtk_dai_tdm_routes;
|
||||
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
|
||||
|
||||
tdm_priv = init_tdm_priv_data(afe, MT8189_DAI_TDM);
|
||||
if (!tdm_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
tdm_dptx_priv = init_tdm_priv_data(afe, MT8189_DAI_TDM_DPTX);
|
||||
if (!tdm_dptx_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
list_add(&dai->list, &afe->sub_dais);
|
||||
|
||||
afe_priv->dai_priv[MT8189_DAI_TDM] = tdm_priv;
|
||||
afe_priv->dai_priv[MT8189_DAI_TDM_DPTX] = tdm_dptx_priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
97
sound/soc/mediatek/mt8189/mt8189-interconnection.h
Normal file
97
sound/soc/mediatek/mt8189/mt8189-interconnection.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Mediatek MT8189 audio driver interconnection definition
|
||||
*
|
||||
* Copyright (c) 2025 MediaTek Inc.
|
||||
* Author: Darren Ye <darren.ye@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MT8189_INTERCONNECTION_H_
|
||||
#define _MT8189_INTERCONNECTION_H_
|
||||
|
||||
/* in port define */
|
||||
#define I_CONNSYS_I2S_CH1 0
|
||||
#define I_CONNSYS_I2S_CH2 1
|
||||
#define I_GAIN0_OUT_CH1 6
|
||||
#define I_GAIN0_OUT_CH2 7
|
||||
#define I_GAIN1_OUT_CH1 8
|
||||
#define I_GAIN1_OUT_CH2 9
|
||||
#define I_GAIN2_OUT_CH1 10
|
||||
#define I_GAIN2_OUT_CH2 11
|
||||
#define I_GAIN3_OUT_CH1 12
|
||||
#define I_GAIN3_OUT_CH2 13
|
||||
#define I_STF_CH1 14
|
||||
#define I_ADDA_UL_CH1 16
|
||||
#define I_ADDA_UL_CH2 17
|
||||
#define I_ADDA_UL_CH3 18
|
||||
#define I_ADDA_UL_CH4 19
|
||||
#define I_UL_PROX_CH1 20
|
||||
#define I_UL_PROX_CH2 21
|
||||
#define I_ADDA_UL_CH5 24
|
||||
#define I_ADDA_UL_CH6 25
|
||||
#define I_DMIC0_CH1 28
|
||||
#define I_DMIC0_CH2 29
|
||||
#define I_DMIC1_CH1 30
|
||||
#define I_DMIC1_CH2 31
|
||||
|
||||
/* in port define >= 32 */
|
||||
#define I_32_OFFSET 32
|
||||
#define I_DL0_CH1 (32 - I_32_OFFSET)
|
||||
#define I_DL0_CH2 (33 - I_32_OFFSET)
|
||||
#define I_DL1_CH1 (34 - I_32_OFFSET)
|
||||
#define I_DL1_CH2 (35 - I_32_OFFSET)
|
||||
#define I_DL2_CH1 (36 - I_32_OFFSET)
|
||||
#define I_DL2_CH2 (37 - I_32_OFFSET)
|
||||
#define I_DL3_CH1 (38 - I_32_OFFSET)
|
||||
#define I_DL3_CH2 (39 - I_32_OFFSET)
|
||||
#define I_DL4_CH1 (40 - I_32_OFFSET)
|
||||
#define I_DL4_CH2 (41 - I_32_OFFSET)
|
||||
#define I_DL5_CH1 (42 - I_32_OFFSET)
|
||||
#define I_DL5_CH2 (43 - I_32_OFFSET)
|
||||
#define I_DL6_CH1 (44 - I_32_OFFSET)
|
||||
#define I_DL6_CH2 (45 - I_32_OFFSET)
|
||||
#define I_DL7_CH1 (46 - I_32_OFFSET)
|
||||
#define I_DL7_CH2 (47 - I_32_OFFSET)
|
||||
#define I_DL8_CH1 (48 - I_32_OFFSET)
|
||||
#define I_DL8_CH2 (49 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH1 (54 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH2 (55 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH3 (56 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH4 (57 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH5 (58 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH6 (59 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH7 (60 - I_32_OFFSET)
|
||||
#define I_DL_24CH_CH8 (61 - I_32_OFFSET)
|
||||
|
||||
/* in port define >= 64 */
|
||||
#define I_64_OFFSET 64
|
||||
#define I_DL23_CH1 (78 - I_64_OFFSET)
|
||||
#define I_DL23_CH2 (79 - I_64_OFFSET)
|
||||
#define I_DL24_CH1 (80 - I_64_OFFSET)
|
||||
#define I_DL24_CH2 (81 - I_64_OFFSET)
|
||||
#define I_DL25_CH1 (82 - I_64_OFFSET)
|
||||
#define I_DL25_CH2 (83 - I_64_OFFSET)
|
||||
|
||||
/* in port define >= 128 */
|
||||
#define I_128_OFFSET 128
|
||||
#define I_PCM_0_CAP_CH1 (130 - I_128_OFFSET)
|
||||
#define I_PCM_0_CAP_CH2 (131 - I_128_OFFSET)
|
||||
#define I_I2SIN0_CH1 (134 - I_128_OFFSET)
|
||||
#define I_I2SIN0_CH2 (135 - I_128_OFFSET)
|
||||
#define I_I2SIN1_CH1 (136 - I_128_OFFSET)
|
||||
#define I_I2SIN1_CH2 (137 - I_128_OFFSET)
|
||||
|
||||
/* in port define >= 192 */
|
||||
#define I_192_OFFSET 192
|
||||
#define I_SRC_0_OUT_CH1 (198 - I_192_OFFSET)
|
||||
#define I_SRC_0_OUT_CH2 (199 - I_192_OFFSET)
|
||||
#define I_SRC_1_OUT_CH1 (200 - I_192_OFFSET)
|
||||
#define I_SRC_1_OUT_CH2 (201 - I_192_OFFSET)
|
||||
#define I_SRC_2_OUT_CH1 (202 - I_192_OFFSET)
|
||||
#define I_SRC_2_OUT_CH2 (203 - I_192_OFFSET)
|
||||
#define I_SRC_3_OUT_CH1 (204 - I_192_OFFSET)
|
||||
#define I_SRC_3_OUT_CH2 (205 - I_192_OFFSET)
|
||||
#define I_SRC_4_OUT_CH1 (206 - I_192_OFFSET)
|
||||
#define I_SRC_4_OUT_CH2 (207 - I_192_OFFSET)
|
||||
|
||||
#endif
|
||||
1178
sound/soc/mediatek/mt8189/mt8189-nau8825.c
Normal file
1178
sound/soc/mediatek/mt8189/mt8189-nau8825.c
Normal file
File diff suppressed because it is too large
Load Diff
10773
sound/soc/mediatek/mt8189/mt8189-reg.h
Normal file
10773
sound/soc/mediatek/mt8189/mt8189-reg.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user