ASoC: mediatek: mt8188: revise ETDM control flow
authorTrevor Wu <trevor.wu@mediatek.com>
Wed, 10 May 2023 03:55:20 +0000 (11:55 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 15 May 2023 11:05:08 +0000 (20:05 +0900)
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
Link: https://lore.kernel.org/r/20230510035526.18137-4-trevor.wu@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org
sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
sound/soc/mediatek/mt8188/mt8188-reg.h

index fddecf5..fd6e39a 100644 (file)
 #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,
        MTK_DAI_ETDM_FORMAT_RJ,
@@ -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,
 };
index 51cd1a8..bdd8854 100644 (file)
 #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)
 
 #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)