diff mbox series

[v2,3/7] ASoC: mediatek: mt8188: revise ETDM control flow

Message ID 168207178248.26.14094839271833938369@mailman-core.alsa-project.org
State Superseded
Headers show
Series [v2,1/7] ASoC: mediatek: mt8188: remove supply AUDIO_HIRES | expand

Commit Message

Trevor Wu April 21, 2023, 10:09 a.m. UTC
Replace register controls in snd_soc_dai_ops with snd_soc_dapm_widgets.
startup, shutdown and trigger ops are removed, and create DAPM_SUPPLY
to handle mclk, clock gating and etdm enabling. Additionally, mclk setup
sequence is also updated because of new supply enabling sequence.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
---
 sound/soc/mediatek/mt8188/mt8188-dai-etdm.c | 790 ++++++++++----------
 sound/soc/mediatek/mt8188/mt8188-reg.h      |   2 +
 2 files changed, 406 insertions(+), 386 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
index fddecf5bf7c6..fd6e39a1e4c1 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
@@ -21,6 +21,13 @@ 
 #define ETDM_TO_DAI_ID(x) ((x) + MT8188_AFE_IO_ETDM_START)
 #define ENUM_TO_STR(x)	#x
 
+enum {
+	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,
@@ -84,7 +91,6 @@  struct mtk_dai_etdm_rate {
 };
 
 struct mtk_dai_etdm_priv {
-	unsigned int clock_mode;
 	unsigned int data_mode;
 	bool slave_mode;
 	bool lrck_inv;
@@ -100,8 +106,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,14 +349,82 @@  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
+		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 (!is_valid_etdm_dai(dai_id))
+		return -EINVAL;
+	etdm_data = afe_priv->dai_priv[dai_id];
 
-	if (clkdiv_id < 0)
+	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]);
 
 	return 0;
@@ -361,12 +433,207 @@  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_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_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 +1173,141 @@  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),
+
 	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"},
+
+	/* 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"},
+
 	{"I012", NULL, "ETDM2_IN"},
 	{"I013", NULL, "ETDM2_IN"},
 	{"I014", NULL, "ETDM2_IN"},
@@ -1163,64 +1560,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 +1747,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 +1983,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,
@@ -1839,10 +2009,10 @@  static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
 	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);
 
@@ -1913,10 +2083,6 @@  static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
 		if (mst_etdm_data->slots)
 			channels = mst_etdm_data->slots;
 
-		ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id);
-		if (ret)
-			return ret;
-
 		ret = mtk_dai_etdm_configure(afe, rate, channels,
 					     bit_width, mst_dai_id);
 		if (ret)
@@ -1940,10 +2106,6 @@  static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
 		if (mst_etdm_data->slots)
 			channels = mst_etdm_data->slots;
 
-		ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
-		if (ret)
-			return ret;
-
 		ret = mtk_dai_etdm_configure(afe, rate, channels,
 					     bit_width, dai->id);
 		if (ret)
@@ -1953,66 +2115,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;
@@ -2166,53 +2268,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) {
@@ -2280,42 +2335,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,
@@ -2337,20 +2361,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-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)