brintos

brintos / linux-shallow public Read only

0
0
Text · 18.1 KiB · ef2801f Raw
644 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// MediaTek ALSA SoC Audio DAI TDM Control4//5// Copyright (c) 2022 MediaTek Inc.6// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>7 8#include <linux/regmap.h>9#include <sound/pcm_params.h>10 11#include "mt8186-afe-clk.h"12#include "mt8186-afe-common.h"13#include "mt8186-afe-gpio.h"14#include "mt8186-interconnection.h"15 16#define TDM_HD_EN_W_NAME "TDM_HD_EN"17#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"18#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"19 20struct mtk_afe_tdm_priv {21	unsigned int id;22	unsigned int rate; /* for determine which apll to use */23	unsigned int bck_invert;24	unsigned int lck_invert;25	unsigned int lrck_width;26	unsigned int mclk_id;27	unsigned int mclk_multiple; /* according to sample rate */28	unsigned int mclk_rate;29	unsigned int mclk_apll;30	unsigned int tdm_mode;31	unsigned int data_mode;32	unsigned int slave_mode;33	unsigned int low_jitter_en;34};35 36enum {37	TDM_IN_I2S = 0,38	TDM_IN_LJ = 1,39	TDM_IN_RJ = 2,40	TDM_IN_DSP_A = 4,41	TDM_IN_DSP_B = 5,42};43 44enum {45	TDM_DATA_ONE_PIN = 0,46	TDM_DATA_MULTI_PIN,47};48 49enum {50	TDM_BCK_NON_INV = 0,51	TDM_BCK_INV = 1,52};53 54enum {55	TDM_LCK_NON_INV = 0,56	TDM_LCK_INV = 1,57};58 59static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,60				       unsigned int mode)61{62	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)63		return 0;64 65	return snd_pcm_format_physical_width(format) - 1;66}67 68static unsigned int get_tdm_ch_fixup(unsigned int channels)69{70	if (channels > 4)71		return 8;72	else if (channels > 2)73		return 4;74 75	return 2;76}77 78static unsigned int get_tdm_ch_per_sdata(unsigned int mode,79					 unsigned int channels)80{81	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)82		return get_tdm_ch_fixup(channels);83 84	return 2;85}86 87enum {88	SUPPLY_SEQ_APLL,89	SUPPLY_SEQ_TDM_MCK_EN,90	SUPPLY_SEQ_TDM_HD_EN,91	SUPPLY_SEQ_TDM_EN,92};93 94static int get_tdm_id_by_name(const char *name)95{96	return MT8186_DAI_TDM_IN;97}98 99static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,100			    struct snd_kcontrol *kcontrol,101			    int event)102{103	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);104	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);105	struct mt8186_afe_private *afe_priv = afe->platform_priv;106	int dai_id = get_tdm_id_by_name(w->name);107	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];108 109	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",110		__func__, w->name, event);111 112	switch (event) {113	case SND_SOC_DAPM_PRE_PMU:114		mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);115		break;116	case SND_SOC_DAPM_POST_PMD:117		mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);118		break;119	default:120		break;121	}122 123	return 0;124}125 126static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,127				struct snd_kcontrol *kcontrol,128				int event)129{130	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);131	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);132	struct mt8186_afe_private *afe_priv = afe->platform_priv;133	int dai_id = get_tdm_id_by_name(w->name);134	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];135 136	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",137		__func__, w->name, event, dai_id);138 139	switch (event) {140	case SND_SOC_DAPM_PRE_PMU:141		mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);142		break;143	case SND_SOC_DAPM_POST_PMD:144		tdm_priv->mclk_rate = 0;145		mt8186_mck_disable(afe, tdm_priv->mclk_id);146		break;147	default:148		break;149	}150 151	return 0;152}153 154/* dai component */155/* tdm virtual mux to output widget */156static const char * const tdm_mux_map[] = {157	"Normal", "Dummy_Widget",158};159 160static int tdm_mux_map_value[] = {161	0, 1,162};163 164static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum,165					      SND_SOC_NOPM,166					      0,167					      1,168					      tdm_mux_map,169					      tdm_mux_map_value);170 171static const struct snd_kcontrol_new tdm_in_mux_control =172	SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum);173 174static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {175	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),176 177	SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,178			      ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT,179			      0, mtk_tdm_en_event,180			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),181	/* tdm hd en */182	SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN,183			      ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT,184			      0, NULL,185			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),186 187	SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN,188			      SND_SOC_NOPM, 0, 0,189			      mtk_tdm_mck_en_event,190			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),191 192	SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"),193 194	SND_SOC_DAPM_MUX("TDM_In_Mux",195			 SND_SOC_NOPM, 0, 0, &tdm_in_mux_control),196};197 198static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,199				    struct snd_soc_dapm_widget *sink)200{201	struct snd_soc_dapm_widget *w = sink;202	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);203	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);204	struct mt8186_afe_private *afe_priv = afe->platform_priv;205	int dai_id = get_tdm_id_by_name(w->name);206	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];207 208	return (tdm_priv->mclk_rate > 0) ? 1 : 0;209}210 211static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source,212					 struct snd_soc_dapm_widget *sink)213{214	struct snd_soc_dapm_widget *w = sink;215	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);216	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);217	struct mt8186_afe_private *afe_priv = afe->platform_priv;218	int dai_id = get_tdm_id_by_name(w->name);219	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];220	int cur_apll;221 222	/* which apll */223	cur_apll = mt8186_get_apll_by_name(afe, source->name);224 225	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;226}227 228static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,229				  struct snd_soc_dapm_widget *sink)230{231	struct snd_soc_dapm_widget *w = sink;232	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);233	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);234	struct mt8186_afe_private *afe_priv = afe->platform_priv;235	int dai_id = get_tdm_id_by_name(w->name);236	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];237 238	return tdm_priv->low_jitter_en;239}240 241static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,242				    struct snd_soc_dapm_widget *sink)243{244	struct snd_soc_dapm_widget *w = sink;245	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);246	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);247	struct mt8186_afe_private *afe_priv = afe->platform_priv;248	int dai_id = get_tdm_id_by_name(w->name);249	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];250	int cur_apll;251	int tdm_need_apll;252 253	/* which apll */254	cur_apll = mt8186_get_apll_by_name(afe, source->name);255 256	/* choose APLL from tdm rate */257	tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate);258 259	return (tdm_need_apll == cur_apll) ? 1 : 0;260}261 262/* low jitter control */263static const char * const mt8186_tdm_hd_str[] = {264	"Normal", "Low_Jitter"265};266 267static const struct soc_enum mt8186_tdm_enum[] = {268	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str),269			    mt8186_tdm_hd_str),270};271 272static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol,273			     struct snd_ctl_elem_value *ucontrol)274{275	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);276	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);277	struct mt8186_afe_private *afe_priv = afe->platform_priv;278	int dai_id = get_tdm_id_by_name(kcontrol->id.name);279	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];280 281	ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;282 283	return 0;284}285 286static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol,287			     struct snd_ctl_elem_value *ucontrol)288{289	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);290	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);291	struct mt8186_afe_private *afe_priv = afe->platform_priv;292	int dai_id = get_tdm_id_by_name(kcontrol->id.name);293	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];294	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;295	int hd_en;296 297	if (ucontrol->value.enumerated.item[0] >= e->items)298		return -EINVAL;299 300	hd_en = ucontrol->value.integer.value[0];301 302	dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",303		__func__, kcontrol->id.name, hd_en);304 305	if (tdm_priv->low_jitter_en == hd_en)306		return 0;307 308	tdm_priv->low_jitter_en = hd_en;309 310	return 1;311}312 313static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {314	SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],315		     mt8186_tdm_hd_get, mt8186_tdm_hd_set),316};317 318static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {319	{"TDM IN", NULL, "aud_tdm_clk"},320	{"TDM IN", NULL, "TDM_EN"},321	{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},322	{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},323	{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},324 325	{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},326	{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect},327	{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect},328 329	/* allow tdm on without codec on */330	{"TDM IN", NULL, "TDM_In_Mux"},331	{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},332};333 334/* dai ops */335static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,336				struct mtk_afe_tdm_priv *tdm_priv,337				int freq)338{339	int apll;340	int apll_rate;341 342	apll = mt8186_get_apll_by_rate(afe, freq);343	apll_rate = mt8186_get_apll_rate(afe, apll);344 345	if (!freq || freq > apll_rate) {346		dev_err(afe->dev,347			"%s(), freq(%d Hz) invalid\n", __func__, freq);348		return -EINVAL;349	}350 351	if (apll_rate % freq != 0) {352		dev_err(afe->dev,353			"%s(), APLL cannot generate %d Hz", __func__, freq);354		return -EINVAL;355	}356 357	tdm_priv->mclk_rate = freq;358	tdm_priv->mclk_apll = apll;359 360	return 0;361}362 363static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,364				 struct snd_pcm_hw_params *params,365				 struct snd_soc_dai *dai)366{367	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);368	struct mt8186_afe_private *afe_priv = afe->platform_priv;369	int tdm_id = dai->id;370	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];371	unsigned int tdm_mode = tdm_priv->tdm_mode;372	unsigned int data_mode = tdm_priv->data_mode;373	unsigned int rate = params_rate(params);374	unsigned int channels = params_channels(params);375	snd_pcm_format_t format = params_format(params);376	unsigned int bit_width =377		snd_pcm_format_physical_width(format);378	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?379		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;380	unsigned int lrck_width =381		get_tdm_lrck_width(format, tdm_mode);382	unsigned int tdm_con = 0;383	bool slave_mode = tdm_priv->slave_mode;384	bool lrck_inv = tdm_priv->lck_invert;385	bool bck_inv = tdm_priv->bck_invert;386	unsigned int tran_rate;387	unsigned int tran_relatch_rate;388 389	tdm_priv->rate = rate;390	tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id);391	tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate);392 393	/* calculate mclk_rate, if not set explicitly */394	if (!tdm_priv->mclk_rate) {395		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;396		mtk_dai_tdm_cal_mclk(afe, tdm_priv, tdm_priv->mclk_rate);397	}398 399	/* ETDM_IN1_CON0 */400	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;401	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;402	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;403	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;404	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;405	/* need to disable sync mode otherwise this may cause latch data error */406	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;407	/* relatch 1x en clock fix to h26m */408	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;409	regmap_update_bits(afe->regmap, ETDM_IN1_CON0, ETDM_IN_CON0_CTRL_MASK, tdm_con);410 411	/* ETDM_IN1_CON1 */412	tdm_con = 0;413	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;414	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;415	tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;416	regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con);417 418	/* ETDM_IN1_CON3 */419	tdm_con = ETDM_IN_CON3_FS(tran_rate);420	regmap_update_bits(afe->regmap, ETDM_IN1_CON3, ETDM_IN_CON3_CTRL_MASK, tdm_con);421 422	/* ETDM_IN1_CON4 */423	tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);424	if (slave_mode) {425		if (lrck_inv)426			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;427		if (bck_inv)428			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;429	} else {430		if (lrck_inv)431			tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;432		if (bck_inv)433			tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;434	}435	regmap_update_bits(afe->regmap, ETDM_IN1_CON4, ETDM_IN_CON4_CTRL_MASK, tdm_con);436 437	/* ETDM_IN1_CON2 */438	tdm_con = 0;439	if (data_mode == TDM_DATA_MULTI_PIN) {440		tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;441		tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);442	}443	regmap_update_bits(afe->regmap, ETDM_IN1_CON2, ETDM_IN_CON2_CTRL_MASK, tdm_con);444 445	/* ETDM_IN1_CON8 */446	tdm_con = 0;447	if (slave_mode) {448		tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;449		tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;450		tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);451	} else {452		tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;453	}454	regmap_update_bits(afe->regmap, ETDM_IN1_CON8, ETDM_IN_CON8_CTRL_MASK, tdm_con);455 456	return 0;457}458 459static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,460				  int clk_id, unsigned int freq, int dir)461{462	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);463	struct mt8186_afe_private *afe_priv = afe->platform_priv;464	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];465 466	if (dir != SND_SOC_CLOCK_IN) {467		dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);468		return -EINVAL;469	}470 471	dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);472 473	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);474}475 476static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)477{478	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);479	struct mt8186_afe_private *afe_priv = afe->platform_priv;480	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];481 482	/* DAI mode*/483	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {484	case SND_SOC_DAIFMT_I2S:485		tdm_priv->tdm_mode = TDM_IN_I2S;486		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;487		break;488	case SND_SOC_DAIFMT_LEFT_J:489		tdm_priv->tdm_mode = TDM_IN_LJ;490		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;491		break;492	case SND_SOC_DAIFMT_RIGHT_J:493		tdm_priv->tdm_mode = TDM_IN_RJ;494		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;495		break;496	case SND_SOC_DAIFMT_DSP_A:497		tdm_priv->tdm_mode = TDM_IN_DSP_A;498		tdm_priv->data_mode = TDM_DATA_ONE_PIN;499		break;500	case SND_SOC_DAIFMT_DSP_B:501		tdm_priv->tdm_mode = TDM_IN_DSP_B;502		tdm_priv->data_mode = TDM_DATA_ONE_PIN;503		break;504	default:505		dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__);506		return -EINVAL;507	}508 509	/* DAI clock inversion*/510	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {511	case SND_SOC_DAIFMT_NB_NF:512		tdm_priv->bck_invert = TDM_BCK_NON_INV;513		tdm_priv->lck_invert = TDM_LCK_NON_INV;514		break;515	case SND_SOC_DAIFMT_NB_IF:516		tdm_priv->bck_invert = TDM_BCK_NON_INV;517		tdm_priv->lck_invert = TDM_LCK_INV;518		break;519	case SND_SOC_DAIFMT_IB_NF:520		tdm_priv->bck_invert = TDM_BCK_INV;521		tdm_priv->lck_invert = TDM_LCK_NON_INV;522		break;523	case SND_SOC_DAIFMT_IB_IF:524		tdm_priv->bck_invert = TDM_BCK_INV;525		tdm_priv->lck_invert = TDM_LCK_INV;526		break;527	default:528		dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__);529		return -EINVAL;530	}531 532	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {533	case SND_SOC_DAIFMT_BP_FP:534		tdm_priv->slave_mode = false;535		break;536	case SND_SOC_DAIFMT_BC_FC:537		tdm_priv->slave_mode = true;538		break;539	default:540		dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK",541			__func__);542		return -EINVAL;543	}544 545	return 0;546}547 548static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai,549				    unsigned int tx_mask,550				    unsigned int rx_mask,551				    int slots,552				    int slot_width)553{554	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);555	struct mt8186_afe_private *afe_priv = afe->platform_priv;556	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];557 558	dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width);559 560	tdm_priv->lrck_width = slot_width;561 562	return 0;563}564 565static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {566	.hw_params = mtk_dai_tdm_hw_params,567	.set_sysclk = mtk_dai_tdm_set_sysclk,568	.set_fmt = mtk_dai_tdm_set_fmt,569	.set_tdm_slot = mtk_dai_tdm_set_tdm_slot,570};571 572/* dai driver */573#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\574		       SNDRV_PCM_RATE_88200 |\575		       SNDRV_PCM_RATE_96000 |\576		       SNDRV_PCM_RATE_176400 |\577		       SNDRV_PCM_RATE_192000)578 579#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\580			 SNDRV_PCM_FMTBIT_S24_LE |\581			 SNDRV_PCM_FMTBIT_S32_LE)582 583static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {584	{585		.name = "TDM IN",586		.id = MT8186_DAI_TDM_IN,587		.capture = {588			.stream_name = "TDM IN",589			.channels_min = 2,590			.channels_max = 8,591			.rates = MTK_TDM_RATES,592			.formats = MTK_TDM_FORMATS,593		},594		.ops = &mtk_dai_tdm_ops,595	},596};597 598static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)599{600	struct mtk_afe_tdm_priv *tdm_priv;601 602	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),603				GFP_KERNEL);604	if (!tdm_priv)605		return NULL;606 607	tdm_priv->mclk_multiple = 512;608	tdm_priv->mclk_id = MT8186_TDM_MCK;609	tdm_priv->id = MT8186_DAI_TDM_IN;610 611	return tdm_priv;612}613 614int mt8186_dai_tdm_register(struct mtk_base_afe *afe)615{616	struct mt8186_afe_private *afe_priv = afe->platform_priv;617	struct mtk_afe_tdm_priv *tdm_priv;618	struct mtk_base_afe_dai *dai;619 620	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);621	if (!dai)622		return -ENOMEM;623 624	list_add(&dai->list, &afe->sub_dais);625 626	dai->dai_drivers = mtk_dai_tdm_driver;627	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);628 629	dai->controls = mtk_dai_tdm_controls;630	dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);631	dai->dapm_widgets = mtk_dai_tdm_widgets;632	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);633	dai->dapm_routes = mtk_dai_tdm_routes;634	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);635 636	tdm_priv = init_tdm_priv_data(afe);637	if (!tdm_priv)638		return -ENOMEM;639 640	afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv;641 642	return 0;643}644