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