Commit e5d2bd41 authored by Trevor Wu's avatar Trevor Wu Committed by Mark Brown

ASoC: mediatek: mt8188: revise ETDM control flow

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
parent 2664c879
...@@ -21,6 +21,13 @@ ...@@ -21,6 +21,13 @@
#define ETDM_TO_DAI_ID(x) ((x) + MT8188_AFE_IO_ETDM_START) #define ETDM_TO_DAI_ID(x) ((x) + MT8188_AFE_IO_ETDM_START)
#define ENUM_TO_STR(x) #x #define ENUM_TO_STR(x) #x
enum {
SUPPLY_SEQ_ETDM_MCLK,
SUPPLY_SEQ_ETDM_CG,
SUPPLY_SEQ_DPTX_EN,
SUPPLY_SEQ_ETDM_EN,
};
enum { enum {
MTK_DAI_ETDM_FORMAT_I2S = 0, MTK_DAI_ETDM_FORMAT_I2S = 0,
MTK_DAI_ETDM_FORMAT_LJ, MTK_DAI_ETDM_FORMAT_LJ,
...@@ -84,7 +91,6 @@ struct mtk_dai_etdm_rate { ...@@ -84,7 +91,6 @@ struct mtk_dai_etdm_rate {
}; };
struct mtk_dai_etdm_priv { struct mtk_dai_etdm_priv {
unsigned int clock_mode;
unsigned int data_mode; unsigned int data_mode;
bool slave_mode; bool slave_mode;
bool lrck_inv; bool lrck_inv;
...@@ -100,8 +106,6 @@ struct mtk_dai_etdm_priv { ...@@ -100,8 +106,6 @@ struct mtk_dai_etdm_priv {
unsigned int cowork_slv_count; unsigned int cowork_slv_count;
int cowork_slv_id[MT8188_AFE_IO_ETDM_NUM - 1]; //dai_id int cowork_slv_id[MT8188_AFE_IO_ETDM_NUM - 1]; //dai_id
bool in_disable_ch[MT8188_ETDM_MAX_CHANNELS]; 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[] = { 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) ...@@ -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) 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 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 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; 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]); mt8188_afe_enable_clk(afe, afe_priv->clk[clkdiv_id]);
return 0; return 0;
...@@ -361,12 +433,207 @@ static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id) ...@@ -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) static int mtk_dai_etdm_disable_mclk(struct mtk_base_afe *afe, int dai_id)
{ {
struct mt8188_afe_private *afe_priv = afe->platform_priv; 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); 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; return -EINVAL;
mt8188_afe_disable_clk(afe, afe_priv->clk[clkdiv_id]); 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; return 0;
} }
...@@ -906,11 +1173,141 @@ static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = { ...@@ -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, SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
&hdmi_ch7_mux_control), &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_INPUT("ETDM_INPUT"),
SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"), SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"),
}; };
static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { 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"}, {"I012", NULL, "ETDM2_IN"},
{"I013", NULL, "ETDM2_IN"}, {"I013", NULL, "ETDM2_IN"},
{"I014", NULL, "ETDM2_IN"}, {"I014", NULL, "ETDM2_IN"},
...@@ -1163,64 +1560,6 @@ static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { ...@@ -1163,64 +1560,6 @@ static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
{"ETDM2_IN", NULL, "ETDM_INPUT"}, {"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) static int etdm_cowork_slv_sel(int id, int slave_mode)
{ {
if (slave_mode) { if (slave_mode) {
...@@ -1408,121 +1747,6 @@ static int mt8188_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id) ...@@ -1408,121 +1747,6 @@ static int mt8188_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id)
} }
/* dai ops */ /* 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, static int mtk_dai_etdm_fifo_mode(struct mtk_base_afe *afe,
int dai_id, unsigned int rate) int dai_id, unsigned int rate)
{ {
...@@ -1759,60 +1983,6 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, ...@@ -1759,60 +1983,6 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe,
return 0; 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, static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
unsigned int rate, unsigned int rate,
unsigned int channels, unsigned int channels,
...@@ -1839,10 +2009,10 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, ...@@ -1839,10 +2009,10 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
if (ret < 0) if (ret < 0)
return ret; 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, __func__, etdm_data->format, etdm_data->data_mode,
etdm_data->lrck_inv, etdm_data->lrck_width, etdm_data->bck_inv, 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", dev_dbg(afe->dev, "%s rate %u channels %u bitwidth %u, id %d\n",
__func__, rate, channels, bit_width, dai_id); __func__, rate, channels, bit_width, dai_id);
...@@ -1913,10 +2083,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, ...@@ -1913,10 +2083,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
if (mst_etdm_data->slots) if (mst_etdm_data->slots)
channels = 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, ret = mtk_dai_etdm_configure(afe, rate, channels,
bit_width, mst_dai_id); bit_width, mst_dai_id);
if (ret) if (ret)
...@@ -1940,10 +2106,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, ...@@ -1940,10 +2106,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
if (mst_etdm_data->slots) if (mst_etdm_data->slots)
channels = 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, ret = mtk_dai_etdm_configure(afe, rate, channels,
bit_width, dai->id); bit_width, dai->id);
if (ret) if (ret)
...@@ -1953,66 +2115,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, ...@@ -1953,66 +2115,6 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
return 0; 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) 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; 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) ...@@ -2166,53 +2268,6 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0; 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) static unsigned int mtk_dai_get_dptx_ch_en(unsigned int channel)
{ {
switch (channel) { switch (channel) {
...@@ -2280,42 +2335,11 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream, ...@@ -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; 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); ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
return ret; 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, static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
int clk_id, int clk_id,
unsigned int freq, unsigned int freq,
...@@ -2337,20 +2361,14 @@ static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai, ...@@ -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 = { 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, .hw_params = mtk_dai_etdm_hw_params,
.prepare = mtk_dai_etdm_prepare,
.set_sysclk = mtk_dai_etdm_set_sysclk, .set_sysclk = mtk_dai_etdm_set_sysclk,
.set_fmt = mtk_dai_etdm_set_fmt, .set_fmt = mtk_dai_etdm_set_fmt,
.set_tdm_slot = mtk_dai_etdm_set_tdm_slot, .set_tdm_slot = mtk_dai_etdm_set_tdm_slot,
}; };
static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = { 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, .hw_params = mtk_dai_hdmitx_dptx_hw_params,
.prepare = mtk_dai_hdmitx_dptx_prepare,
.set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk, .set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk,
.set_fmt = mtk_dai_etdm_set_fmt, .set_fmt = mtk_dai_etdm_set_fmt,
}; };
......
...@@ -3007,6 +3007,7 @@ ...@@ -3007,6 +3007,7 @@
#define ETDM_CON0_SLAVE_MODE BIT(5) #define ETDM_CON0_SLAVE_MODE BIT(5)
#define ETDM_CON0_SYNC_MODE BIT(1) #define ETDM_CON0_SYNC_MODE BIT(1)
#define ETDM_CON0_EN BIT(0) #define ETDM_CON0_EN BIT(0)
#define ETDM_CON0_EN_SHIFT 0
#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28) #define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28)
...@@ -3108,6 +3109,7 @@ ...@@ -3108,6 +3109,7 @@
#define AFE_DPTX_CON_CH_NUM_8CH (0x1 << 1) #define AFE_DPTX_CON_CH_NUM_8CH (0x1 << 1)
#define AFE_DPTX_CON_CH_NUM_MASK BIT(1) #define AFE_DPTX_CON_CH_NUM_MASK BIT(1)
#define AFE_DPTX_CON_ON BIT(0) #define AFE_DPTX_CON_ON BIT(0)
#define AFE_DPTX_CON_ON_SHIFT 0
/* AFE_ADDA_DL_SRC2_CON0 */ /* AFE_ADDA_DL_SRC2_CON0 */
#define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28) #define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment