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