Path: blob/master/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c
26488 views
// SPDX-License-Identifier: GPL-2.01//2// MediaTek ALSA SoC Audio DAI TDM Control3//4// Copyright (c) 2022 MediaTek Inc.5// Author: Jiaxin Yu <[email protected]>67#include <linux/regmap.h>8#include <sound/pcm_params.h>910#include "mt8186-afe-clk.h"11#include "mt8186-afe-common.h"12#include "mt8186-afe-gpio.h"13#include "mt8186-interconnection.h"1415#define TDM_HD_EN_W_NAME "TDM_HD_EN"16#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"17#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"1819struct mtk_afe_tdm_priv {20unsigned int id;21unsigned int rate; /* for determine which apll to use */22unsigned int bck_invert;23unsigned int lck_invert;24unsigned int lrck_width;25unsigned int mclk_id;26unsigned int mclk_multiple; /* according to sample rate */27unsigned int mclk_rate;28unsigned int mclk_apll;29unsigned int tdm_mode;30unsigned int data_mode;31unsigned int slave_mode;32unsigned int low_jitter_en;33};3435enum {36TDM_IN_I2S = 0,37TDM_IN_LJ = 1,38TDM_IN_RJ = 2,39TDM_IN_DSP_A = 4,40TDM_IN_DSP_B = 5,41};4243enum {44TDM_DATA_ONE_PIN = 0,45TDM_DATA_MULTI_PIN,46};4748enum {49TDM_BCK_NON_INV = 0,50TDM_BCK_INV = 1,51};5253enum {54TDM_LCK_NON_INV = 0,55TDM_LCK_INV = 1,56};5758static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,59unsigned int mode)60{61if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)62return 0;6364return snd_pcm_format_physical_width(format) - 1;65}6667static unsigned int get_tdm_ch_fixup(unsigned int channels)68{69if (channels > 4)70return 8;71else if (channels > 2)72return 4;7374return 2;75}7677static unsigned int get_tdm_ch_per_sdata(unsigned int mode,78unsigned int channels)79{80if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)81return get_tdm_ch_fixup(channels);8283return 2;84}8586enum {87SUPPLY_SEQ_APLL,88SUPPLY_SEQ_TDM_MCK_EN,89SUPPLY_SEQ_TDM_HD_EN,90SUPPLY_SEQ_TDM_EN,91};9293static int get_tdm_id_by_name(const char *name)94{95return MT8186_DAI_TDM_IN;96}9798static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,99struct snd_kcontrol *kcontrol,100int event)101{102struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);103struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);104struct mt8186_afe_private *afe_priv = afe->platform_priv;105int dai_id = get_tdm_id_by_name(w->name);106struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];107108dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",109__func__, w->name, event);110111switch (event) {112case SND_SOC_DAPM_PRE_PMU:113mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);114break;115case SND_SOC_DAPM_POST_PMD:116mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);117break;118default:119break;120}121122return 0;123}124125static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,126struct snd_kcontrol *kcontrol,127int event)128{129struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);130struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);131struct mt8186_afe_private *afe_priv = afe->platform_priv;132int dai_id = get_tdm_id_by_name(w->name);133struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];134135dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",136__func__, w->name, event, dai_id);137138switch (event) {139case SND_SOC_DAPM_PRE_PMU:140mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);141break;142case SND_SOC_DAPM_POST_PMD:143tdm_priv->mclk_rate = 0;144mt8186_mck_disable(afe, tdm_priv->mclk_id);145break;146default:147break;148}149150return 0;151}152153/* dai component */154/* tdm virtual mux to output widget */155static const char * const tdm_mux_map[] = {156"Normal", "Dummy_Widget",157};158159static int tdm_mux_map_value[] = {1600, 1,161};162163static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum,164SND_SOC_NOPM,1650,1661,167tdm_mux_map,168tdm_mux_map_value);169170static const struct snd_kcontrol_new tdm_in_mux_control =171SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum);172173static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {174SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),175176SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,177ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT,1780, mtk_tdm_en_event,179SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),180/* tdm hd en */181SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN,182ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT,1830, NULL,184SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),185186SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN,187SND_SOC_NOPM, 0, 0,188mtk_tdm_mck_en_event,189SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),190191SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"),192193SND_SOC_DAPM_MUX("TDM_In_Mux",194SND_SOC_NOPM, 0, 0, &tdm_in_mux_control),195};196197static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,198struct snd_soc_dapm_widget *sink)199{200struct snd_soc_dapm_widget *w = sink;201struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);202struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);203struct mt8186_afe_private *afe_priv = afe->platform_priv;204int dai_id = get_tdm_id_by_name(w->name);205struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];206207return (tdm_priv->mclk_rate > 0) ? 1 : 0;208}209210static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source,211struct snd_soc_dapm_widget *sink)212{213struct snd_soc_dapm_widget *w = sink;214struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);215struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);216struct mt8186_afe_private *afe_priv = afe->platform_priv;217int dai_id = get_tdm_id_by_name(w->name);218struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];219int cur_apll;220221/* which apll */222cur_apll = mt8186_get_apll_by_name(afe, source->name);223224return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;225}226227static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,228struct snd_soc_dapm_widget *sink)229{230struct snd_soc_dapm_widget *w = sink;231struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);232struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);233struct mt8186_afe_private *afe_priv = afe->platform_priv;234int dai_id = get_tdm_id_by_name(w->name);235struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];236237return tdm_priv->low_jitter_en;238}239240static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,241struct snd_soc_dapm_widget *sink)242{243struct snd_soc_dapm_widget *w = sink;244struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);245struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);246struct mt8186_afe_private *afe_priv = afe->platform_priv;247int dai_id = get_tdm_id_by_name(w->name);248struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];249int cur_apll;250int tdm_need_apll;251252/* which apll */253cur_apll = mt8186_get_apll_by_name(afe, source->name);254255/* choose APLL from tdm rate */256tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate);257258return (tdm_need_apll == cur_apll) ? 1 : 0;259}260261/* low jitter control */262static const char * const mt8186_tdm_hd_str[] = {263"Normal", "Low_Jitter"264};265266static const struct soc_enum mt8186_tdm_enum[] = {267SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str),268mt8186_tdm_hd_str),269};270271static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol,272struct snd_ctl_elem_value *ucontrol)273{274struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);275struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);276struct mt8186_afe_private *afe_priv = afe->platform_priv;277int dai_id = get_tdm_id_by_name(kcontrol->id.name);278struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];279280ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;281282return 0;283}284285static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol,286struct snd_ctl_elem_value *ucontrol)287{288struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);289struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);290struct mt8186_afe_private *afe_priv = afe->platform_priv;291int dai_id = get_tdm_id_by_name(kcontrol->id.name);292struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];293struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;294int hd_en;295296if (ucontrol->value.enumerated.item[0] >= e->items)297return -EINVAL;298299hd_en = ucontrol->value.integer.value[0];300301dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",302__func__, kcontrol->id.name, hd_en);303304if (tdm_priv->low_jitter_en == hd_en)305return 0;306307tdm_priv->low_jitter_en = hd_en;308309return 1;310}311312static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {313SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],314mt8186_tdm_hd_get, mt8186_tdm_hd_set),315};316317static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {318{"TDM IN", NULL, "aud_tdm_clk"},319{"TDM IN", NULL, "TDM_EN"},320{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},321{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},322{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},323324{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},325{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect},326{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect},327328/* allow tdm on without codec on */329{"TDM IN", NULL, "TDM_In_Mux"},330{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},331};332333/* dai ops */334static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,335struct mtk_afe_tdm_priv *tdm_priv,336int freq)337{338int apll;339int apll_rate;340341apll = mt8186_get_apll_by_rate(afe, freq);342apll_rate = mt8186_get_apll_rate(afe, apll);343344if (!freq || freq > apll_rate) {345dev_err(afe->dev,346"%s(), freq(%d Hz) invalid\n", __func__, freq);347return -EINVAL;348}349350if (apll_rate % freq != 0) {351dev_err(afe->dev,352"%s(), APLL cannot generate %d Hz", __func__, freq);353return -EINVAL;354}355356tdm_priv->mclk_rate = freq;357tdm_priv->mclk_apll = apll;358359return 0;360}361362static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,363struct snd_pcm_hw_params *params,364struct snd_soc_dai *dai)365{366struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);367struct mt8186_afe_private *afe_priv = afe->platform_priv;368int tdm_id = dai->id;369struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];370unsigned int tdm_mode = tdm_priv->tdm_mode;371unsigned int data_mode = tdm_priv->data_mode;372unsigned int rate = params_rate(params);373unsigned int channels = params_channels(params);374snd_pcm_format_t format = params_format(params);375unsigned int bit_width =376snd_pcm_format_physical_width(format);377unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?378get_tdm_ch_per_sdata(tdm_mode, channels) : 2;379unsigned int lrck_width =380get_tdm_lrck_width(format, tdm_mode);381unsigned int tdm_con = 0;382bool slave_mode = tdm_priv->slave_mode;383bool lrck_inv = tdm_priv->lck_invert;384bool bck_inv = tdm_priv->bck_invert;385unsigned int tran_rate;386unsigned int tran_relatch_rate;387388tdm_priv->rate = rate;389tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id);390tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate);391392/* calculate mclk_rate, if not set explicitly */393if (!tdm_priv->mclk_rate) {394tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;395mtk_dai_tdm_cal_mclk(afe, tdm_priv, tdm_priv->mclk_rate);396}397398/* ETDM_IN1_CON0 */399tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;400tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;401tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;402tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;403tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;404/* need to disable sync mode otherwise this may cause latch data error */405tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;406/* relatch 1x en clock fix to h26m */407tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;408regmap_update_bits(afe->regmap, ETDM_IN1_CON0, ETDM_IN_CON0_CTRL_MASK, tdm_con);409410/* ETDM_IN1_CON1 */411tdm_con = 0;412tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;413tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;414tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;415regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con);416417/* ETDM_IN1_CON3 */418tdm_con = ETDM_IN_CON3_FS(tran_rate);419regmap_update_bits(afe->regmap, ETDM_IN1_CON3, ETDM_IN_CON3_CTRL_MASK, tdm_con);420421/* ETDM_IN1_CON4 */422tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);423if (slave_mode) {424if (lrck_inv)425tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;426if (bck_inv)427tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;428} else {429if (lrck_inv)430tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;431if (bck_inv)432tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;433}434regmap_update_bits(afe->regmap, ETDM_IN1_CON4, ETDM_IN_CON4_CTRL_MASK, tdm_con);435436/* ETDM_IN1_CON2 */437tdm_con = 0;438if (data_mode == TDM_DATA_MULTI_PIN) {439tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;440tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);441}442regmap_update_bits(afe->regmap, ETDM_IN1_CON2, ETDM_IN_CON2_CTRL_MASK, tdm_con);443444/* ETDM_IN1_CON8 */445tdm_con = 0;446if (slave_mode) {447tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;448tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;449tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);450} else {451tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;452}453regmap_update_bits(afe->regmap, ETDM_IN1_CON8, ETDM_IN_CON8_CTRL_MASK, tdm_con);454455return 0;456}457458static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,459int clk_id, unsigned int freq, int dir)460{461struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);462struct mt8186_afe_private *afe_priv = afe->platform_priv;463struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];464465if (dir != SND_SOC_CLOCK_IN) {466dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);467return -EINVAL;468}469470dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);471472return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);473}474475static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)476{477struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);478struct mt8186_afe_private *afe_priv = afe->platform_priv;479struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];480481/* DAI mode*/482switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {483case SND_SOC_DAIFMT_I2S:484tdm_priv->tdm_mode = TDM_IN_I2S;485tdm_priv->data_mode = TDM_DATA_MULTI_PIN;486break;487case SND_SOC_DAIFMT_LEFT_J:488tdm_priv->tdm_mode = TDM_IN_LJ;489tdm_priv->data_mode = TDM_DATA_MULTI_PIN;490break;491case SND_SOC_DAIFMT_RIGHT_J:492tdm_priv->tdm_mode = TDM_IN_RJ;493tdm_priv->data_mode = TDM_DATA_MULTI_PIN;494break;495case SND_SOC_DAIFMT_DSP_A:496tdm_priv->tdm_mode = TDM_IN_DSP_A;497tdm_priv->data_mode = TDM_DATA_ONE_PIN;498break;499case SND_SOC_DAIFMT_DSP_B:500tdm_priv->tdm_mode = TDM_IN_DSP_B;501tdm_priv->data_mode = TDM_DATA_ONE_PIN;502break;503default:504dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__);505return -EINVAL;506}507508/* DAI clock inversion*/509switch (fmt & SND_SOC_DAIFMT_INV_MASK) {510case SND_SOC_DAIFMT_NB_NF:511tdm_priv->bck_invert = TDM_BCK_NON_INV;512tdm_priv->lck_invert = TDM_LCK_NON_INV;513break;514case SND_SOC_DAIFMT_NB_IF:515tdm_priv->bck_invert = TDM_BCK_NON_INV;516tdm_priv->lck_invert = TDM_LCK_INV;517break;518case SND_SOC_DAIFMT_IB_NF:519tdm_priv->bck_invert = TDM_BCK_INV;520tdm_priv->lck_invert = TDM_LCK_NON_INV;521break;522case SND_SOC_DAIFMT_IB_IF:523tdm_priv->bck_invert = TDM_BCK_INV;524tdm_priv->lck_invert = TDM_LCK_INV;525break;526default:527dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__);528return -EINVAL;529}530531switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {532case SND_SOC_DAIFMT_BP_FP:533tdm_priv->slave_mode = false;534break;535case SND_SOC_DAIFMT_BC_FC:536tdm_priv->slave_mode = true;537break;538default:539dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK",540__func__);541return -EINVAL;542}543544return 0;545}546547static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai,548unsigned int tx_mask,549unsigned int rx_mask,550int slots,551int slot_width)552{553struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);554struct mt8186_afe_private *afe_priv = afe->platform_priv;555struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];556557dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width);558559tdm_priv->lrck_width = slot_width;560561return 0;562}563564static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {565.hw_params = mtk_dai_tdm_hw_params,566.set_sysclk = mtk_dai_tdm_set_sysclk,567.set_fmt = mtk_dai_tdm_set_fmt,568.set_tdm_slot = mtk_dai_tdm_set_tdm_slot,569};570571/* dai driver */572#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\573SNDRV_PCM_RATE_88200 |\574SNDRV_PCM_RATE_96000 |\575SNDRV_PCM_RATE_176400 |\576SNDRV_PCM_RATE_192000)577578#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\579SNDRV_PCM_FMTBIT_S24_LE |\580SNDRV_PCM_FMTBIT_S32_LE)581582static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {583{584.name = "TDM IN",585.id = MT8186_DAI_TDM_IN,586.capture = {587.stream_name = "TDM IN",588.channels_min = 2,589.channels_max = 8,590.rates = MTK_TDM_RATES,591.formats = MTK_TDM_FORMATS,592},593.ops = &mtk_dai_tdm_ops,594},595};596597static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)598{599struct mtk_afe_tdm_priv *tdm_priv;600601tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),602GFP_KERNEL);603if (!tdm_priv)604return NULL;605606tdm_priv->mclk_multiple = 512;607tdm_priv->mclk_id = MT8186_TDM_MCK;608tdm_priv->id = MT8186_DAI_TDM_IN;609610return tdm_priv;611}612613int mt8186_dai_tdm_register(struct mtk_base_afe *afe)614{615struct mt8186_afe_private *afe_priv = afe->platform_priv;616struct mtk_afe_tdm_priv *tdm_priv;617struct mtk_base_afe_dai *dai;618619dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);620if (!dai)621return -ENOMEM;622623list_add(&dai->list, &afe->sub_dais);624625dai->dai_drivers = mtk_dai_tdm_driver;626dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);627628dai->controls = mtk_dai_tdm_controls;629dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);630dai->dapm_widgets = mtk_dai_tdm_widgets;631dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);632dai->dapm_routes = mtk_dai_tdm_routes;633dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);634635tdm_priv = init_tdm_priv_data(afe);636if (!tdm_priv)637return -ENOMEM;638639afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv;640641return 0;642}643644645