1232 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// MediaTek ALSA SoC Audio DAI I2S Control4//5// Copyright (c) 2022 MediaTek Inc.6// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>7 8#include <linux/bitops.h>9#include <linux/regmap.h>10#include <sound/pcm_params.h>11#include "mt8186-afe-clk.h"12#include "mt8186-afe-common.h"13#include "mt8186-afe-gpio.h"14#include "mt8186-interconnection.h"15 16enum {17 I2S_FMT_EIAJ = 0,18 I2S_FMT_I2S = 1,19};20 21enum {22 I2S_WLEN_16_BIT = 0,23 I2S_WLEN_32_BIT = 1,24};25 26enum {27 I2S_HD_NORMAL = 0,28 I2S_HD_LOW_JITTER = 1,29};30 31enum {32 I2S1_SEL_O28_O29 = 0,33 I2S1_SEL_O03_O04 = 1,34};35 36enum {37 I2S_IN_PAD_CONNSYS = 0,38 I2S_IN_PAD_IO_MUX = 1,39};40 41struct mtk_afe_i2s_priv {42 int id;43 int rate; /* for determine which apll to use */44 int low_jitter_en;45 int master; /* only i2s0 has slave mode*/46 47 int share_i2s_id;48 49 int mclk_id;50 int mclk_rate;51 int mclk_apll;52};53 54static unsigned int get_i2s_wlen(snd_pcm_format_t format)55{56 return snd_pcm_format_physical_width(format) <= 16 ?57 I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;58}59 60#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"61#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"62#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"63#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"64#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux"65 66#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"67#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"68#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"69#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"70 71#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"72#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"73#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"74#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"75 76static int get_i2s_id_by_name(struct mtk_base_afe *afe,77 const char *name)78{79 if (strncmp(name, "I2S0", 4) == 0)80 return MT8186_DAI_I2S_0;81 else if (strncmp(name, "I2S1", 4) == 0)82 return MT8186_DAI_I2S_1;83 else if (strncmp(name, "I2S2", 4) == 0)84 return MT8186_DAI_I2S_2;85 else if (strncmp(name, "I2S3", 4) == 0)86 return MT8186_DAI_I2S_3;87 88 return -EINVAL;89}90 91static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,92 const char *name)93{94 struct mt8186_afe_private *afe_priv = afe->platform_priv;95 int dai_id = get_i2s_id_by_name(afe, name);96 97 if (dai_id < 0)98 return NULL;99 100 return afe_priv->dai_priv[dai_id];101}102 103/* low jitter control */104static const char * const mt8186_i2s_hd_str[] = {105 "Normal", "Low_Jitter"106};107 108static const struct soc_enum mt8186_i2s_enum[] = {109 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str),110 mt8186_i2s_hd_str),111};112 113static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol,114 struct snd_ctl_elem_value *ucontrol)115{116 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);117 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);118 struct mtk_afe_i2s_priv *i2s_priv;119 120 i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);121 ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;122 123 return 0;124}125 126static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol,127 struct snd_ctl_elem_value *ucontrol)128{129 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);130 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);131 struct mtk_afe_i2s_priv *i2s_priv;132 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;133 int hd_en;134 135 if (ucontrol->value.enumerated.item[0] >= e->items)136 return -EINVAL;137 138 hd_en = ucontrol->value.integer.value[0];139 140 dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",141 __func__, kcontrol->id.name, hd_en);142 143 i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);144 if (i2s_priv->low_jitter_en == hd_en)145 return 0;146 147 i2s_priv->low_jitter_en = hd_en;148 149 return 1;150}151 152static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {153 SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8186_i2s_enum[0],154 mt8186_i2s_hd_get, mt8186_i2s_hd_set),155 SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8186_i2s_enum[0],156 mt8186_i2s_hd_get, mt8186_i2s_hd_set),157 SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8186_i2s_enum[0],158 mt8186_i2s_hd_get, mt8186_i2s_hd_set),159 SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8186_i2s_enum[0],160 mt8186_i2s_hd_get, mt8186_i2s_hd_set),161};162 163/* dai component */164/* i2s virtual mux to output widget */165static const char * const i2s_mux_map[] = {166 "Normal", "Dummy_Widget",167};168 169static int i2s_mux_map_value[] = {170 0, 1,171};172 173static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum,174 SND_SOC_NOPM,175 0,176 1,177 i2s_mux_map,178 i2s_mux_map_value);179 180static const struct snd_kcontrol_new i2s0_in_mux_control =181 SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum);182 183static const struct snd_kcontrol_new i2s1_out_mux_control =184 SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum);185 186static const struct snd_kcontrol_new i2s2_in_mux_control =187 SOC_DAPM_ENUM("I2S2 In Select", i2s_mux_map_enum);188 189static const struct snd_kcontrol_new i2s3_out_mux_control =190 SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum);191 192/* i2s in lpbk */193static const char * const i2s_lpbk_mux_map[] = {194 "Normal", "Lpbk",195};196 197static int i2s_lpbk_mux_map_value[] = {198 0, 1,199};200 201static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum,202 AFE_I2S_CON,203 I2S_LOOPBACK_SFT,204 1,205 i2s_lpbk_mux_map,206 i2s_lpbk_mux_map_value);207 208static const struct snd_kcontrol_new i2s0_lpbk_mux_control =209 SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum);210 211static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum,212 AFE_I2S_CON2,213 I2S3_LOOPBACK_SFT,214 1,215 i2s_lpbk_mux_map,216 i2s_lpbk_mux_map_value);217 218static const struct snd_kcontrol_new i2s2_lpbk_mux_control =219 SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum);220 221/* interconnection */222static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = {223 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN0,224 I_DL1_CH1, 1, 0),225 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN0,226 I_DL2_CH1, 1, 0),227 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN0,228 I_DL3_CH1, 1, 0),229 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN0,230 I_DL12_CH1, 1, 0),231 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN0,232 I_DL12_CH3, 1, 0),233 SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN0_1,234 I_DL6_CH1, 1, 0),235 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN0_1,236 I_DL4_CH1, 1, 0),237 SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN0_1,238 I_DL5_CH1, 1, 0),239 SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN0_1,240 I_DL8_CH1, 1, 0),241 SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN0,242 I_GAIN1_OUT_CH1, 1, 0),243 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN0,244 I_ADDA_UL_CH1, 1, 0),245 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN0,246 I_ADDA_UL_CH2, 1, 0),247 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN0,248 I_ADDA_UL_CH3, 1, 0),249 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN0,250 I_PCM_1_CAP_CH1, 1, 0),251 SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN0_1,252 I_SRC_1_OUT_CH1, 1, 0),253};254 255static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = {256 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN1,257 I_DL1_CH2, 1, 0),258 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN1,259 I_DL2_CH2, 1, 0),260 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN1,261 I_DL3_CH2, 1, 0),262 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN1,263 I_DL12_CH2, 1, 0),264 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN1,265 I_DL12_CH4, 1, 0),266 SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN1_1,267 I_DL6_CH2, 1, 0),268 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN1_1,269 I_DL4_CH2, 1, 0),270 SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN1_1,271 I_DL5_CH2, 1, 0),272 SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN1_1,273 I_DL8_CH2, 1, 0),274 SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN1,275 I_GAIN1_OUT_CH2, 1, 0),276 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN1,277 I_ADDA_UL_CH1, 1, 0),278 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN1,279 I_ADDA_UL_CH2, 1, 0),280 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN1,281 I_ADDA_UL_CH3, 1, 0),282 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN1,283 I_PCM_1_CAP_CH2, 1, 0),284 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN1,285 I_PCM_2_CAP_CH2, 1, 0),286 SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN1_1,287 I_SRC_1_OUT_CH2, 1, 0),288};289 290static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = {291 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN28,292 I_DL1_CH1, 1, 0),293 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN28,294 I_DL2_CH1, 1, 0),295 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN28,296 I_DL3_CH1, 1, 0),297 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN28,298 I_DL12_CH1, 1, 0),299 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN28,300 I_DL12_CH3, 1, 0),301 SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN28_1,302 I_DL6_CH1, 1, 0),303 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN28_1,304 I_DL4_CH1, 1, 0),305 SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN28_1,306 I_DL5_CH1, 1, 0),307 SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN28_1,308 I_DL8_CH1, 1, 0),309 SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN28,310 I_GAIN1_OUT_CH1, 1, 0),311 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN28,312 I_ADDA_UL_CH1, 1, 0),313 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN28,314 I_PCM_1_CAP_CH1, 1, 0),315 SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN28_1,316 I_SRC_1_OUT_CH1, 1, 0),317};318 319static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = {320 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN29,321 I_DL1_CH2, 1, 0),322 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN29,323 I_DL2_CH2, 1, 0),324 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN29,325 I_DL3_CH2, 1, 0),326 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN29,327 I_DL12_CH2, 1, 0),328 SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN29,329 I_DL12_CH4, 1, 0),330 SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN29_1,331 I_DL6_CH2, 1, 0),332 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN29_1,333 I_DL4_CH2, 1, 0),334 SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN29_1,335 I_DL5_CH2, 1, 0),336 SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN29_1,337 I_DL8_CH2, 1, 0),338 SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN29,339 I_GAIN1_OUT_CH2, 1, 0),340 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN29,341 I_ADDA_UL_CH2, 1, 0),342 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN29,343 I_PCM_1_CAP_CH2, 1, 0),344 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN29,345 I_PCM_2_CAP_CH2, 1, 0),346 SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN29_1,347 I_SRC_1_OUT_CH2, 1, 0),348};349 350enum {351 SUPPLY_SEQ_APLL,352 SUPPLY_SEQ_I2S_MCLK_EN,353 SUPPLY_SEQ_I2S_HD_EN,354 SUPPLY_SEQ_I2S_EN,355};356 357static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,358 struct snd_kcontrol *kcontrol,359 int event)360{361 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);362 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);363 struct mtk_afe_i2s_priv *i2s_priv;364 365 i2s_priv = get_i2s_priv_by_name(afe, w->name);366 367 dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",368 __func__, w->name, event);369 370 switch (event) {371 case SND_SOC_DAPM_PRE_PMU:372 mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0);373 break;374 case SND_SOC_DAPM_POST_PMD:375 mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0);376 break;377 default:378 break;379 }380 381 return 0;382}383 384static int mtk_apll_event(struct snd_soc_dapm_widget *w,385 struct snd_kcontrol *kcontrol,386 int event)387{388 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);389 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);390 391 dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",392 __func__, w->name, event);393 394 switch (event) {395 case SND_SOC_DAPM_PRE_PMU:396 if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)397 mt8186_apll1_enable(afe);398 else399 mt8186_apll2_enable(afe);400 break;401 case SND_SOC_DAPM_POST_PMD:402 if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)403 mt8186_apll1_disable(afe);404 else405 mt8186_apll2_disable(afe);406 break;407 default:408 break;409 }410 411 return 0;412}413 414static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,415 struct snd_kcontrol *kcontrol,416 int event)417{418 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);419 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);420 struct mtk_afe_i2s_priv *i2s_priv;421 422 dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",423 __func__, w->name, event);424 425 i2s_priv = get_i2s_priv_by_name(afe, w->name);426 427 switch (event) {428 case SND_SOC_DAPM_PRE_PMU:429 mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);430 break;431 case SND_SOC_DAPM_POST_PMD:432 i2s_priv->mclk_rate = 0;433 mt8186_mck_disable(afe, i2s_priv->mclk_id);434 break;435 default:436 break;437 }438 439 return 0;440}441 442static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {443 SND_SOC_DAPM_INPUT("CONNSYS"),444 445 SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0,446 mtk_i2s1_ch1_mix,447 ARRAY_SIZE(mtk_i2s1_ch1_mix)),448 SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0,449 mtk_i2s1_ch2_mix,450 ARRAY_SIZE(mtk_i2s1_ch2_mix)),451 452 SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0,453 mtk_i2s3_ch1_mix,454 ARRAY_SIZE(mtk_i2s3_ch1_mix)),455 SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0,456 mtk_i2s3_ch2_mix,457 ARRAY_SIZE(mtk_i2s3_ch2_mix)),458 459 /* i2s en*/460 SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN,461 AFE_I2S_CON, I2S_EN_SFT, 0,462 mtk_i2s_en_event,463 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),464 SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN,465 AFE_I2S_CON1, I2S_EN_SFT, 0,466 mtk_i2s_en_event,467 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),468 SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN,469 AFE_I2S_CON2, I2S_EN_SFT, 0,470 mtk_i2s_en_event,471 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),472 SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN,473 AFE_I2S_CON3, I2S_EN_SFT, 0,474 mtk_i2s_en_event,475 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),476 /* i2s hd en */477 SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,478 AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL,479 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),480 SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,481 AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL,482 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),483 SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,484 AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL,485 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),486 SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,487 AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL,488 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),489 490 /* i2s mclk en */491 SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,492 SND_SOC_NOPM, 0, 0,493 mtk_mclk_en_event,494 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),495 SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,496 SND_SOC_NOPM, 0, 0,497 mtk_mclk_en_event,498 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),499 SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,500 SND_SOC_NOPM, 0, 0,501 mtk_mclk_en_event,502 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),503 SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,504 SND_SOC_NOPM, 0, 0,505 mtk_mclk_en_event,506 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),507 508 /* apll */509 SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,510 SND_SOC_NOPM, 0, 0,511 mtk_apll_event,512 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),513 SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,514 SND_SOC_NOPM, 0, 0,515 mtk_apll_event,516 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),517 518 /* allow i2s on without codec on */519 SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"),520 SND_SOC_DAPM_MUX("I2S1_Out_Mux",521 SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control),522 SND_SOC_DAPM_MUX("I2S3_Out_Mux",523 SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control),524 SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"),525 SND_SOC_DAPM_MUX("I2S0_In_Mux",526 SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control),527 SND_SOC_DAPM_MUX("I2S2_In_Mux",528 SND_SOC_NOPM, 0, 0, &i2s2_in_mux_control),529 530 /* i2s in lpbk */531 SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux",532 SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control),533 SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux",534 SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control),535};536 537static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,538 struct snd_soc_dapm_widget *sink)539{540 struct snd_soc_dapm_widget *w = sink;541 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);542 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);543 struct mtk_afe_i2s_priv *i2s_priv;544 545 i2s_priv = get_i2s_priv_by_name(afe, sink->name);546 if (i2s_priv->share_i2s_id < 0)547 return 0;548 549 return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);550}551 552static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,553 struct snd_soc_dapm_widget *sink)554{555 struct snd_soc_dapm_widget *w = sink;556 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);557 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);558 struct mtk_afe_i2s_priv *i2s_priv;559 560 i2s_priv = get_i2s_priv_by_name(afe, sink->name);561 if (get_i2s_id_by_name(afe, sink->name) ==562 get_i2s_id_by_name(afe, source->name))563 return i2s_priv->low_jitter_en;564 565 /* check if share i2s need hd en */566 if (i2s_priv->share_i2s_id < 0)567 return 0;568 569 if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))570 return i2s_priv->low_jitter_en;571 572 return 0;573}574 575static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,576 struct snd_soc_dapm_widget *sink)577{578 struct snd_soc_dapm_widget *w = sink;579 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);580 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);581 struct mtk_afe_i2s_priv *i2s_priv;582 int cur_apll;583 int i2s_need_apll;584 585 i2s_priv = get_i2s_priv_by_name(afe, w->name);586 /* which apll */587 cur_apll = mt8186_get_apll_by_name(afe, source->name);588 /* choose APLL from i2s rate */589 i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate);590 591 return (i2s_need_apll == cur_apll) ? 1 : 0;592}593 594static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,595 struct snd_soc_dapm_widget *sink)596{597 struct snd_soc_dapm_widget *w = sink;598 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);599 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);600 struct mtk_afe_i2s_priv *i2s_priv;601 602 i2s_priv = get_i2s_priv_by_name(afe, sink->name);603 if (get_i2s_id_by_name(afe, sink->name) ==604 get_i2s_id_by_name(afe, source->name))605 return (i2s_priv->mclk_rate > 0) ? 1 : 0;606 607 /* check if share i2s need mclk */608 if (i2s_priv->share_i2s_id < 0)609 return 0;610 611 if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))612 return (i2s_priv->mclk_rate > 0) ? 1 : 0;613 614 return 0;615}616 617static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,618 struct snd_soc_dapm_widget *sink)619{620 struct snd_soc_dapm_widget *w = sink;621 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);622 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);623 struct mtk_afe_i2s_priv *i2s_priv;624 int cur_apll;625 626 i2s_priv = get_i2s_priv_by_name(afe, w->name);627 /* which apll */628 cur_apll = mt8186_get_apll_by_name(afe, source->name);629 630 return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0;631}632 633static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {634 {"Connsys I2S", NULL, "CONNSYS"},635 636 /* i2s0 */637 {"I2S0", NULL, "I2S0_EN"},638 {"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},639 {"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},640 {"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},641 642 {"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},643 {"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},644 {"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},645 {"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},646 {I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},647 {I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},648 649 {"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},650 {"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},651 {"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},652 {"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},653 {I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},654 {I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},655 656 /* i2s1 */657 {"I2S1_CH1", "DL1_CH1 Switch", "DL1"},658 {"I2S1_CH2", "DL1_CH2 Switch", "DL1"},659 660 {"I2S1_CH1", "DL1_CH1 Switch", "DSP_DL1_VIRT"},661 {"I2S1_CH2", "DL1_CH2 Switch", "DSP_DL1_VIRT"},662 663 {"I2S1_CH1", "DL2_CH1 Switch", "DL2"},664 {"I2S1_CH2", "DL2_CH2 Switch", "DL2"},665 666 {"I2S1_CH1", "DL2_CH1 Switch", "DSP_DL2_VIRT"},667 {"I2S1_CH2", "DL2_CH2 Switch", "DSP_DL2_VIRT"},668 669 {"I2S1_CH1", "DL3_CH1 Switch", "DL3"},670 {"I2S1_CH2", "DL3_CH2 Switch", "DL3"},671 672 {"I2S1_CH1", "DL12_CH1 Switch", "DL12"},673 {"I2S1_CH2", "DL12_CH2 Switch", "DL12"},674 675 {"I2S1_CH1", "DL12_CH3 Switch", "DL12"},676 {"I2S1_CH2", "DL12_CH4 Switch", "DL12"},677 678 {"I2S1_CH1", "DL6_CH1 Switch", "DL6"},679 {"I2S1_CH2", "DL6_CH2 Switch", "DL6"},680 681 {"I2S1_CH1", "DL4_CH1 Switch", "DL4"},682 {"I2S1_CH2", "DL4_CH2 Switch", "DL4"},683 684 {"I2S1_CH1", "DL5_CH1 Switch", "DL5"},685 {"I2S1_CH2", "DL5_CH2 Switch", "DL5"},686 687 {"I2S1_CH1", "DL8_CH1 Switch", "DL8"},688 {"I2S1_CH2", "DL8_CH2 Switch", "DL8"},689 690 {"I2S1", NULL, "I2S1_CH1"},691 {"I2S1", NULL, "I2S1_CH2"},692 693 {"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},694 {"I2S1", NULL, "I2S1_EN"},695 {"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},696 {"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},697 698 {"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},699 {"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},700 {"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},701 {"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},702 {I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},703 {I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},704 705 {"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},706 {"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},707 {"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},708 {"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},709 {I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},710 {I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},711 712 /* i2s2 */713 {"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},714 {"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},715 {"I2S2", NULL, "I2S2_EN"},716 {"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},717 718 {"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},719 {"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},720 {"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},721 {"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},722 {I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},723 {I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},724 725 {"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},726 {"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},727 {"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},728 {"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},729 {I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},730 {I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},731 732 /* i2s3 */733 {"I2S3_CH1", "DL1_CH1 Switch", "DL1"},734 {"I2S3_CH2", "DL1_CH2 Switch", "DL1"},735 736 {"I2S3_CH1", "DL1_CH1 Switch", "DSP_DL1_VIRT"},737 {"I2S3_CH2", "DL1_CH2 Switch", "DSP_DL1_VIRT"},738 739 {"I2S3_CH1", "DL2_CH1 Switch", "DL2"},740 {"I2S3_CH2", "DL2_CH2 Switch", "DL2"},741 742 {"I2S3_CH1", "DL2_CH1 Switch", "DSP_DL2_VIRT"},743 {"I2S3_CH2", "DL2_CH2 Switch", "DSP_DL2_VIRT"},744 745 {"I2S3_CH1", "DL3_CH1 Switch", "DL3"},746 {"I2S3_CH2", "DL3_CH2 Switch", "DL3"},747 748 {"I2S3_CH1", "DL12_CH1 Switch", "DL12"},749 {"I2S3_CH2", "DL12_CH2 Switch", "DL12"},750 751 {"I2S3_CH1", "DL12_CH3 Switch", "DL12"},752 {"I2S3_CH2", "DL12_CH4 Switch", "DL12"},753 754 {"I2S3_CH1", "DL6_CH1 Switch", "DL6"},755 {"I2S3_CH2", "DL6_CH2 Switch", "DL6"},756 757 {"I2S3_CH1", "DL4_CH1 Switch", "DL4"},758 {"I2S3_CH2", "DL4_CH2 Switch", "DL4"},759 760 {"I2S3_CH1", "DL5_CH1 Switch", "DL5"},761 {"I2S3_CH2", "DL5_CH2 Switch", "DL5"},762 763 {"I2S3_CH1", "DL8_CH1 Switch", "DL8"},764 {"I2S3_CH2", "DL8_CH2 Switch", "DL8"},765 766 {"I2S3", NULL, "I2S3_CH1"},767 {"I2S3", NULL, "I2S3_CH2"},768 769 {"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},770 {"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},771 {"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},772 {"I2S3", NULL, "I2S3_EN"},773 774 {"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},775 {"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},776 {"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},777 {"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},778 {I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},779 {I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},780 781 {"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},782 {"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},783 {"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},784 {"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},785 {I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},786 {I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},787 788 /* allow i2s on without codec on */789 {"I2S0", NULL, "I2S0_In_Mux"},790 {"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},791 792 {"I2S1_Out_Mux", "Dummy_Widget", "I2S1"},793 {"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"},794 795 {"I2S2", NULL, "I2S2_In_Mux"},796 {"I2S2_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},797 798 {"I2S3_Out_Mux", "Dummy_Widget", "I2S3"},799 {"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"},800 801 /* i2s in lpbk */802 {"I2S0_Lpbk_Mux", "Lpbk", "I2S3"},803 {"I2S2_Lpbk_Mux", "Lpbk", "I2S1"},804 {"I2S0", NULL, "I2S0_Lpbk_Mux"},805 {"I2S2", NULL, "I2S2_Lpbk_Mux"},806};807 808/* dai ops */809static int mtk_dai_connsys_i2s_hw_params(struct snd_pcm_substream *substream,810 struct snd_pcm_hw_params *params,811 struct snd_soc_dai *dai)812{813 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);814 unsigned int rate = params_rate(params);815 unsigned int rate_reg = mt8186_rate_transform(afe->dev,816 rate, dai->id);817 unsigned int i2s_con = 0;818 819 dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",820 __func__, dai->id, substream->stream, rate);821 822 /* non-inverse, i2s mode, slave, 16bits, from connsys */823 i2s_con |= 0 << INV_PAD_CTRL_SFT;824 i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;825 i2s_con |= 1 << I2S_SRC_SFT;826 i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT;827 i2s_con |= 0 << I2SIN_PAD_SEL_SFT;828 regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);829 830 /* use asrc */831 regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,832 I2S_BYPSRC_MASK_SFT, 0);833 834 /* slave mode, set i2s for asrc */835 regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,836 I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT);837 838 if (rate == 44100)839 regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1b9000);840 else if (rate == 32000)841 regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);842 else843 regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1e0000);844 845 /* Calibration setting */846 regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x140000);847 regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x36000);848 regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x2fc00);849 regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x7ef4);850 regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0xff5986);851 852 /* 0:Stereo 1:Mono */853 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,854 CHSET_IS_MONO_MASK_SFT, 0);855 856 return 0;857}858 859static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream,860 int cmd, struct snd_soc_dai *dai)861{862 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);863 struct mt8186_afe_private *afe_priv = afe->platform_priv;864 865 dev_dbg(afe->dev, "%s(), cmd %d, stream %d\n",866 __func__, cmd, substream->stream);867 868 switch (cmd) {869 case SNDRV_PCM_TRIGGER_START:870 case SNDRV_PCM_TRIGGER_RESUME:871 /* i2s enable */872 regmap_update_bits(afe->regmap,873 AFE_CONNSYS_I2S_CON,874 I2S_EN_MASK_SFT,875 BIT(I2S_EN_SFT));876 877 /* calibrator enable */878 regmap_update_bits(afe->regmap,879 AFE_ASRC_2CH_CON5,880 CALI_EN_MASK_SFT,881 BIT(CALI_EN_SFT));882 883 /* asrc enable */884 regmap_update_bits(afe->regmap,885 AFE_ASRC_2CH_CON0,886 CON0_CHSET_STR_CLR_MASK_SFT,887 BIT(CON0_CHSET_STR_CLR_SFT));888 regmap_update_bits(afe->regmap,889 AFE_ASRC_2CH_CON0,890 CON0_ASM_ON_MASK_SFT,891 BIT(CON0_ASM_ON_SFT));892 893 afe_priv->dai_on[dai->id] = true;894 return 0;895 case SNDRV_PCM_TRIGGER_STOP:896 case SNDRV_PCM_TRIGGER_SUSPEND:897 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,898 CON0_ASM_ON_MASK_SFT, 0);899 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,900 CALI_EN_MASK_SFT, 0);901 902 /* i2s disable */903 regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,904 I2S_EN_MASK_SFT, 0);905 906 /* bypass asrc */907 regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,908 I2S_BYPSRC_MASK_SFT, BIT(I2S_BYPSRC_SFT));909 910 afe_priv->dai_on[dai->id] = false;911 return 0;912 default:913 return -EINVAL;914 }915 return 0;916}917 918static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = {919 .hw_params = mtk_dai_connsys_i2s_hw_params,920 .trigger = mtk_dai_connsys_i2s_trigger,921};922 923/* i2s */924static int mtk_dai_i2s_config(struct mtk_base_afe *afe,925 struct snd_pcm_hw_params *params,926 int i2s_id)927{928 struct mt8186_afe_private *afe_priv = afe->platform_priv;929 struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];930 931 unsigned int rate = params_rate(params);932 unsigned int rate_reg = mt8186_rate_transform(afe->dev,933 rate, i2s_id);934 snd_pcm_format_t format = params_format(params);935 unsigned int i2s_con = 0;936 int ret;937 938 dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n",939 __func__, i2s_id, rate, format);940 941 i2s_priv->rate = rate;942 943 switch (i2s_id) {944 case MT8186_DAI_I2S_0:945 i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;946 i2s_con |= rate_reg << I2S_OUT_MODE_SFT;947 i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;948 i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;949 regmap_update_bits(afe->regmap, AFE_I2S_CON,950 0xffffeffa, i2s_con);951 break;952 case MT8186_DAI_I2S_1:953 i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;954 i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;955 i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;956 i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;957 regmap_update_bits(afe->regmap, AFE_I2S_CON1,958 0xffffeffa, i2s_con);959 break;960 case MT8186_DAI_I2S_2:961 i2s_con = 8 << I2S3_UPDATE_WORD_SFT;962 i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;963 i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;964 i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;965 regmap_update_bits(afe->regmap, AFE_I2S_CON2,966 0xffffeffa, i2s_con);967 break;968 case MT8186_DAI_I2S_3:969 i2s_con = rate_reg << I2S4_OUT_MODE_SFT;970 i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;971 i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;972 regmap_update_bits(afe->regmap, AFE_I2S_CON3,973 0xffffeffa, i2s_con);974 break;975 default:976 dev_err(afe->dev, "%s(), id %d not support\n",977 __func__, i2s_id);978 return -EINVAL;979 }980 981 /* set share i2s */982 if (i2s_priv->share_i2s_id >= 0) {983 ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);984 if (ret)985 return ret;986 }987 988 return 0;989}990 991static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream,992 struct snd_pcm_hw_params *params,993 struct snd_soc_dai *dai)994{995 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);996 997 return mtk_dai_i2s_config(afe, params, dai->id);998}999 1000static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,1001 int clk_id, unsigned int freq, int dir)1002{1003 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);1004 struct mt8186_afe_private *afe_priv = afe->platform_priv;1005 struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];1006 int apll;1007 int apll_rate;1008 1009 if (dir != SND_SOC_CLOCK_OUT) {1010 dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);1011 return -EINVAL;1012 }1013 1014 dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);1015 1016 apll = mt8186_get_apll_by_rate(afe, freq);1017 apll_rate = mt8186_get_apll_rate(afe, apll);1018 1019 if (freq > apll_rate) {1020 dev_err(afe->dev, "%s(), freq > apll rate", __func__);1021 return -EINVAL;1022 }1023 1024 if (apll_rate % freq != 0) {1025 dev_err(afe->dev, "%s(), APLL cannot generate freq Hz", __func__);1026 return -EINVAL;1027 }1028 1029 i2s_priv->mclk_rate = freq;1030 i2s_priv->mclk_apll = apll;1031 1032 if (i2s_priv->share_i2s_id > 0) {1033 struct mtk_afe_i2s_priv *share_i2s_priv;1034 1035 share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];1036 if (!share_i2s_priv) {1037 dev_err(afe->dev, "%s(), share_i2s_priv == NULL", __func__);1038 return -EINVAL;1039 }1040 1041 share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;1042 share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;1043 }1044 1045 return 0;1046}1047 1048static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {1049 .hw_params = mtk_dai_i2s_hw_params,1050 .set_sysclk = mtk_dai_i2s_set_sysclk,1051};1052 1053/* dai driver */1054#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)1055 1056#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\1057 SNDRV_PCM_RATE_88200 |\1058 SNDRV_PCM_RATE_96000 |\1059 SNDRV_PCM_RATE_176400 |\1060 SNDRV_PCM_RATE_192000)1061 1062#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\1063 SNDRV_PCM_FMTBIT_S24_LE |\1064 SNDRV_PCM_FMTBIT_S32_LE)1065 1066static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {1067 {1068 .name = "CONNSYS_I2S",1069 .id = MT8186_DAI_CONNSYS_I2S,1070 .capture = {1071 .stream_name = "Connsys I2S",1072 .channels_min = 1,1073 .channels_max = 2,1074 .rates = MTK_CONNSYS_I2S_RATES,1075 .formats = MTK_I2S_FORMATS,1076 },1077 .ops = &mtk_dai_connsys_i2s_ops,1078 },1079 {1080 .name = "I2S0",1081 .id = MT8186_DAI_I2S_0,1082 .capture = {1083 .stream_name = "I2S0",1084 .channels_min = 1,1085 .channels_max = 2,1086 .rates = MTK_I2S_RATES,1087 .formats = MTK_I2S_FORMATS,1088 },1089 .ops = &mtk_dai_i2s_ops,1090 },1091 {1092 .name = "I2S1",1093 .id = MT8186_DAI_I2S_1,1094 .playback = {1095 .stream_name = "I2S1",1096 .channels_min = 1,1097 .channels_max = 2,1098 .rates = MTK_I2S_RATES,1099 .formats = MTK_I2S_FORMATS,1100 },1101 .ops = &mtk_dai_i2s_ops,1102 },1103 {1104 .name = "I2S2",1105 .id = MT8186_DAI_I2S_2,1106 .capture = {1107 .stream_name = "I2S2",1108 .channels_min = 1,1109 .channels_max = 2,1110 .rates = MTK_I2S_RATES,1111 .formats = MTK_I2S_FORMATS,1112 },1113 .ops = &mtk_dai_i2s_ops,1114 },1115 {1116 .name = "I2S3",1117 .id = MT8186_DAI_I2S_3,1118 .playback = {1119 .stream_name = "I2S3",1120 .channels_min = 1,1121 .channels_max = 2,1122 .rates = MTK_I2S_RATES,1123 .formats = MTK_I2S_FORMATS,1124 },1125 .ops = &mtk_dai_i2s_ops,1126 }1127};1128 1129/* this enum is merely for mtk_afe_i2s_priv declare */1130enum {1131 DAI_I2S0 = 0,1132 DAI_I2S1,1133 DAI_I2S2,1134 DAI_I2S3,1135 DAI_I2S_NUM,1136};1137 1138static const struct mtk_afe_i2s_priv mt8186_i2s_priv[DAI_I2S_NUM] = {1139 [DAI_I2S0] = {1140 .id = MT8186_DAI_I2S_0,1141 .mclk_id = MT8186_I2S0_MCK,1142 .share_i2s_id = -1,1143 },1144 [DAI_I2S1] = {1145 .id = MT8186_DAI_I2S_1,1146 .mclk_id = MT8186_I2S1_MCK,1147 .share_i2s_id = -1,1148 },1149 [DAI_I2S2] = {1150 .id = MT8186_DAI_I2S_2,1151 .mclk_id = MT8186_I2S2_MCK,1152 .share_i2s_id = -1,1153 },1154 [DAI_I2S3] = {1155 .id = MT8186_DAI_I2S_3,1156 /* clock gate naming is hf_faud_i2s4_m_ck*/1157 .mclk_id = MT8186_I2S4_MCK,1158 .share_i2s_id = -1,1159 }1160};1161 1162/**1163 * mt8186_dai_i2s_set_share() - Set up I2S ports to share a single clock.1164 * @afe: Pointer to &struct mtk_base_afe1165 * @main_i2s_name: The name of the I2S port that will provide the clock1166 * @secondary_i2s_name: The name of the I2S port that will use this clock1167 */1168int mt8186_dai_i2s_set_share(struct mtk_base_afe *afe, const char *main_i2s_name,1169 const char *secondary_i2s_name)1170{1171 struct mtk_afe_i2s_priv *secondary_i2s_priv;1172 int main_i2s_id;1173 1174 secondary_i2s_priv = get_i2s_priv_by_name(afe, secondary_i2s_name);1175 if (!secondary_i2s_priv)1176 return -EINVAL;1177 1178 main_i2s_id = get_i2s_id_by_name(afe, main_i2s_name);1179 if (main_i2s_id < 0)1180 return main_i2s_id;1181 1182 secondary_i2s_priv->share_i2s_id = main_i2s_id;1183 1184 return 0;1185}1186EXPORT_SYMBOL_GPL(mt8186_dai_i2s_set_share);1187 1188static int mt8186_dai_i2s_set_priv(struct mtk_base_afe *afe)1189{1190 int i;1191 int ret;1192 1193 for (i = 0; i < DAI_I2S_NUM; i++) {1194 ret = mt8186_dai_set_priv(afe, mt8186_i2s_priv[i].id,1195 sizeof(struct mtk_afe_i2s_priv),1196 &mt8186_i2s_priv[i]);1197 if (ret)1198 return ret;1199 }1200 1201 return 0;1202}1203 1204int mt8186_dai_i2s_register(struct mtk_base_afe *afe)1205{1206 struct mtk_base_afe_dai *dai;1207 int ret;1208 1209 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);1210 if (!dai)1211 return -ENOMEM;1212 1213 list_add(&dai->list, &afe->sub_dais);1214 1215 dai->dai_drivers = mtk_dai_i2s_driver;1216 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);1217 1218 dai->controls = mtk_dai_i2s_controls;1219 dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);1220 dai->dapm_widgets = mtk_dai_i2s_widgets;1221 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);1222 dai->dapm_routes = mtk_dai_i2s_routes;1223 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);1224 1225 /* set all dai i2s private data */1226 ret = mt8186_dai_i2s_set_priv(afe);1227 if (ret)1228 return ret;1229 1230 return 0;1231}1232