summaryrefslogtreecommitdiff
path: root/sound/soc/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/mediatek')
-rw-r--r--sound/soc/mediatek/Kconfig5
-rw-r--r--sound/soc/mediatek/common/mtk-soundcard-driver.c53
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c13
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650.c2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-clk.c6
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-clk.h1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-control.c1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-pcm.c4
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-audsys-clk.c46
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-audsys-clk.h1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c1
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-clk.c149
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-clk.h16
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-common.h3
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-pcm.c117
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-audsys-clk.c47
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-audsys-clk.h1
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-adda.c110
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-etdm.c922
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-mt6359.c453
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-reg.h2
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-control.c2
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.c5
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.h1
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-pcm.c103
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.c47
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.h1
28 files changed, 1367 insertions, 746 deletions
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 4baac72677d9..90db67e0ce4f 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -223,8 +223,13 @@ config SND_SOC_MT8188
config SND_SOC_MT8188_MT6359
tristate "ASoC Audio driver for MT8188 with MT6359 and I2S codecs"
depends on SND_SOC_MT8188 && MTK_PMIC_WRAP
+ depends on I2C
select SND_SOC_MT6359
select SND_SOC_HDMI_CODEC
+ select SND_SOC_DMIC
+ select SND_SOC_MAX98390
+ select SND_SOC_NAU8315
+ select SND_SOC_NAU8825
help
This adds support for ASoC machine driver for MediaTek MT8188
boards with the MT6359 and other I2S audio codecs.
diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c
index 738093451ccb..a58e1e3674de 100644
--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c
+++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c
@@ -21,8 +21,10 @@ static int set_card_codec_info(struct snd_soc_card *card,
int ret;
codec_node = of_get_child_by_name(sub_node, "codec");
- if (!codec_node)
- return -EINVAL;
+ if (!codec_node) {
+ dev_dbg(dev, "%s no specified codec\n", dai_link->name);
+ return 0;
+ }
/* set card codec info */
ret = snd_soc_of_get_dai_link_codecs(dev, codec_node, dai_link);
@@ -36,6 +38,47 @@ static int set_card_codec_info(struct snd_soc_card *card,
return 0;
}
+static int set_dailink_daifmt(struct snd_soc_card *card,
+ struct device_node *sub_node,
+ struct snd_soc_dai_link *dai_link)
+{
+ unsigned int daifmt;
+ const char *str;
+ int ret;
+ struct {
+ char *name;
+ unsigned int val;
+ } of_clk_table[] = {
+ { "cpu", SND_SOC_DAIFMT_CBC_CFC },
+ { "codec", SND_SOC_DAIFMT_CBP_CFP },
+ };
+
+ daifmt = snd_soc_daifmt_parse_format(sub_node, NULL);
+ if (daifmt) {
+ dai_link->dai_fmt &= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+ dai_link->dai_fmt |= daifmt;
+ }
+
+ /*
+ * check "mediatek,clk-provider = xxx"
+ * SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK area
+ */
+ ret = of_property_read_string(sub_node, "mediatek,clk-provider", &str);
+ if (ret == 0) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(of_clk_table); i++) {
+ if (strcmp(str, of_clk_table[i].name) == 0) {
+ dai_link->dai_fmt &= ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+ dai_link->dai_fmt |= of_clk_table[i].val;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
int parse_dai_link_info(struct snd_soc_card *card)
{
struct device *dev = card->dev;
@@ -67,6 +110,12 @@ int parse_dai_link_info(struct snd_soc_card *card)
of_node_put(sub_node);
return ret;
}
+
+ ret = set_dailink_daifmt(card, sub_node, dai_link);
+ if (ret < 0) {
+ of_node_put(sub_node);
+ return ret;
+ }
}
return 0;
diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
index f93c2ec8beb7..06269f7e3756 100644
--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
+++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
@@ -1070,6 +1070,10 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev)
afe->dev = &pdev->dev;
+ irq_id = platform_get_irq(pdev, 0);
+ if (irq_id <= 0)
+ return irq_id < 0 ? irq_id : -ENXIO;
+
afe->base_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(afe->base_addr))
return PTR_ERR(afe->base_addr);
@@ -1156,14 +1160,14 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev)
comp_hdmi = devm_kzalloc(&pdev->dev, sizeof(*comp_hdmi), GFP_KERNEL);
if (!comp_hdmi) {
ret = -ENOMEM;
- goto err_pm_disable;
+ goto err_cleanup_components;
}
ret = snd_soc_component_initialize(comp_hdmi,
&mt8173_afe_hdmi_dai_component,
&pdev->dev);
if (ret)
- goto err_pm_disable;
+ goto err_cleanup_components;
#ifdef CONFIG_DEBUG_FS
comp_hdmi->debugfs_prefix = "hdmi";
@@ -1175,14 +1179,11 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret)
goto err_cleanup_components;
- irq_id = platform_get_irq(pdev, 0);
- if (irq_id <= 0)
- return irq_id < 0 ? irq_id : -ENXIO;
ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler,
0, "Afe_ISR_Handle", (void *)afe);
if (ret) {
dev_err(afe->dev, "could not request_irq\n");
- goto err_pm_disable;
+ goto err_cleanup_components;
}
dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n");
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
index e05f2b0231fe..3ece4b5eaca2 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
@@ -288,7 +288,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
np = of_get_child_by_name(pdev->dev.of_node, "codec-capture");
if (np) {
- ret = snd_soc_of_get_dai_name(np, &codec_capture_dai);
+ ret = snd_soc_of_get_dai_name(np, &codec_capture_dai, 0);
of_node_put(np);
if (ret < 0) {
dev_err(&pdev->dev,
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
index a6b4f29049bb..539e3a023bc4 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c
@@ -644,9 +644,3 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
return 0;
}
-
-void mt8186_deinit_clock(void *priv)
-{
- struct mtk_base_afe *afe = priv;
- mt8186_audsys_clk_unregister(afe);
-}
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
index d5988717d8f2..a9d59e506d9a 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h
@@ -81,7 +81,6 @@ enum {
struct mtk_base_afe;
int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
int mt8186_init_clock(struct mtk_base_afe *afe);
-void mt8186_deinit_clock(void *priv);
int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
int mt8186_afe_enable_clock(struct mtk_base_afe *afe);
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-control.c b/sound/soc/mediatek/mt8186/mt8186-afe-control.c
index d714e9641571..55edf6374578 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-control.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-control.c
@@ -6,7 +6,6 @@
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
#include "mt8186-afe-common.h"
-#include <linux/pm_runtime.h>
enum {
MTK_AFE_RATE_8K = 0,
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
index 41172a82103e..a868a04ed4e7 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
@@ -2848,10 +2848,6 @@ static int mt8186_afe_pcm_dev_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_add_action_or_reset(dev, mt8186_deinit_clock, (void *)afe);
- if (ret)
- return ret;
-
/* init memif */
afe->memif_32bit_supported = 0;
afe->memif_size = MT8186_MEMIF_NUM;
diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
index 578969ca91c8..5666be6b1bd2 100644
--- a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
+++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
@@ -84,6 +84,29 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24),
};
+static void mt8186_audsys_clk_unregister(void *data)
+{
+ struct mtk_base_afe *afe = data;
+ struct mt8186_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ int i;
+
+ if (!afe_priv)
+ return;
+
+ for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+ cl = afe_priv->lookup[i];
+ if (!cl)
+ continue;
+
+ clk = cl->clk;
+ clk_unregister_gate(clk);
+
+ clkdev_drop(cl);
+ }
+}
+
int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
{
struct mt8186_afe_private *afe_priv = afe->platform_priv;
@@ -124,27 +147,6 @@ int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
afe_priv->lookup[i] = cl;
}
- return 0;
+ return devm_add_action_or_reset(afe->dev, mt8186_audsys_clk_unregister, afe);
}
-void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe)
-{
- struct mt8186_afe_private *afe_priv = afe->platform_priv;
- struct clk *clk;
- struct clk_lookup *cl;
- int i;
-
- if (!afe_priv)
- return;
-
- for (i = 0; i < CLK_AUD_NR_CLK; i++) {
- cl = afe_priv->lookup[i];
- if (!cl)
- continue;
-
- clk = cl->clk;
- clk_unregister_gate(clk);
-
- clkdev_drop(cl);
- }
-}
diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
index b8d6a06e11e8..897a2914dc19 100644
--- a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
+++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
@@ -10,6 +10,5 @@
#define _MT8186_AUDSYS_CLK_H_
int mt8186_audsys_clk_register(struct mtk_base_afe *afe);
-void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe);
#endif
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
index cdf54d1eb50d..0432f9d89020 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
@@ -10,7 +10,6 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
index 7538274641fd..9c11016f032c 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
@@ -12,7 +12,6 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/rt5682.h>
diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
index 743d6a162cb9..e69c1bb2cb23 100644
--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
+++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
@@ -24,14 +24,19 @@ static const char *aud_clks[MT8188_CLK_NUM] = {
[MT8188_CLK_APMIXED_APLL2] = "apll2",
/* divider */
+ [MT8188_CLK_TOP_APLL1_D4] = "apll1_d4",
+ [MT8188_CLK_TOP_APLL2_D4] = "apll2_d4",
[MT8188_CLK_TOP_APLL12_DIV0] = "apll12_div0",
[MT8188_CLK_TOP_APLL12_DIV1] = "apll12_div1",
[MT8188_CLK_TOP_APLL12_DIV2] = "apll12_div2",
[MT8188_CLK_TOP_APLL12_DIV3] = "apll12_div3",
+ [MT8188_CLK_TOP_APLL12_DIV4] = "apll12_div4",
[MT8188_CLK_TOP_APLL12_DIV9] = "apll12_div9",
/* mux */
[MT8188_CLK_TOP_A1SYS_HP_SEL] = "top_a1sys_hp",
+ [MT8188_CLK_TOP_A2SYS_SEL] = "top_a2sys",
+ [MT8188_CLK_TOP_AUD_IEC_SEL] = "top_aud_iec",
[MT8188_CLK_TOP_AUD_INTBUS_SEL] = "top_aud_intbus",
[MT8188_CLK_TOP_AUDIO_H_SEL] = "top_audio_h",
[MT8188_CLK_TOP_AUDIO_LOCAL_BUS_SEL] = "top_audio_local_bus",
@@ -378,6 +383,19 @@ int mt8188_afe_get_default_mclk_source_by_rate(int rate)
MT8188_MCK_SEL_APLL1 : MT8188_MCK_SEL_APLL2;
}
+int mt8188_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
+{
+ return ((rate % 8000) == 0) ? MT8188_AUD_PLL1 : MT8188_AUD_PLL2;
+}
+
+int mt8188_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
+{
+ if (strcmp(name, APLL1_W_NAME) == 0)
+ return MT8188_AUD_PLL1;
+
+ return MT8188_AUD_PLL2;
+}
+
int mt8188_afe_init_clock(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
@@ -418,13 +436,6 @@ int mt8188_afe_init_clock(struct mtk_base_afe *afe)
return 0;
}
-void mt8188_afe_deinit_clock(void *priv)
-{
- struct mtk_base_afe *afe = priv;
-
- mt8188_audsys_clk_unregister(afe);
-}
-
int mt8188_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
{
int ret;
@@ -477,8 +488,8 @@ int mt8188_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
if (clk && parent) {
ret = clk_set_parent(clk, parent);
if (ret) {
- dev_dbg(afe->dev, "%s(), failed to set clk parent\n",
- __func__);
+ dev_dbg(afe->dev, "%s(), failed to set clk parent %d\n",
+ __func__, ret);
return ret;
}
}
@@ -605,54 +616,132 @@ static int mt8188_afe_disable_afe_on(struct mtk_base_afe *afe)
return 0;
}
-static int mt8188_afe_enable_timing_sys(struct mtk_base_afe *afe)
+static int mt8188_afe_enable_a1sys(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ int ret;
- mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A1SYS]);
- mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A2SYS]);
+ ret = mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A1SYS]);
+ if (ret)
+ return ret;
- mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_A1SYS_TIMING);
- mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_A2SYS_TIMING);
- mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_26M_TIMING);
+ return mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_A1SYS_TIMING);
+}
+static int mt8188_afe_disable_a1sys(struct mtk_base_afe *afe)
+{
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+
+ mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_A1SYS_TIMING);
+ mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A1SYS]);
return 0;
}
-static int mt8188_afe_disable_timing_sys(struct mtk_base_afe *afe)
+static int mt8188_afe_enable_a2sys(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ int ret;
- mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A1SYS]);
- mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A2SYS]);
+ ret = mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A2SYS]);
+ if (ret)
+ return ret;
- mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_26M_TIMING);
- mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_A2SYS_TIMING);
- mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_A1SYS_TIMING);
+ return mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_A2SYS_TIMING);
+}
+static int mt8188_afe_disable_a2sys(struct mtk_base_afe *afe)
+{
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+
+ mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_A2SYS_TIMING);
+ mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_A2SYS]);
return 0;
}
-int mt8188_afe_enable_main_clock(struct mtk_base_afe *afe)
+int mt8188_apll1_enable(struct mtk_base_afe *afe)
{
- mt8188_afe_enable_timing_sys(afe);
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ int ret;
- mt8188_afe_enable_afe_on(afe);
+ ret = mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_TOP_APLL1_D4]);
+ if (ret)
+ return ret;
- mt8188_afe_enable_apll_tuner(afe, MT8188_AUD_PLL1);
- mt8188_afe_enable_apll_tuner(afe, MT8188_AUD_PLL2);
+ ret = mt8188_afe_set_clk_parent(afe, afe_priv->clk[MT8188_CLK_TOP_A1SYS_HP_SEL],
+ afe_priv->clk[MT8188_CLK_TOP_APLL1_D4]);
+ if (ret)
+ goto err_clk_parent;
+
+ ret = mt8188_afe_enable_apll_tuner(afe, MT8188_AUD_PLL1);
+ if (ret)
+ goto err_apll_tuner;
+
+ ret = mt8188_afe_enable_a1sys(afe);
+ if (ret)
+ goto err_a1sys;
return 0;
+
+err_a1sys:
+ mt8188_afe_disable_apll_tuner(afe, MT8188_AUD_PLL1);
+err_apll_tuner:
+ mt8188_afe_set_clk_parent(afe, afe_priv->clk[MT8188_CLK_TOP_A1SYS_HP_SEL],
+ afe_priv->clk[MT8188_CLK_XTAL_26M]);
+err_clk_parent:
+ mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_TOP_APLL1_D4]);
+
+ return ret;
}
-int mt8188_afe_disable_main_clock(struct mtk_base_afe *afe)
+int mt8188_apll1_disable(struct mtk_base_afe *afe)
{
- mt8188_afe_disable_apll_tuner(afe, MT8188_AUD_PLL2);
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+
+ mt8188_afe_disable_a1sys(afe);
mt8188_afe_disable_apll_tuner(afe, MT8188_AUD_PLL1);
+ mt8188_afe_set_clk_parent(afe, afe_priv->clk[MT8188_CLK_TOP_A1SYS_HP_SEL],
+ afe_priv->clk[MT8188_CLK_XTAL_26M]);
+ mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_TOP_APLL1_D4]);
- mt8188_afe_disable_afe_on(afe);
+ return 0;
+}
- mt8188_afe_disable_timing_sys(afe);
+int mt8188_apll2_enable(struct mtk_base_afe *afe)
+{
+ int ret;
+
+ ret = mt8188_afe_enable_apll_tuner(afe, MT8188_AUD_PLL2);
+ if (ret)
+ return ret;
+
+ ret = mt8188_afe_enable_a2sys(afe);
+ if (ret)
+ goto err_a2sys;
return 0;
+err_a2sys:
+ mt8188_afe_disable_apll_tuner(afe, MT8188_AUD_PLL2);
+
+ return ret;
+}
+
+int mt8188_apll2_disable(struct mtk_base_afe *afe)
+{
+ mt8188_afe_disable_a2sys(afe);
+ mt8188_afe_disable_apll_tuner(afe, MT8188_AUD_PLL2);
+ return 0;
+}
+
+int mt8188_afe_enable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8188_afe_enable_top_cg(afe, MT8188_TOP_CG_26M_TIMING);
+ mt8188_afe_enable_afe_on(afe);
+ return 0;
+}
+
+int mt8188_afe_disable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8188_afe_disable_afe_on(afe);
+ mt8188_afe_disable_top_cg(afe, MT8188_TOP_CG_26M_TIMING);
+ return 0;
}
diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
index 084fdfb1d877..ec53c171c170 100644
--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
+++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
@@ -11,6 +11,10 @@
#ifndef _MT8188_AFE_CLK_H_
#define _MT8188_AFE_CLK_H_
+/* APLL */
+#define APLL1_W_NAME "APLL1"
+#define APLL2_W_NAME "APLL2"
+
enum {
/* xtal */
MT8188_CLK_XTAL_26M,
@@ -18,13 +22,18 @@ enum {
MT8188_CLK_APMIXED_APLL1,
MT8188_CLK_APMIXED_APLL2,
/* divider */
+ MT8188_CLK_TOP_APLL1_D4,
+ MT8188_CLK_TOP_APLL2_D4,
MT8188_CLK_TOP_APLL12_DIV0,
MT8188_CLK_TOP_APLL12_DIV1,
MT8188_CLK_TOP_APLL12_DIV2,
MT8188_CLK_TOP_APLL12_DIV3,
+ MT8188_CLK_TOP_APLL12_DIV4,
MT8188_CLK_TOP_APLL12_DIV9,
/* mux */
MT8188_CLK_TOP_A1SYS_HP_SEL,
+ MT8188_CLK_TOP_A2SYS_SEL,
+ MT8188_CLK_TOP_AUD_IEC_SEL,
MT8188_CLK_TOP_AUD_INTBUS_SEL,
MT8188_CLK_TOP_AUDIO_H_SEL,
MT8188_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
@@ -99,14 +108,19 @@ struct mtk_base_afe;
int mt8188_afe_get_mclk_source_clk_id(int sel);
int mt8188_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll);
int mt8188_afe_get_default_mclk_source_by_rate(int rate);
+int mt8188_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
+int mt8188_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
int mt8188_afe_init_clock(struct mtk_base_afe *afe);
-void mt8188_afe_deinit_clock(void *priv);
int mt8188_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
void mt8188_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
int mt8188_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
unsigned int rate);
int mt8188_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
struct clk *parent);
+int mt8188_apll1_enable(struct mtk_base_afe *afe);
+int mt8188_apll1_disable(struct mtk_base_afe *afe);
+int mt8188_apll2_enable(struct mtk_base_afe *afe);
+int mt8188_apll2_disable(struct mtk_base_afe *afe);
int mt8188_afe_enable_main_clock(struct mtk_base_afe *afe);
int mt8188_afe_disable_main_clock(struct mtk_base_afe *afe);
int mt8188_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-common.h b/sound/soc/mediatek/mt8188/mt8188-afe-common.h
index eb7e57c239bd..1304d685a306 100644
--- a/sound/soc/mediatek/mt8188/mt8188-afe-common.h
+++ b/sound/soc/mediatek/mt8188/mt8188-afe-common.h
@@ -39,7 +39,7 @@ enum {
MT8188_AFE_MEMIF_END,
MT8188_AFE_MEMIF_NUM = (MT8188_AFE_MEMIF_END - MT8188_AFE_MEMIF_START),
MT8188_AFE_IO_START = MT8188_AFE_MEMIF_END,
- MT8188_AFE_IO_ADDA = MT8188_AFE_IO_START,
+ MT8188_AFE_IO_DL_SRC = MT8188_AFE_IO_START,
MT8188_AFE_IO_DMIC_IN,
MT8188_AFE_IO_DPTX,
MT8188_AFE_IO_ETDM_START,
@@ -52,6 +52,7 @@ enum {
MT8188_AFE_IO_ETDM_NUM =
(MT8188_AFE_IO_ETDM_END - MT8188_AFE_IO_ETDM_START),
MT8188_AFE_IO_PCM = MT8188_AFE_IO_ETDM_END,
+ MT8188_AFE_IO_UL_SRC,
MT8188_AFE_IO_END,
MT8188_AFE_IO_NUM = (MT8188_AFE_IO_END - MT8188_AFE_IO_START),
MT8188_DAI_END = MT8188_AFE_IO_END,
diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
index e5f9373bed56..6a24b339444b 100644
--- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/infracfg.h>
#include <linux/reset.h>
#include <sound/pcm_params.h>
#include "mt8188-afe-common.h"
@@ -1898,10 +1899,6 @@ static const struct snd_kcontrol_new mt8188_memif_controls[] = {
MT8188_AFE_MEMIF_UL10),
};
-static const struct snd_soc_component_driver mt8188_afe_pcm_dai_component = {
- .name = "mt8188-afe-pcm-dai",
-};
-
static const struct mtk_base_memif_data memif_data[MT8188_AFE_MEMIF_NUM] = {
[MT8188_AFE_MEMIF_DL2] = {
.name = "DL2",
@@ -3137,14 +3134,69 @@ static int mt8188_afe_parse_of(struct mtk_base_afe *afe,
return 0;
}
+#define MT8188_DELAY_US 10
+#define MT8188_TIMEOUT_US USEC_PER_SEC
+
+static int bus_protect_enable(struct regmap *regmap)
+{
+ int ret;
+ u32 val;
+ u32 mask;
+
+ val = 0;
+ mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1;
+ regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_SET, mask);
+
+ ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+ val, (val & mask) == mask,
+ MT8188_DELAY_US, MT8188_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ val = 0;
+ mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2;
+ regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_SET, mask);
+
+ ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+ val, (val & mask) == mask,
+ MT8188_DELAY_US, MT8188_TIMEOUT_US);
+ return ret;
+}
+
+static int bus_protect_disable(struct regmap *regmap)
+{
+ int ret;
+ u32 val;
+ u32 mask;
+
+ val = 0;
+ mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2;
+ regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_CLR, mask);
+
+ ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+ val, !(val & mask),
+ MT8188_DELAY_US, MT8188_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ val = 0;
+ mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1;
+ regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_CLR, mask);
+
+ ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+ val, !(val & mask),
+ MT8188_DELAY_US, MT8188_TIMEOUT_US);
+ return ret;
+}
+
static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
struct mt8188_afe_private *afe_priv;
struct device *dev;
- int i, irq_id, ret;
- struct snd_soc_component *component;
struct reset_control *rstc;
+ struct regmap *infra_ao;
+ int i, irq_id, ret;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
if (ret)
@@ -3168,27 +3220,42 @@ static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(afe->base_addr),
"AFE base_addr not found\n");
+ infra_ao = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "mediatek,infracfg");
+ if (IS_ERR(infra_ao))
+ return dev_err_probe(dev, PTR_ERR(infra_ao),
+ "%s() Cannot find infra_ao controller\n",
+ __func__);
+
/* reset controller to reset audio regs before regmap cache */
rstc = devm_reset_control_get_exclusive(dev, "audiosys");
if (IS_ERR(rstc))
return dev_err_probe(dev, PTR_ERR(rstc),
"could not get audiosys reset\n");
+ ret = bus_protect_enable(infra_ao);
+ if (ret) {
+ dev_err(dev, "bus_protect_enable failed\n");
+ return ret;
+ }
+
ret = reset_control_reset(rstc);
if (ret) {
dev_err(dev, "failed to trigger audio reset:%d\n", ret);
return ret;
}
+ ret = bus_protect_disable(infra_ao);
+ if (ret) {
+ dev_err(dev, "bus_protect_disable failed\n");
+ return ret;
+ }
+
/* initial audio related clock */
ret = mt8188_afe_init_clock(afe);
if (ret)
return dev_err_probe(dev, ret, "init clock error");
- ret = devm_add_action_or_reset(dev, mt8188_afe_deinit_clock, (void *)afe);
- if (ret)
- return ret;
-
spin_lock_init(&afe_priv->afe_ctrl_lock);
mutex_init(&afe->irq_alloc_lock);
@@ -3280,34 +3347,12 @@ static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
/* register component */
ret = devm_snd_soc_register_component(dev, &mt8188_afe_component,
- NULL, 0);
+ afe->dai_drivers, afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_platform\n");
goto err_pm_put;
}
- component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL);
- if (!component) {
- ret = -ENOMEM;
- goto err_pm_put;
- }
-
- ret = snd_soc_component_initialize(component,
- &mt8188_afe_pcm_dai_component,
- &pdev->dev);
- if (ret)
- goto err_pm_put;
-#ifdef CONFIG_DEBUG_FS
- component->debugfs_prefix = "pcm";
-#endif
- ret = snd_soc_add_component(component,
- afe->dai_drivers,
- afe->num_dai_drivers);
- if (ret) {
- dev_warn(dev, "err_add_component\n");
- goto err_pm_put;
- }
-
mt8188_afe_init_registers(afe);
pm_runtime_put_sync(&pdev->dev);
@@ -3323,11 +3368,6 @@ err_pm_put:
return ret;
}
-static void mt8188_afe_pcm_dev_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_component(&pdev->dev);
-}
-
static const struct of_device_id mt8188_afe_pcm_dt_match[] = {
{ .compatible = "mediatek,mt8188-afe", },
{},
@@ -3346,7 +3386,6 @@ static struct platform_driver mt8188_afe_pcm_driver = {
.pm = &mt8188_afe_pm_ops,
},
.probe = mt8188_afe_pcm_dev_probe,
- .remove_new = mt8188_afe_pcm_dev_remove,
};
module_platform_driver(mt8188_afe_pcm_driver);
diff --git a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c
index be1c53bf4729..c796ad8b62ee 100644
--- a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c
+++ b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c
@@ -138,6 +138,29 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11", "top_asm_h", 11),
};
+static void mt8188_audsys_clk_unregister(void *data)
+{
+ struct mtk_base_afe *afe = data;
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ int i;
+
+ if (!afe_priv)
+ return;
+
+ for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+ cl = afe_priv->lookup[i];
+ if (!cl)
+ continue;
+
+ clk = cl->clk;
+ clk_unregister_gate(clk);
+
+ clkdev_drop(cl);
+ }
+}
+
int mt8188_audsys_clk_register(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
@@ -179,27 +202,5 @@ int mt8188_audsys_clk_register(struct mtk_base_afe *afe)
afe_priv->lookup[i] = cl;
}
- return 0;
-}
-
-void mt8188_audsys_clk_unregister(struct mtk_base_afe *afe)
-{
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct clk *clk;
- struct clk_lookup *cl;
- int i;
-
- if (!afe_priv)
- return;
-
- for (i = 0; i < CLK_AUD_NR_CLK; i++) {
- cl = afe_priv->lookup[i];
- if (!cl)
- continue;
-
- clk = cl->clk;
- clk_unregister_gate(clk);
-
- clkdev_drop(cl);
- }
+ return devm_add_action_or_reset(afe->dev, mt8188_audsys_clk_unregister, afe);
}
diff --git a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.h b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.h
index 6c5f463ad7e4..45b0948c4a06 100644
--- a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.h
+++ b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.h
@@ -10,6 +10,5 @@
#define _MT8188_AUDSYS_CLK_H_
int mt8188_audsys_clk_register(struct mtk_base_afe *afe);
-void mt8188_audsys_clk_unregister(struct mtk_base_afe *afe);
#endif
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
index d71696901553..7dc029f2b428 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
@@ -18,7 +18,6 @@
#define ADDA_HIRES_THRES 48000
enum {
- SUPPLY_SEQ_CLOCK_SEL,
SUPPLY_SEQ_ADDA_DL_ON,
SUPPLY_SEQ_ADDA_MTKAIF_CFG,
SUPPLY_SEQ_ADDA_UL_ON,
@@ -54,8 +53,7 @@ enum {
};
struct mtk_dai_adda_priv {
- unsigned int dl_rate;
- unsigned int ul_rate;
+ bool hires_required;
};
static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe,
@@ -242,70 +240,35 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
return 0;
}
-static int mtk_audio_hires_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
+static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+ const char *name)
{
- struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct clk *clk = afe_priv->clk[MT8188_CLK_TOP_AUDIO_H_SEL];
- struct clk *clk_parent;
-
- dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
- __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- clk_parent = afe_priv->clk[MT8188_CLK_APMIXED_APLL1];
- break;
- case SND_SOC_DAPM_POST_PMD:
- clk_parent = afe_priv->clk[MT8188_CLK_XTAL_26M];
- break;
- default:
- return 0;
- }
- mt8188_afe_set_clk_parent(afe, clk, clk_parent);
-
- return 0;
-}
-
-static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink)
-{
- struct snd_soc_dapm_widget *w = source;
- struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_adda_priv *adda_priv;
-
- adda_priv = afe_priv->dai_priv[MT8188_AFE_IO_ADDA];
- if (!adda_priv) {
- dev_err(afe->dev, "%s adda_priv == NULL", __func__);
- return 0;
- }
-
- return !!(adda_priv->ul_rate > ADDA_HIRES_THRES);
+ if (strstr(name, "aud_adc_hires"))
+ return afe_priv->dai_priv[MT8188_AFE_IO_UL_SRC];
+ else if (strstr(name, "aud_dac_hires"))
+ return afe_priv->dai_priv[MT8188_AFE_IO_DL_SRC];
+ else
+ return NULL;
}
-static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink)
+static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
{
struct snd_soc_dapm_widget *w = source;
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
struct mtk_dai_adda_priv *adda_priv;
- adda_priv = afe_priv->dai_priv[MT8188_AFE_IO_ADDA];
+ adda_priv = get_adda_priv_by_name(afe, w->name);
if (!adda_priv) {
- dev_err(afe->dev, "%s adda_priv == NULL", __func__);
+ dev_dbg(afe->dev, "adda_priv == NULL");
return 0;
}
- return !!(adda_priv->dl_rate > ADDA_HIRES_THRES);
+ return (adda_priv->hires_required) ? 1 : 0;
}
static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = {
@@ -364,12 +327,6 @@ static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
mtk_adda_ul_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SUPPLY_S("AUDIO_HIRES", SUPPLY_SEQ_CLOCK_SEL,
- SND_SOC_NOPM,
- 0, 0,
- mtk_audio_hires_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
SND_SOC_NOPM,
0, 0,
@@ -396,8 +353,7 @@ static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
{"ADDA Capture", NULL, "ADDA Capture Enable"},
{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
{"ADDA Capture", NULL, "aud_adc"},
- {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adc_hires_connect},
- {"aud_adc_hires", NULL, "AUDIO_HIRES"},
+ {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect},
{"I168", NULL, "ADDA Capture"},
{"I169", NULL, "ADDA Capture"},
@@ -405,8 +361,7 @@ static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
{"ADDA Playback", NULL, "ADDA Enable"},
{"ADDA Playback", NULL, "ADDA Playback Enable"},
{"ADDA Playback", NULL, "aud_dac"},
- {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_dac_hires_connect},
- {"aud_dac_hires", NULL, "AUDIO_HIRES"},
+ {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect},
{"DL_GAIN", NULL, "O176"},
{"DL_GAIN", NULL, "O177"},
@@ -540,13 +495,12 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %u\n",
__func__, id, substream->stream, rate);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- adda_priv->dl_rate = rate;
+ adda_priv->hires_required = (rate > ADDA_HIRES_THRES);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = mtk_dai_da_configure(afe, rate, id);
- } else {
- adda_priv->ul_rate = rate;
+ else
ret = mtk_dai_ad_configure(afe, rate, id);
- }
return ret;
}
@@ -573,8 +527,8 @@ static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
{
- .name = "ADDA",
- .id = MT8188_AFE_IO_ADDA,
+ .name = "DL_SRC",
+ .id = MT8188_AFE_IO_DL_SRC,
.playback = {
.stream_name = "ADDA Playback",
.channels_min = 1,
@@ -582,6 +536,11 @@ static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
.rates = MTK_ADDA_PLAYBACK_RATES,
.formats = MTK_ADDA_FORMATS,
},
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "UL_SRC",
+ .id = MT8188_AFE_IO_UL_SRC,
.capture = {
.stream_name = "ADDA Capture",
.channels_min = 1,
@@ -597,13 +556,18 @@ static int init_adda_priv_data(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
struct mtk_dai_adda_priv *adda_priv;
+ int adda_dai_list[] = {MT8188_AFE_IO_DL_SRC, MT8188_AFE_IO_UL_SRC};
+ int i;
- adda_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_adda_priv),
- GFP_KERNEL);
- if (!adda_priv)
- return -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {
+ adda_priv = devm_kzalloc(afe->dev,
+ sizeof(struct mtk_dai_adda_priv),
+ GFP_KERNEL);
+ if (!adda_priv)
+ return -ENOMEM;
- afe_priv->dai_priv[MT8188_AFE_IO_ADDA] = adda_priv;
+ afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;
+ }
return 0;
}
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
index 7a37752d4244..16440dd0a89c 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
@@ -22,6 +22,14 @@
#define ENUM_TO_STR(x) #x
enum {
+ SUPPLY_SEQ_APLL,
+ SUPPLY_SEQ_ETDM_MCLK,
+ SUPPLY_SEQ_ETDM_CG,
+ SUPPLY_SEQ_DPTX_EN,
+ SUPPLY_SEQ_ETDM_EN,
+};
+
+enum {
MTK_DAI_ETDM_FORMAT_I2S = 0,
MTK_DAI_ETDM_FORMAT_LJ,
MTK_DAI_ETDM_FORMAT_RJ,
@@ -84,11 +92,11 @@ struct mtk_dai_etdm_rate {
};
struct mtk_dai_etdm_priv {
- unsigned int clock_mode;
unsigned int data_mode;
bool slave_mode;
bool lrck_inv;
bool bck_inv;
+ unsigned int rate;
unsigned int format;
unsigned int slots;
unsigned int lrck_width;
@@ -100,8 +108,6 @@ struct mtk_dai_etdm_priv {
unsigned int cowork_slv_count;
int cowork_slv_id[MT8188_AFE_IO_ETDM_NUM - 1]; //dai_id
bool in_disable_ch[MT8188_ETDM_MAX_CHANNELS];
- unsigned int en_ref_cnt;
- bool is_prepared;
};
static const struct mtk_dai_etdm_rate mt8188_etdm_rates[] = {
@@ -345,13 +351,85 @@ static int mtk_dai_etdm_get_clkdiv_id_by_dai_id(int dai_id)
}
}
+static int get_etdm_id_by_name(struct mtk_base_afe *afe,
+ const char *name)
+{
+ if (!strncmp(name, "ETDM1_IN", strlen("ETDM1_IN")))
+ return MT8188_AFE_IO_ETDM1_IN;
+ else if (!strncmp(name, "ETDM2_IN", strlen("ETDM2_IN")))
+ return MT8188_AFE_IO_ETDM2_IN;
+ else if (!strncmp(name, "ETDM1_OUT", strlen("ETDM1_OUT")))
+ return MT8188_AFE_IO_ETDM1_OUT;
+ else if (!strncmp(name, "ETDM2_OUT", strlen("ETDM2_OUT")))
+ return MT8188_AFE_IO_ETDM2_OUT;
+ else if (!strncmp(name, "ETDM3_OUT", strlen("ETDM3_OUT")))
+ return MT8188_AFE_IO_ETDM3_OUT;
+ else if (!strncmp(name, "DPTX", strlen("DPTX")))
+ return MT8188_AFE_IO_ETDM3_OUT;
+ else
+ return -EINVAL;
+}
+
+static struct mtk_dai_etdm_priv *get_etdm_priv_by_name(struct mtk_base_afe *afe,
+ const char *name)
+{
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ int dai_id = get_etdm_id_by_name(afe, name);
+
+ if (dai_id < MT8188_AFE_IO_ETDM_START ||
+ dai_id >= MT8188_AFE_IO_ETDM_END)
+ return NULL;
+
+ return afe_priv->dai_priv[dai_id];
+}
+
static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data;
+ struct etdm_con_reg etdm_reg;
+ unsigned int val = 0;
+ unsigned int mask;
+ int clkmux_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id);
int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+ int apll_clk_id;
+ int apll;
+ int ret;
- if (clkdiv_id < 0)
+ if (!is_valid_etdm_dai(dai_id))
return -EINVAL;
+ etdm_data = afe_priv->dai_priv[dai_id];
+
+ apll = etdm_data->mclk_apll;
+ apll_clk_id = mt8188_afe_get_mclk_source_clk_id(apll);
+
+ if (clkmux_id < 0 || clkdiv_id < 0)
+ return -EINVAL;
+
+ if (apll_clk_id < 0)
+ return apll_clk_id;
+
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ return ret;
+
+ mask = ETDM_CON1_MCLK_OUTPUT;
+ if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
+ val = ETDM_CON1_MCLK_OUTPUT;
+ regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+ /* enable parent clock before select apll*/
+ mt8188_afe_enable_clk(afe, afe_priv->clk[clkmux_id]);
+
+ /* select apll */
+ ret = mt8188_afe_set_clk_parent(afe, afe_priv->clk[clkmux_id],
+ afe_priv->clk[apll_clk_id]);
+ if (ret)
+ return ret;
+
+ /* set rate */
+ ret = mt8188_afe_set_clk_rate(afe, afe_priv->clk[clkdiv_id],
+ etdm_data->mclk_freq);
mt8188_afe_enable_clk(afe, afe_priv->clk[clkdiv_id]);
@@ -361,12 +439,275 @@ static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id)
static int mtk_dai_etdm_disable_mclk(struct mtk_base_afe *afe, int dai_id)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ int clkmux_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id);
int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
- if (clkdiv_id < 0)
+ if (clkmux_id < 0 || clkdiv_id < 0)
return -EINVAL;
mt8188_afe_disable_clk(afe, afe_priv->clk[clkdiv_id]);
+ mt8188_afe_disable_clk(afe, afe_priv->clk[clkmux_id]);
+
+ return 0;
+}
+
+static int mtk_afe_etdm_apll_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_dapm_widget *w = sink;
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_dai_etdm_priv *etdm_priv;
+ int cur_apll;
+ int need_apll;
+
+ etdm_priv = get_etdm_priv_by_name(afe, w->name);
+ if (!etdm_priv) {
+ dev_dbg(afe->dev, "etdm_priv == NULL\n");
+ return 0;
+ }
+
+ cur_apll = mt8188_get_apll_by_name(afe, source->name);
+ need_apll = mt8188_get_apll_by_rate(afe, etdm_priv->rate);
+
+ return (need_apll == cur_apll) ? 1 : 0;
+}
+
+static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_dapm_widget *w = sink;
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_dai_etdm_priv *etdm_priv;
+ int cur_apll;
+
+ etdm_priv = get_etdm_priv_by_name(afe, w->name);
+
+ cur_apll = mt8188_get_apll_by_name(afe, source->name);
+
+ return (etdm_priv->mclk_apll == cur_apll) ? 1 : 0;
+}
+
+static int mtk_etdm_mclk_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_dapm_widget *w = sink;
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8188_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_priv;
+ int mclk_id;
+
+ mclk_id = get_etdm_id_by_name(afe, source->name);
+ if (mclk_id < 0) {
+ dev_dbg(afe->dev, "mclk_id < 0\n");
+ return 0;
+ }
+
+ etdm_priv = get_etdm_priv_by_name(afe, w->name);
+ if (!etdm_priv) {
+ dev_dbg(afe->dev, "etdm_priv == NULL\n");
+ return 0;
+ }
+
+ if (get_etdm_id_by_name(afe, sink->name) == mclk_id)
+ return !!(etdm_priv->mclk_freq > 0);
+
+ if (etdm_priv->cowork_source_id == mclk_id) {
+ etdm_priv = afe_priv->dai_priv[mclk_id];
+ return !!(etdm_priv->mclk_freq > 0);
+ }
+
+ return 0;
+}
+
+static int mtk_etdm_cowork_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 mt8188_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_priv;
+ int source_id;
+ int i;
+
+ source_id = get_etdm_id_by_name(afe, source->name);
+ if (source_id < 0) {
+ dev_dbg(afe->dev, "%s() source_id < 0\n", __func__);
+ return 0;
+ }
+
+ etdm_priv = get_etdm_priv_by_name(afe, w->name);
+ if (!etdm_priv) {
+ dev_dbg(afe->dev, "%s() etdm_priv == NULL\n", __func__);
+ return 0;
+ }
+
+ if (etdm_priv->cowork_source_id != COWORK_ETDM_NONE) {
+ if (etdm_priv->cowork_source_id == source_id)
+ return 1;
+
+ etdm_priv = afe_priv->dai_priv[etdm_priv->cowork_source_id];
+ for (i = 0; i < etdm_priv->cowork_slv_count; i++) {
+ if (etdm_priv->cowork_slv_id[i] == source_id)
+ return 1;
+ }
+ } else {
+ for (i = 0; i < etdm_priv->cowork_slv_count; i++) {
+ if (etdm_priv->cowork_slv_id[i] == source_id)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int mtk_apll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (strcmp(w->name, APLL1_W_NAME) == 0)
+ mt8188_apll1_enable(afe);
+ else
+ mt8188_apll2_enable(afe);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (strcmp(w->name, APLL1_W_NAME) == 0)
+ mt8188_apll1_disable(afe);
+ else
+ mt8188_apll2_disable(afe);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_etdm_mclk_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);
+ int mclk_id = get_etdm_id_by_name(afe, w->name);
+
+ if (mclk_id < 0) {
+ dev_dbg(afe->dev, "%s() mclk_id < 0\n", __func__);
+ return 0;
+ }
+
+ dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mtk_dai_etdm_enable_mclk(afe, mclk_id);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mtk_dai_etdm_disable_mclk(afe, mclk_id);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_dptx_mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mtk_dai_etdm_enable_mclk(afe, MT8188_AFE_IO_DPTX);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mtk_dai_etdm_disable_mclk(afe, MT8188_AFE_IO_DPTX);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_etdm_cg_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 mt8188_afe_private *afe_priv = afe->platform_priv;
+ int etdm_id;
+ int cg_id;
+
+ etdm_id = get_etdm_id_by_name(afe, w->name);
+ if (etdm_id < 0) {
+ dev_dbg(afe->dev, "%s() etdm_id < 0\n", __func__);
+ return 0;
+ }
+
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(etdm_id);
+ if (cg_id < 0) {
+ dev_dbg(afe->dev, "%s() cg_id < 0\n", __func__);
+ return 0;
+ }
+
+ dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8188_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8188_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_etdm3_cg_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 mt8188_afe_private *afe_priv = afe->platform_priv;
+
+ dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_HDMI_OUT]);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_HDMI_OUT]);
+ break;
+ default:
+ break;
+ }
return 0;
}
@@ -906,11 +1247,181 @@ static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = {
SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch7_mux_control),
+ /* mclk en */
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_IN_MCLK", SUPPLY_SEQ_ETDM_MCLK,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_IN_MCLK", SUPPLY_SEQ_ETDM_MCLK,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_OUT_MCLK", SUPPLY_SEQ_ETDM_MCLK,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_OUT_MCLK", SUPPLY_SEQ_ETDM_MCLK,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("DPTX_MCLK", SUPPLY_SEQ_ETDM_MCLK,
+ SND_SOC_NOPM, 0, 0,
+ mtk_dptx_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* cg */
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_IN_CG", SUPPLY_SEQ_ETDM_CG,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_cg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_IN_CG", SUPPLY_SEQ_ETDM_CG,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_cg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_OUT_CG", SUPPLY_SEQ_ETDM_CG,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_cg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_OUT_CG", SUPPLY_SEQ_ETDM_CG,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm_cg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ETDM3_OUT_CG", SUPPLY_SEQ_ETDM_CG,
+ SND_SOC_NOPM, 0, 0,
+ mtk_etdm3_cg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* en */
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_IN_EN", SUPPLY_SEQ_ETDM_EN,
+ ETDM_IN1_CON0, ETDM_CON0_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_IN_EN", SUPPLY_SEQ_ETDM_EN,
+ ETDM_IN2_CON0, ETDM_CON0_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ETDM1_OUT_EN", SUPPLY_SEQ_ETDM_EN,
+ ETDM_OUT1_CON0, ETDM_CON0_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ETDM2_OUT_EN", SUPPLY_SEQ_ETDM_EN,
+ ETDM_OUT2_CON0, ETDM_CON0_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ETDM3_OUT_EN", SUPPLY_SEQ_ETDM_EN,
+ ETDM_OUT3_CON0, ETDM_CON0_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DPTX_EN", SUPPLY_SEQ_DPTX_EN,
+ AFE_DPTX_CON, AFE_DPTX_CON_ON_SHIFT, 0, NULL, 0),
+
+ /* apll */
+ SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,
+ SND_SOC_NOPM, 0, 0,
+ mtk_apll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,
+ SND_SOC_NOPM, 0, 0,
+ mtk_apll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_INPUT("ETDM_INPUT"),
SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"),
};
static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
+ /* mclk */
+ {"ETDM1_IN", NULL, "ETDM1_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_IN", NULL, "ETDM2_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_IN", NULL, "ETDM1_OUT_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_IN", NULL, "ETDM2_OUT_MCLK", mtk_etdm_mclk_connect},
+
+ {"ETDM2_IN", NULL, "ETDM1_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_IN", NULL, "ETDM2_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_IN", NULL, "ETDM1_OUT_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_IN", NULL, "ETDM2_OUT_MCLK", mtk_etdm_mclk_connect},
+
+ {"ETDM1_OUT", NULL, "ETDM1_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_OUT", NULL, "ETDM2_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_OUT", NULL, "ETDM1_OUT_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM1_OUT", NULL, "ETDM2_OUT_MCLK", mtk_etdm_mclk_connect},
+
+ {"ETDM2_OUT", NULL, "ETDM1_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_IN_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_OUT", NULL, "ETDM1_OUT_MCLK", mtk_etdm_mclk_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_OUT_MCLK", mtk_etdm_mclk_connect},
+
+ {"DPTX", NULL, "DPTX_MCLK"},
+
+ {"ETDM1_IN_MCLK", NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {"ETDM1_IN_MCLK", NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+ {"ETDM2_IN_MCLK", NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {"ETDM2_IN_MCLK", NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+ {"ETDM1_OUT_MCLK", NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {"ETDM1_OUT_MCLK", NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+ {"ETDM2_OUT_MCLK", NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {"ETDM2_OUT_MCLK", NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+ {"DPTX_MCLK", NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {"DPTX_MCLK", NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+
+ /* cg */
+ {"ETDM1_IN", NULL, "ETDM1_IN_CG"},
+ {"ETDM1_IN", NULL, "ETDM2_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM1_IN", NULL, "ETDM1_OUT_CG", mtk_etdm_cowork_connect},
+ {"ETDM1_IN", NULL, "ETDM2_OUT_CG", mtk_etdm_cowork_connect},
+
+ {"ETDM2_IN", NULL, "ETDM1_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM2_IN", NULL, "ETDM2_IN_CG"},
+ {"ETDM2_IN", NULL, "ETDM1_OUT_CG", mtk_etdm_cowork_connect},
+ {"ETDM2_IN", NULL, "ETDM2_OUT_CG", mtk_etdm_cowork_connect},
+
+ {"ETDM1_OUT", NULL, "ETDM1_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM1_OUT", NULL, "ETDM2_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM1_OUT", NULL, "ETDM1_OUT_CG"},
+ {"ETDM1_OUT", NULL, "ETDM2_OUT_CG", mtk_etdm_cowork_connect},
+
+ {"ETDM2_OUT", NULL, "ETDM1_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_IN_CG", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM1_OUT_CG", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_OUT_CG"},
+
+ {"ETDM3_OUT", NULL, "ETDM3_OUT_CG"},
+ {"DPTX", NULL, "ETDM3_OUT_CG"},
+
+ /* en */
+ {"ETDM1_IN", NULL, "ETDM1_IN_EN"},
+ {"ETDM1_IN", NULL, "ETDM2_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM1_IN", NULL, "ETDM1_OUT_EN", mtk_etdm_cowork_connect},
+ {"ETDM1_IN", NULL, "ETDM2_OUT_EN", mtk_etdm_cowork_connect},
+
+ {"ETDM2_IN", NULL, "ETDM1_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM2_IN", NULL, "ETDM2_IN_EN"},
+ {"ETDM2_IN", NULL, "ETDM1_OUT_EN", mtk_etdm_cowork_connect},
+ {"ETDM2_IN", NULL, "ETDM2_OUT_EN", mtk_etdm_cowork_connect},
+
+ {"ETDM1_OUT", NULL, "ETDM1_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM1_OUT", NULL, "ETDM2_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM1_OUT", NULL, "ETDM1_OUT_EN"},
+ {"ETDM1_OUT", NULL, "ETDM2_OUT_EN", mtk_etdm_cowork_connect},
+
+ {"ETDM2_OUT", NULL, "ETDM1_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_IN_EN", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM1_OUT_EN", mtk_etdm_cowork_connect},
+ {"ETDM2_OUT", NULL, "ETDM2_OUT_EN"},
+
+ {"ETDM3_OUT", NULL, "ETDM3_OUT_EN"},
+ {"DPTX", NULL, "ETDM3_OUT_EN"},
+ {"DPTX", NULL, "DPTX_EN"},
+
+ {"ETDM1_IN_EN", NULL, APLL1_W_NAME, mtk_afe_etdm_apll_connect},
+ {"ETDM1_IN_EN", NULL, APLL2_W_NAME, mtk_afe_etdm_apll_connect},
+
+ {"ETDM2_IN_EN", NULL, APLL1_W_NAME, mtk_afe_etdm_apll_connect},
+ {"ETDM2_IN_EN", NULL, APLL2_W_NAME, mtk_afe_etdm_apll_connect},
+
+ {"ETDM1_OUT_EN", NULL, APLL1_W_NAME, mtk_afe_etdm_apll_connect},
+ {"ETDM1_OUT_EN", NULL, APLL2_W_NAME, mtk_afe_etdm_apll_connect},
+
+ {"ETDM2_OUT_EN", NULL, APLL1_W_NAME, mtk_afe_etdm_apll_connect},
+ {"ETDM2_OUT_EN", NULL, APLL2_W_NAME, mtk_afe_etdm_apll_connect},
+
+ {"ETDM3_OUT_EN", NULL, APLL1_W_NAME, mtk_afe_etdm_apll_connect},
+ {"ETDM3_OUT_EN", NULL, APLL2_W_NAME, mtk_afe_etdm_apll_connect},
+
{"I012", NULL, "ETDM2_IN"},
{"I013", NULL, "ETDM2_IN"},
{"I014", NULL, "ETDM2_IN"},
@@ -1163,64 +1674,6 @@ static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
{"ETDM2_IN", NULL, "ETDM_INPUT"},
};
-static int mt8188_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id)
-{
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *etdm_data;
- struct etdm_con_reg etdm_reg;
- unsigned long flags;
- int ret = 0;
-
- if (!is_valid_etdm_dai(dai_id))
- return -EINVAL;
- etdm_data = afe_priv->dai_priv[dai_id];
-
- dev_dbg(afe->dev, "%s [%d]%d\n", __func__, dai_id, etdm_data->en_ref_cnt);
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
- etdm_data->en_ref_cnt++;
- if (etdm_data->en_ref_cnt == 1) {
- ret = get_etdm_reg(dai_id, &etdm_reg);
- if (ret < 0)
- goto out;
-
- regmap_set_bits(afe->regmap, etdm_reg.con0, ETDM_CON0_EN);
- }
-
-out:
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
- return ret;
-}
-
-static int mt8188_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id)
-{
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *etdm_data;
- struct etdm_con_reg etdm_reg;
- unsigned long flags;
- int ret = 0;
-
- if (!is_valid_etdm_dai(dai_id))
- return -EINVAL;
- etdm_data = afe_priv->dai_priv[dai_id];
-
- dev_dbg(afe->dev, "%s [%d]%d\n", __func__, dai_id, etdm_data->en_ref_cnt);
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
- if (etdm_data->en_ref_cnt > 0) {
- etdm_data->en_ref_cnt--;
- if (etdm_data->en_ref_cnt == 0) {
- ret = get_etdm_reg(dai_id, &etdm_reg);
- if (ret < 0)
- goto out;
- regmap_clear_bits(afe->regmap, etdm_reg.con0,
- ETDM_CON0_EN);
- }
- }
-
-out:
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
- return ret;
-}
-
static int etdm_cowork_slv_sel(int id, int slave_mode)
{
if (slave_mode) {
@@ -1408,121 +1861,6 @@ static int mt8188_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id)
}
/* dai ops */
-static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *mst_etdm_data;
- int mst_dai_id;
- int slv_dai_id;
- int cg_id;
- int i;
-
- if (is_cowork_mode(dai)) {
- mst_dai_id = get_etdm_cowork_master_id(dai);
- if (!is_valid_etdm_dai(mst_dai_id))
- return -EINVAL;
- mtk_dai_etdm_enable_mclk(afe, mst_dai_id);
-
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
- if (cg_id >= 0)
- mt8188_afe_enable_clk(afe, afe_priv->clk[cg_id]);
-
- mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
-
- for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
- slv_dai_id = mst_etdm_data->cowork_slv_id[i];
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
- if (cg_id >= 0)
- mt8188_afe_enable_clk(afe,
- afe_priv->clk[cg_id]);
- }
- } else {
- mtk_dai_etdm_enable_mclk(afe, dai->id);
-
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
- if (cg_id >= 0)
- mt8188_afe_enable_clk(afe, afe_priv->clk[cg_id]);
- }
-
- return 0;
-}
-
-static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *mst_etdm_data;
- int mst_dai_id;
- int slv_dai_id;
- int cg_id;
- int ret;
- int i;
-
- if (!is_valid_etdm_dai(dai->id))
- return;
- mst_etdm_data = afe_priv->dai_priv[dai->id];
-
- dev_dbg(afe->dev, "%s(), dai id %d, prepared %d\n", __func__, dai->id,
- mst_etdm_data->is_prepared);
-
- if (mst_etdm_data->is_prepared) {
- mst_etdm_data->is_prepared = false;
-
- if (is_cowork_mode(dai)) {
- mst_dai_id = get_etdm_cowork_master_id(dai);
- if (!is_valid_etdm_dai(mst_dai_id))
- return;
- mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
-
- ret = mt8188_afe_disable_etdm(afe, mst_dai_id);
- if (ret)
- dev_dbg(afe->dev, "%s disable %d failed\n",
- __func__, mst_dai_id);
-
- for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
- slv_dai_id = mst_etdm_data->cowork_slv_id[i];
- ret = mt8188_afe_disable_etdm(afe, slv_dai_id);
- if (ret)
- dev_dbg(afe->dev, "%s disable %d failed\n",
- __func__, slv_dai_id);
- }
- } else {
- ret = mt8188_afe_disable_etdm(afe, dai->id);
- if (ret)
- dev_dbg(afe->dev, "%s disable %d failed\n",
- __func__, dai->id);
- }
- }
-
- if (is_cowork_mode(dai)) {
- mst_dai_id = get_etdm_cowork_master_id(dai);
- if (!is_valid_etdm_dai(mst_dai_id))
- return;
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
- if (cg_id >= 0)
- mt8188_afe_disable_clk(afe, afe_priv->clk[cg_id]);
-
- mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
- for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
- slv_dai_id = mst_etdm_data->cowork_slv_id[i];
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
- if (cg_id >= 0)
- mt8188_afe_disable_clk(afe,
- afe_priv->clk[cg_id]);
- }
- mtk_dai_etdm_disable_mclk(afe, mst_dai_id);
- } else {
- cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
- if (cg_id >= 0)
- mt8188_afe_disable_clk(afe, afe_priv->clk[cg_id]);
-
- mtk_dai_etdm_disable_mclk(afe, dai->id);
- }
-}
-
static int mtk_dai_etdm_fifo_mode(struct mtk_base_afe *afe,
int dai_id, unsigned int rate)
{
@@ -1759,60 +2097,6 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe,
return 0;
}
-static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id)
-{
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *etdm_data;
- struct etdm_con_reg etdm_reg;
- int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id);
- int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
- int apll_clk_id;
- int apll;
- int ret;
-
- if (clk_id < 0 || clkdiv_id < 0)
- return -EINVAL;
-
- if (!is_valid_etdm_dai(dai_id))
- return -EINVAL;
- etdm_data = afe_priv->dai_priv[dai_id];
-
- ret = get_etdm_reg(dai_id, &etdm_reg);
- if (ret < 0)
- return ret;
-
- if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
- regmap_set_bits(afe->regmap, etdm_reg.con1,
- ETDM_CON1_MCLK_OUTPUT);
- else
- regmap_clear_bits(afe->regmap, etdm_reg.con1,
- ETDM_CON1_MCLK_OUTPUT);
-
- if (etdm_data->mclk_freq) {
- apll = etdm_data->mclk_apll;
- apll_clk_id = mt8188_afe_get_mclk_source_clk_id(apll);
- if (apll_clk_id < 0)
- return apll_clk_id;
-
- /* select apll */
- ret = mt8188_afe_set_clk_parent(afe, afe_priv->clk[clk_id],
- afe_priv->clk[apll_clk_id]);
- if (ret)
- return ret;
-
- /* set rate */
- ret = mt8188_afe_set_clk_rate(afe, afe_priv->clk[clkdiv_id],
- etdm_data->mclk_freq);
- if (ret)
- return ret;
- } else {
- if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
- dev_dbg(afe->dev, "%s mclk freq = 0\n", __func__);
- }
-
- return 0;
-}
-
static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
unsigned int rate,
unsigned int channels,
@@ -1834,15 +2118,16 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
return -EINVAL;
etdm_data = afe_priv->dai_priv[dai_id];
slave_mode = etdm_data->slave_mode;
+ etdm_data->rate = rate;
ret = get_etdm_reg(dai_id, &etdm_reg);
if (ret < 0)
return ret;
- dev_dbg(afe->dev, "%s fmt %u data %u lrck %d-%u bck %d, clock %u slv %u\n",
+ dev_dbg(afe->dev, "%s fmt %u data %u lrck %d-%u bck %d, slv %u\n",
__func__, etdm_data->format, etdm_data->data_mode,
etdm_data->lrck_inv, etdm_data->lrck_width, etdm_data->bck_inv,
- etdm_data->clock_mode, etdm_data->slave_mode);
+ etdm_data->slave_mode);
dev_dbg(afe->dev, "%s rate %u channels %u bitwidth %u, id %d\n",
__func__, rate, channels, bit_width, dai_id);
@@ -1909,16 +2194,15 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
if (!is_valid_etdm_dai(mst_dai_id))
return -EINVAL;
- ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id);
- if (ret)
- return ret;
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+ if (mst_etdm_data->slots)
+ channels = mst_etdm_data->slots;
ret = mtk_dai_etdm_configure(afe, rate, channels,
bit_width, mst_dai_id);
if (ret)
return ret;
- mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
slv_dai_id = mst_etdm_data->cowork_slv_id[i];
ret = mtk_dai_etdm_configure(afe, rate, channels,
@@ -1931,9 +2215,11 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
return ret;
}
} else {
- ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
- if (ret)
- return ret;
+ if (!is_valid_etdm_dai(dai->id))
+ return -EINVAL;
+ mst_etdm_data = afe_priv->dai_priv[dai->id];
+ if (mst_etdm_data->slots)
+ channels = mst_etdm_data->slots;
ret = mtk_dai_etdm_configure(afe, rate, channels,
bit_width, dai->id);
@@ -1944,66 +2230,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int mtk_dai_etdm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *mst_etdm_data;
- int mst_dai_id;
- int slv_dai_id;
- int ret;
- int i;
-
- if (!is_valid_etdm_dai(dai->id))
- return -EINVAL;
- mst_etdm_data = afe_priv->dai_priv[dai->id];
-
- dev_dbg(afe->dev, "%s(), dai id %d, prepared %d\n", __func__, dai->id,
- mst_etdm_data->is_prepared);
-
- if (mst_etdm_data->is_prepared)
- return 0;
-
- mst_etdm_data->is_prepared = true;
-
- if (is_cowork_mode(dai)) {
- mst_dai_id = get_etdm_cowork_master_id(dai);
- if (!is_valid_etdm_dai(mst_dai_id))
- return -EINVAL;
- mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
-
- for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
- slv_dai_id = mst_etdm_data->cowork_slv_id[i];
- ret = mt8188_afe_enable_etdm(afe, slv_dai_id);
- if (ret) {
- dev_dbg(afe->dev, "%s enable %d failed\n",
- __func__, slv_dai_id);
-
- return ret;
- }
- }
-
- ret = mt8188_afe_enable_etdm(afe, mst_dai_id);
- if (ret) {
- dev_dbg(afe->dev, "%s enable %d failed\n",
- __func__, mst_dai_id);
-
- return ret;
- }
- } else {
- ret = mt8188_afe_enable_etdm(afe, dai->id);
- if (ret) {
- dev_dbg(afe->dev, "%s enable %d failed\n",
- __func__, dai->id);
-
- return ret;
- }
- }
-
- return 0;
-}
-
static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
@@ -2073,10 +2299,16 @@ static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai,
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt8188_afe_private *afe_priv = afe->platform_priv;
struct mtk_dai_etdm_priv *etdm_data;
+ int dai_id;
- if (!is_valid_etdm_dai(dai->id))
+ if (is_cowork_mode(dai))
+ dai_id = get_etdm_cowork_master_id(dai);
+ else
+ dai_id = dai->id;
+
+ if (!is_valid_etdm_dai(dai_id))
return -EINVAL;
- etdm_data = afe_priv->dai_priv[dai->id];
+ etdm_data = afe_priv->dai_priv[dai_id];
dev_dbg(dai->dev, "%s id %d slot_width %d\n",
__func__, dai->id, slot_width);
@@ -2151,53 +2383,6 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
-static int mtk_dai_hdmitx_dptx_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
-
- if (cg_id >= 0)
- mt8188_afe_enable_clk(afe, afe_priv->clk[cg_id]);
-
- mtk_dai_etdm_enable_mclk(afe, dai->id);
-
- return 0;
-}
-
-static void mtk_dai_hdmitx_dptx_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
- struct mtk_dai_etdm_priv *etdm_data;
- int ret;
-
- if (!is_valid_etdm_dai(dai->id))
- return;
- etdm_data = afe_priv->dai_priv[dai->id];
-
- if (etdm_data->is_prepared) {
- etdm_data->is_prepared = false;
- /* disable etdm_out3 */
- ret = mt8188_afe_disable_etdm(afe, dai->id);
- if (ret)
- dev_dbg(afe->dev, "%s disable failed\n", __func__);
-
- /* disable dptx interface */
- if (dai->id == MT8188_AFE_IO_DPTX)
- regmap_clear_bits(afe->regmap, AFE_DPTX_CON,
- AFE_DPTX_CON_ON);
- }
-
- mtk_dai_etdm_disable_mclk(afe, dai->id);
-
- if (cg_id >= 0)
- mt8188_afe_disable_clk(afe, afe_priv->clk[cg_id]);
-}
-
static unsigned int mtk_dai_get_dptx_ch_en(unsigned int channel)
{
switch (channel) {
@@ -2265,42 +2450,11 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream,
etdm_data->data_mode = MTK_DAI_ETDM_DATA_MULTI_PIN;
}
- ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
- if (ret)
- return ret;
-
ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
return ret;
}
-static int mtk_dai_hdmitx_dptx_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
- struct mt8188_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *etdm_data;
-
- if (!is_valid_etdm_dai(dai->id))
- return -EINVAL;
- etdm_data = afe_priv->dai_priv[dai->id];
-
- dev_dbg(afe->dev, "%s(), dai id %d, prepared %d\n", __func__, dai->id,
- etdm_data->is_prepared);
-
- if (etdm_data->is_prepared)
- return 0;
-
- etdm_data->is_prepared = true;
-
- /* enable dptx interface */
- if (dai->id == MT8188_AFE_IO_DPTX)
- regmap_set_bits(afe->regmap, AFE_DPTX_CON, AFE_DPTX_CON_ON);
-
- /* enable etdm_out3 */
- return mt8188_afe_enable_etdm(afe, dai->id);
-}
-
static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
int clk_id,
unsigned int freq,
@@ -2322,20 +2476,14 @@ static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
}
static const struct snd_soc_dai_ops mtk_dai_etdm_ops = {
- .startup = mtk_dai_etdm_startup,
- .shutdown = mtk_dai_etdm_shutdown,
.hw_params = mtk_dai_etdm_hw_params,
- .prepare = mtk_dai_etdm_prepare,
.set_sysclk = mtk_dai_etdm_set_sysclk,
.set_fmt = mtk_dai_etdm_set_fmt,
.set_tdm_slot = mtk_dai_etdm_set_tdm_slot,
};
static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = {
- .startup = mtk_dai_hdmitx_dptx_startup,
- .shutdown = mtk_dai_hdmitx_dptx_shutdown,
.hw_params = mtk_dai_hdmitx_dptx_hw_params,
- .prepare = mtk_dai_hdmitx_dptx_prepare,
.set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk,
.set_fmt = mtk_dai_etdm_set_fmt,
};
diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
index 919d74ea1934..ac69c23e0da1 100644
--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
+++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
@@ -6,6 +6,8 @@
* Author: Trevor Wu <trevor.wu@mediatek.com>
*/
+#include <linux/bitfield.h>
+#include <linux/input.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
@@ -13,10 +15,36 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "mt8188-afe-common.h"
+#include "../../codecs/nau8825.h"
#include "../../codecs/mt6359.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-soundcard-driver.h"
+#define CKSYS_AUD_TOP_CFG 0x032c
+ #define RG_TEST_ON BIT(0)
+ #define RG_TEST_TYPE BIT(2)
+#define CKSYS_AUD_TOP_MON 0x0330
+ #define TEST_MISO_COUNT_1 GENMASK(3, 0)
+ #define TEST_MISO_COUNT_2 GENMASK(7, 4)
+ #define TEST_MISO_DONE_1 BIT(28)
+ #define TEST_MISO_DONE_2 BIT(29)
+
+#define NAU8825_HS_PRESENT BIT(0)
+
+/*
+ * Maxim MAX98390
+ */
+#define MAX98390_CODEC_DAI "max98390-aif1"
+#define MAX98390_DEV0_NAME "max98390.0-0038" /* rear right */
+#define MAX98390_DEV1_NAME "max98390.0-0039" /* rear left */
+#define MAX98390_DEV2_NAME "max98390.0-003a" /* front right */
+#define MAX98390_DEV3_NAME "max98390.0-003b" /* front left */
+
+/*
+ * Nau88l25
+ */
+#define NAU8825_CODEC_DAI "nau8825-hifi"
+
/* FE */
SND_SOC_DAILINK_DEFS(playback2,
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
@@ -99,8 +127,8 @@ SND_SOC_DAILINK_DEFS(capture10,
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* BE */
-SND_SOC_DAILINK_DEFS(adda,
- DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
+SND_SOC_DAILINK_DEFS(dl_src,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
"mt6359-snd-codec-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
@@ -140,9 +168,44 @@ SND_SOC_DAILINK_DEFS(pcm1,
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(ul_src,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+ "mt6359-snd-codec-aif1"),
+ COMP_CODEC("dmic-codec",
+ "dmic-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
struct mt8188_mt6359_priv {
struct snd_soc_jack dp_jack;
struct snd_soc_jack hdmi_jack;
+ struct snd_soc_jack headset_jack;
+ void *private_data;
+};
+
+static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = {
+ {
+ .pin = "HDMI",
+ .mask = SND_JACK_LINEOUT,
+ },
+};
+
+static struct snd_soc_jack_pin mt8188_dp_jack_pins[] = {
+ {
+ .pin = "DP",
+ .mask = SND_JACK_LINEOUT,
+ },
+};
+
+static struct snd_soc_jack_pin nau8825_jack_pins[] = {
+ {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
};
struct mt8188_card_data {
@@ -150,9 +213,39 @@ struct mt8188_card_data {
unsigned long quirk;
};
+static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Ext Spk"),
+};
+
+static const struct snd_soc_dapm_widget mt8188_dumb_spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_kcontrol_new mt8188_dual_spk_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Left Spk"),
+ SOC_DAPM_PIN_SWITCH("Right Spk"),
+};
+
+static const struct snd_soc_dapm_widget mt8188_dual_spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Left Spk", NULL),
+ SND_SOC_DAPM_SPK("Right Spk", NULL),
+};
+
+static const struct snd_kcontrol_new mt8188_rear_spk_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Rear Left Spk"),
+ SOC_DAPM_PIN_SWITCH("Rear Right Spk"),
+};
+
+static const struct snd_soc_dapm_widget mt8188_rear_spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Rear Left Spk", NULL),
+ SND_SOC_DAPM_SPK("Rear Right Spk", NULL),
+};
+
static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_SINK("HDMI"),
+ SND_SOC_DAPM_SINK("DP"),
};
static const struct snd_kcontrol_new mt8188_mt6359_controls[] = {
@@ -160,8 +253,13 @@ static const struct snd_kcontrol_new mt8188_mt6359_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
-#define CKSYS_AUD_TOP_CFG 0x032c
-#define CKSYS_AUD_TOP_MON 0x0330
+static const struct snd_soc_dapm_widget mt8188_nau8825_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+};
+
+static const struct snd_kcontrol_new mt8188_nau8825_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+};
static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
{
@@ -174,13 +272,13 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
struct mtkaif_param *param;
int chosen_phase_1, chosen_phase_2;
int prev_cycle_1, prev_cycle_2;
- int test_done_1, test_done_2;
+ u8 test_done_1, test_done_2;
int cycle_1, cycle_2;
int mtkaif_chosen_phase[MT8188_MTKAIF_MISO_NUM];
int mtkaif_phase_cycle[MT8188_MTKAIF_MISO_NUM];
int mtkaif_calibration_num_phase;
bool mtkaif_calibration_ok;
- unsigned int monitor = 0;
+ u32 monitor = 0;
int counter;
int phase;
int i;
@@ -212,8 +310,7 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
mt6359_mtkaif_calibration_enable(cmpnt_codec);
/* set test type to synchronizer pulse */
- regmap_update_bits(afe_priv->topckgen,
- CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
+ regmap_write(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, RG_TEST_TYPE);
mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */
mtkaif_calibration_ok = true;
@@ -223,7 +320,7 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
phase, phase, phase);
- regmap_set_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1);
+ regmap_set_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, RG_TEST_ON);
test_done_1 = 0;
test_done_2 = 0;
@@ -235,20 +332,19 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
while (!(test_done_1 & test_done_2)) {
regmap_read(afe_priv->topckgen,
CKSYS_AUD_TOP_MON, &monitor);
- test_done_1 = (monitor >> 28) & 0x1;
- test_done_2 = (monitor >> 29) & 0x1;
+ test_done_1 = FIELD_GET(TEST_MISO_DONE_1, monitor);
+ test_done_2 = FIELD_GET(TEST_MISO_DONE_2, monitor);
if (test_done_1 == 1)
- cycle_1 = monitor & 0xf;
+ cycle_1 = FIELD_GET(TEST_MISO_COUNT_1, monitor);
if (test_done_2 == 1)
- cycle_2 = (monitor >> 4) & 0xf;
+ cycle_2 = FIELD_GET(TEST_MISO_COUNT_2, monitor);
/* handle if never test done */
if (++counter > 10000) {
- dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, monitor 0x%x\n",
- __func__,
- cycle_1, cycle_2, monitor);
+ dev_err(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, monitor 0x%x\n",
+ __func__, cycle_1, cycle_2, monitor);
mtkaif_calibration_ok = false;
break;
}
@@ -271,7 +367,7 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1] = prev_cycle_2;
}
- regmap_clear_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1);
+ regmap_clear_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, RG_TEST_ON);
if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] >= 0 &&
mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] >= 0)
@@ -307,8 +403,8 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++)
param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i];
- dev_info(afe->dev, "%s(), end, calibration ok %d\n",
- __func__, param->mtkaif_calibration_ok);
+ dev_dbg(afe->dev, "%s(), end, calibration ok %d\n",
+ __func__, param->mtkaif_calibration_ok);
return 0;
}
@@ -345,7 +441,7 @@ enum {
DAI_LINK_UL8_FE,
DAI_LINK_UL9_FE,
DAI_LINK_UL10_FE,
- DAI_LINK_ADDA_BE,
+ DAI_LINK_DL_SRC_BE,
DAI_LINK_DPTX_BE,
DAI_LINK_ETDM1_IN_BE,
DAI_LINK_ETDM2_IN_BE,
@@ -353,6 +449,7 @@ enum {
DAI_LINK_ETDM2_OUT_BE,
DAI_LINK_ETDM3_OUT_BE,
DAI_LINK_PCM1_BE,
+ DAI_LINK_UL_SRC_BE,
};
static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream,
@@ -389,19 +486,23 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
int ret = 0;
- ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
- &priv->hdmi_jack);
+ ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack",
+ SND_JACK_LINEOUT, &priv->hdmi_jack,
+ mt8188_hdmi_jack_pins,
+ ARRAY_SIZE(mt8188_hdmi_jack_pins));
if (ret) {
- dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
+ dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
return ret;
}
ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL);
- if (ret)
- dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
- __func__, component->name, ret);
+ if (ret) {
+ dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
+ __func__, component->name, ret);
+ return ret;
+ }
- return ret;
+ return 0;
}
static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
@@ -410,21 +511,207 @@ static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
int ret = 0;
- ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT,
- &priv->dp_jack);
+ ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT,
+ &priv->dp_jack, mt8188_dp_jack_pins,
+ ARRAY_SIZE(mt8188_dp_jack_pins));
if (ret) {
- dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
+ dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
return ret;
}
ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL);
- if (ret)
- dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
- __func__, component->name, ret);
+ if (ret) {
+ dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
+ __func__, component->name, ret);
+ return ret;
+ }
- return ret;
+ return 0;
+}
+
+static int mt8188_dumb_amp_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ int ret = 0;
+
+ ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dumb_spk_widgets,
+ ARRAY_SIZE(mt8188_dumb_spk_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8188_dumb_spk_controls,
+ ARRAY_SIZE(mt8188_dumb_spk_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8188_max98390_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ unsigned int bit_width = params_width(params);
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai;
+ int i;
+
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0xf, 4, bit_width);
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ if (!strcmp(codec_dai->component->name, MAX98390_DEV0_NAME))
+ snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x3, 4, bit_width);
+
+ if (!strcmp(codec_dai->component->name, MAX98390_DEV1_NAME))
+ snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x3, 4, bit_width);
+
+ if (!strcmp(codec_dai->component->name, MAX98390_DEV2_NAME))
+ snd_soc_dai_set_tdm_slot(codec_dai, 0x2, 0x3, 4, bit_width);
+
+ if (!strcmp(codec_dai->component->name, MAX98390_DEV3_NAME))
+ snd_soc_dai_set_tdm_slot(codec_dai, 0x1, 0x3, 4, bit_width);
+ }
+ return 0;
+}
+
+static const struct snd_soc_ops mt8188_max98390_ops = {
+ .hw_params = mt8188_max98390_hw_params,
+};
+
+static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ int ret;
+
+ /* add regular speakers dapm route */
+ ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dual_spk_widgets,
+ ARRAY_SIZE(mt8188_dual_spk_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Left/Right Speaker widget, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8188_dual_spk_controls,
+ ARRAY_SIZE(mt8188_dual_spk_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Left/Right card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ if (rtd->dai_link->num_codecs <= 2)
+ return 0;
+
+ /* add widgets/controls/dapm for rear speakers */
+ ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_rear_spk_widgets,
+ ARRAY_SIZE(mt8188_rear_spk_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Rear Speaker widget, ret %d\n", ret);
+ /* Don't need to add routes if widget addition failed */
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8188_rear_spk_controls,
+ ARRAY_SIZE(mt8188_rear_spk_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Rear card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8188_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
+ struct snd_soc_jack *jack = &priv->headset_jack;
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets,
+ ARRAY_SIZE(mt8188_nau8825_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8188_nau8825_controls,
+ ARRAY_SIZE(mt8188_nau8825_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3,
+ jack,
+ nau8825_jack_pins,
+ ARRAY_SIZE(nau8825_jack_pins));
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+};
+
+static void mt8188_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
+
+ snd_soc_component_set_jack(component, NULL, NULL);
}
+static int mt8188_nau8825_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ unsigned int rate = params_rate(params);
+ unsigned int bit_width = params_width(params);
+ int clk_freq, ret;
+
+ clk_freq = rate * 2 * bit_width;
+
+ /* Configure clock for codec */
+ ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret);
+ return ret;
+ }
+
+ /* Configure pll for codec */
+ ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq,
+ params_rate(params) * 256);
+ if (ret < 0) {
+ dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8188_nau8825_ops = {
+ .hw_params = mt8188_nau8825_hw_params,
+};
static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
/* FE */
[DAI_LINK_DL2_FE] = {
@@ -604,13 +891,11 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DAILINK_REG(capture10),
},
/* BE */
- [DAI_LINK_ADDA_BE] = {
- .name = "ADDA_BE",
+ [DAI_LINK_DL_SRC_BE] = {
+ .name = "DL_SRC_BE",
.no_pcm = 1,
.dpcm_playback = 1,
- .dpcm_capture = 1,
- .init = mt8188_mt6359_init,
- SND_SOC_DAILINK_REG(adda),
+ SND_SOC_DAILINK_REG(dl_src),
},
[DAI_LINK_DPTX_BE] = {
.name = "DPTX_BE",
@@ -676,8 +961,48 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(pcm1),
},
+ [DAI_LINK_UL_SRC_BE] = {
+ .name = "UL_SRC_BE",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(ul_src),
+ },
};
+static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
+{
+ struct snd_ctl_elem_id sid;
+
+ memset(&sid, 0, sizeof(sid));
+ strcpy(sid.name, name);
+ sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ return snd_ctl_find_id(card, &sid);
+}
+
+static void mt8188_fixup_controls(struct snd_soc_card *card)
+{
+ struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card);
+ struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data;
+ struct snd_kcontrol *kctl;
+
+ if (card_data->quirk & NAU8825_HS_PRESENT) {
+ struct snd_soc_dapm_widget *w, *next_w;
+
+ for_each_card_widgets_safe(card, w, next_w) {
+ if (strcmp(w->name, "Headphone"))
+ continue;
+
+ snd_soc_dapm_free_widget(w);
+ }
+
+ kctl = ctl_find(card->snd_card, "Headphone Switch");
+ if (kctl)
+ snd_ctl_remove(card->snd_card, kctl);
+ else
+ dev_warn(card->dev, "Cannot find ctl : Headphone Switch\n");
+ }
+}
+
static struct snd_soc_card mt8188_mt6359_soc_card = {
.owner = THIS_MODULE,
.dai_link = mt8188_mt6359_dai_links,
@@ -686,6 +1011,7 @@ static struct snd_soc_card mt8188_mt6359_soc_card = {
.num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets),
.controls = mt8188_mt6359_controls,
.num_controls = ARRAY_SIZE(mt8188_mt6359_controls),
+ .fixup_controls = mt8188_fixup_controls,
};
static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
@@ -695,6 +1021,10 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
struct mt8188_mt6359_priv *priv;
struct mt8188_card_data *card_data;
struct snd_soc_dai_link *dai_link;
+ bool init_mt6359 = false;
+ bool init_nau8825 = false;
+ bool init_max98390 = false;
+ bool init_dumb = false;
int ret, i;
card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev);
@@ -739,9 +1069,41 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8188_hdmi_codec_init;
+ } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 ||
+ strcmp(dai_link->name, "UL_SRC_BE") == 0) {
+ if (!init_mt6359) {
+ dai_link->init = mt8188_mt6359_init;
+ init_mt6359 = true;
+ }
+ } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 ||
+ strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 ||
+ strcmp(dai_link->name, "ETDM1_IN_BE") == 0 ||
+ strcmp(dai_link->name, "ETDM2_IN_BE") == 0) {
+ if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) {
+ dai_link->ops = &mt8188_max98390_ops;
+ if (!init_max98390) {
+ dai_link->init = mt8188_max98390_codec_init;
+ init_max98390 = true;
+ }
+ } else if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) {
+ dai_link->ops = &mt8188_nau8825_ops;
+ if (!init_nau8825) {
+ dai_link->init = mt8188_nau8825_codec_init;
+ dai_link->exit = mt8188_nau8825_codec_exit;
+ init_nau8825 = true;
+ }
+ } else {
+ if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) {
+ if (!init_dumb) {
+ dai_link->init = mt8188_dumb_amp_init;
+ init_dumb = true;
+ }
+ }
+ }
}
}
+ priv->private_data = card_data;
snd_soc_card_set_drvdata(card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, card);
@@ -758,12 +1120,15 @@ static struct mt8188_card_data mt8188_evb_card = {
.name = "mt8188_mt6359",
};
+static struct mt8188_card_data mt8188_nau8825_card = {
+ .name = "mt8188_nau8825",
+ .quirk = NAU8825_HS_PRESENT,
+};
+
static const struct of_device_id mt8188_mt6359_dt_match[] = {
- {
- .compatible = "mediatek,mt8188-mt6359-evb",
- .data = &mt8188_evb_card,
- },
- {},
+ { .compatible = "mediatek,mt8188-mt6359-evb", .data = &mt8188_evb_card, },
+ { .compatible = "mediatek,mt8188-nau8825", .data = &mt8188_nau8825_card, },
+ { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mt8188_mt6359_dt_match);
diff --git a/sound/soc/mediatek/mt8188/mt8188-reg.h b/sound/soc/mediatek/mt8188/mt8188-reg.h
index 51cd1a83dd9d..bdd885419ff3 100644
--- a/sound/soc/mediatek/mt8188/mt8188-reg.h
+++ b/sound/soc/mediatek/mt8188/mt8188-reg.h
@@ -3007,6 +3007,7 @@
#define ETDM_CON0_SLAVE_MODE BIT(5)
#define ETDM_CON0_SYNC_MODE BIT(1)
#define ETDM_CON0_EN BIT(0)
+#define ETDM_CON0_EN_SHIFT 0
#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28)
@@ -3108,6 +3109,7 @@
#define AFE_DPTX_CON_CH_NUM_8CH (0x1 << 1)
#define AFE_DPTX_CON_CH_NUM_MASK BIT(1)
#define AFE_DPTX_CON_ON BIT(0)
+#define AFE_DPTX_CON_ON_SHIFT 0
/* AFE_ADDA_DL_SRC2_CON0 */
#define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28)
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-control.c b/sound/soc/mediatek/mt8192/mt8192-afe-control.c
index 9163e05e54e1..d01b62e10088 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-control.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-control.c
@@ -6,8 +6,6 @@
// Author: Shane Chien <shane.chien@mediatek.com>
//
-#include <linux/pm_runtime.h>
-
#include "mt8192-afe-common.h"
enum {
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
index 9ca2cb8c8a9c..f35318ae0739 100644
--- a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
@@ -410,11 +410,6 @@ int mt8195_afe_init_clock(struct mtk_base_afe *afe)
return 0;
}
-void mt8195_afe_deinit_clock(struct mtk_base_afe *afe)
-{
- mt8195_audsys_clk_unregister(afe);
-}
-
int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
{
int ret;
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.h b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
index 40663e31becd..a08c0ee6c860 100644
--- a/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
@@ -101,7 +101,6 @@ int mt8195_afe_get_mclk_source_clk_id(int sel);
int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll);
int mt8195_afe_get_default_mclk_source_by_rate(int rate);
int mt8195_afe_init_clock(struct mtk_base_afe *afe);
-void mt8195_afe_deinit_clock(struct mtk_base_afe *afe);
int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk);
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
index 9e45efeada55..a0f2012211fb 100644
--- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
@@ -3030,28 +3030,6 @@ static const struct reg_sequence mt8195_cg_patch[] = {
{ AUDIO_TOP_CON1, 0xfffffff8 },
};
-static int mt8195_afe_init_registers(struct mtk_base_afe *afe)
-{
- return regmap_multi_reg_write(afe->regmap,
- mt8195_afe_reg_defaults,
- ARRAY_SIZE(mt8195_afe_reg_defaults));
-}
-
-static void mt8195_afe_parse_of(struct mtk_base_afe *afe,
- struct device_node *np)
-{
-#if IS_ENABLED(CONFIG_SND_SOC_MT6359)
- struct mt8195_afe_private *afe_priv = afe->platform_priv;
-
- afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
- "mediatek,topckgen");
- if (IS_ERR(afe_priv->topckgen)) {
- dev_info(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
- __func__, PTR_ERR(afe_priv->topckgen));
- }
-#endif
-}
-
static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
@@ -3062,10 +3040,8 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
struct snd_soc_component *component;
ret = of_reserved_mem_device_init(dev);
- if (ret) {
- dev_err(dev, "failed to assign memory region: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to assign memory region\n");
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
if (ret)
@@ -3089,24 +3065,17 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
/* initial audio related clock */
ret = mt8195_afe_init_clock(afe);
- if (ret) {
- dev_err(dev, "init clock error\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "init clock error\n");
/* reset controller to reset audio regs before regmap cache */
rstc = devm_reset_control_get_exclusive(dev, "audiosys");
- if (IS_ERR(rstc)) {
- ret = PTR_ERR(rstc);
- dev_err(dev, "could not get audiosys reset:%d\n", ret);
- return ret;
- }
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc), "could not get audiosys reset\n");
ret = reset_control_reset(rstc);
- if (ret) {
- dev_err(dev, "failed to trigger audio reset:%d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to trigger audio reset\n");
spin_lock_init(&afe_priv->afe_ctrl_lock);
@@ -3143,30 +3112,22 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq_id, mt8195_afe_irq_handler,
IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
- if (ret) {
- dev_err(dev, "could not request_irq for asys-isr\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "could not request_irq for asys-isr\n");
/* init sub_dais */
INIT_LIST_HEAD(&afe->sub_dais);
for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
ret = dai_register_cbs[i](afe);
- if (ret) {
- dev_warn(dev, "dai register i %d fail, ret %d\n",
- i, ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "dai cb%i register fail\n", i);
}
/* init dai_driver and component_driver */
ret = mtk_afe_combine_sub_dai(afe);
- if (ret) {
- dev_warn(dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
- ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n");
afe->mtk_afe_hardware = &mt8195_afe_hardware;
afe->memif_fs = mt8195_memif_fs;
@@ -3177,18 +3138,21 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, afe);
- mt8195_afe_parse_of(afe, pdev->dev.of_node);
-
- pm_runtime_enable(dev);
- if (!pm_runtime_enabled(dev)) {
- ret = mt8195_afe_runtime_resume(dev);
- if (ret)
- return ret;
- }
+ afe_priv->topckgen = syscon_regmap_lookup_by_phandle(dev->of_node, "mediatek,topckgen");
+ if (IS_ERR(afe_priv->topckgen))
+ dev_dbg(afe->dev, "Cannot find topckgen controller: %ld\n",
+ PTR_ERR(afe_priv->topckgen));
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(dev);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to resume device\n");
afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
&mt8195_afe_regmap_config);
@@ -3236,9 +3200,15 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
goto err_pm_put;
}
- mt8195_afe_init_registers(afe);
+ ret = regmap_multi_reg_write(afe->regmap, mt8195_afe_reg_defaults,
+ ARRAY_SIZE(mt8195_afe_reg_defaults));
+ if (ret)
+ goto err_pm_put;
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to suspend device\n");
- pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
regcache_cache_only(afe->regmap, true);
@@ -3248,22 +3218,17 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
err_pm_put:
pm_runtime_put_sync(dev);
- pm_runtime_disable(dev);
return ret;
}
static void mt8195_afe_pcm_dev_remove(struct platform_device *pdev)
{
- struct mtk_base_afe *afe = platform_get_drvdata(pdev);
-
snd_soc_unregister_component(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
mt8195_afe_runtime_suspend(&pdev->dev);
-
- mt8195_afe_deinit_clock(afe);
}
static const struct of_device_id mt8195_afe_pcm_dt_match[] = {
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
index e0670e0dbd5b..38594bc3f2f7 100644
--- a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
@@ -148,6 +148,29 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19", "top_asm_h", 19),
};
+static void mt8195_audsys_clk_unregister(void *data)
+{
+ struct mtk_base_afe *afe = data;
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ int i;
+
+ if (!afe_priv)
+ return;
+
+ for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+ cl = afe_priv->lookup[i];
+ if (!cl)
+ continue;
+
+ clk = cl->clk;
+ clk_unregister_gate(clk);
+
+ clkdev_drop(cl);
+ }
+}
+
int mt8195_audsys_clk_register(struct mtk_base_afe *afe)
{
struct mt8195_afe_private *afe_priv = afe->platform_priv;
@@ -188,27 +211,5 @@ int mt8195_audsys_clk_register(struct mtk_base_afe *afe)
afe_priv->lookup[i] = cl;
}
- return 0;
-}
-
-void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe)
-{
- struct mt8195_afe_private *afe_priv = afe->platform_priv;
- struct clk *clk;
- struct clk_lookup *cl;
- int i;
-
- if (!afe_priv)
- return;
-
- for (i = 0; i < CLK_AUD_NR_CLK; i++) {
- cl = afe_priv->lookup[i];
- if (!cl)
- continue;
-
- clk = cl->clk;
- clk_unregister_gate(clk);
-
- clkdev_drop(cl);
- }
+ return devm_add_action_or_reset(afe->dev, mt8195_audsys_clk_unregister, afe);
}
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
index 239d31016ba7..69db2dd1c9e0 100644
--- a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
@@ -10,6 +10,5 @@
#define _MT8195_AUDSYS_CLK_H_
int mt8195_audsys_clk_register(struct mtk_base_afe *afe);
-void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe);
#endif