1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // MediaTek ALSA SoC Audio DAI I2S Control 4 // 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 #include "mt8186-afe-common.h" 11 #include "mt8186-afe-gpio.h" 12 #include "mt8186-interconnection.h" 13 14 struct mtk_afe_pcm_priv { 15 unsigned int id; 16 unsigned int fmt; 17 unsigned int bck_invert; 18 unsigned int lck_invert; 19 }; 20 21 enum aud_tx_lch_rpt { 22 AUD_TX_LCH_RPT_NO_REPEAT = 0, 23 AUD_TX_LCH_RPT_REPEAT = 1 24 }; 25 26 enum aud_vbt_16k_mode { 27 AUD_VBT_16K_MODE_DISABLE = 0, 28 AUD_VBT_16K_MODE_ENABLE = 1 29 }; 30 31 enum aud_ext_modem { 32 AUD_EXT_MODEM_SELECT_INTERNAL = 0, 33 AUD_EXT_MODEM_SELECT_EXTERNAL = 1 34 }; 35 36 enum aud_pcm_sync_type { 37 /* bck sync length = 1 */ 38 AUD_PCM_ONE_BCK_CYCLE_SYNC = 0, 39 /* bck sync length = PCM_INTF_CON1[9:13] */ 40 AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1 41 }; 42 43 enum aud_bt_mode { 44 AUD_BT_MODE_DUAL_MIC_ON_TX = 0, 45 AUD_BT_MODE_SINGLE_MIC_ON_TX = 1 46 }; 47 48 enum aud_pcm_afifo_src { 49 /* slave mode & external modem uses different crystal */ 50 AUD_PCM_AFIFO_ASRC = 0, 51 /* slave mode & external modem uses the same crystal */ 52 AUD_PCM_AFIFO_AFIFO = 1 53 }; 54 55 enum aud_pcm_clock_source { 56 AUD_PCM_CLOCK_MASTER_MODE = 0, 57 AUD_PCM_CLOCK_SLAVE_MODE = 1 58 }; 59 60 enum aud_pcm_wlen { 61 AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0, 62 AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1 63 }; 64 65 enum aud_pcm_24bit { 66 AUD_PCM_24BIT_PCM_16_BITS = 0, 67 AUD_PCM_24BIT_PCM_24_BITS = 1 68 }; 69 70 enum aud_pcm_mode { 71 AUD_PCM_MODE_PCM_MODE_8K = 0, 72 AUD_PCM_MODE_PCM_MODE_16K = 1, 73 AUD_PCM_MODE_PCM_MODE_32K = 2, 74 AUD_PCM_MODE_PCM_MODE_48K = 3, 75 }; 76 77 enum aud_pcm_fmt { 78 AUD_PCM_FMT_I2S = 0, 79 AUD_PCM_FMT_EIAJ = 1, 80 AUD_PCM_FMT_PCM_MODE_A = 2, 81 AUD_PCM_FMT_PCM_MODE_B = 3 82 }; 83 84 enum aud_bclk_out_inv { 85 AUD_BCLK_OUT_INV_NO_INVERSE = 0, 86 AUD_BCLK_OUT_INV_INVERSE = 1 87 }; 88 89 enum aud_lrclk_out_inv { 90 AUD_LRCLK_OUT_INV_NO_INVERSE = 0, 91 AUD_LRCLK_OUT_INV_INVERSE = 1 92 }; 93 94 enum aud_pcm_en { 95 AUD_PCM_EN_DISABLE = 0, 96 AUD_PCM_EN_ENABLE = 1 97 }; 98 99 /* dai component */ 100 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = { 101 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN7, 102 I_ADDA_UL_CH1, 1, 0), 103 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN7, 104 I_DL2_CH1, 1, 0), 105 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN7_1, 106 I_DL4_CH1, 1, 0), 107 }; 108 109 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = { 110 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN8, 111 I_ADDA_UL_CH2, 1, 0), 112 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN8, 113 I_DL2_CH2, 1, 0), 114 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN8_1, 115 I_DL4_CH2, 1, 0), 116 }; 117 118 static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w, 119 struct snd_kcontrol *kcontrol, 120 int event) 121 { 122 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 123 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 124 125 dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", 126 __func__, w->name, event); 127 128 switch (event) { 129 case SND_SOC_DAPM_PRE_PMU: 130 mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_PCM, 0); 131 break; 132 case SND_SOC_DAPM_POST_PMD: 133 mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_PCM, 0); 134 break; 135 } 136 137 return 0; 138 } 139 140 /* pcm in/out lpbk */ 141 static const char * const pcm_lpbk_mux_map[] = { 142 "Normal", "Lpbk", 143 }; 144 145 static int pcm_lpbk_mux_map_value[] = { 146 0, 1, 147 }; 148 149 static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_in_lpbk_mux_map_enum, 150 PCM_INTF_CON1, 151 PCM_I2S_PCM_LOOPBACK_SFT, 152 1, 153 pcm_lpbk_mux_map, 154 pcm_lpbk_mux_map_value); 155 156 static const struct snd_kcontrol_new pcm_in_lpbk_mux_control = 157 SOC_DAPM_ENUM("PCM In Lpbk Select", pcm_in_lpbk_mux_map_enum); 158 159 static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_out_lpbk_mux_map_enum, 160 PCM_INTF_CON1, 161 PCM_I2S_PCM_LOOPBACK_SFT, 162 1, 163 pcm_lpbk_mux_map, 164 pcm_lpbk_mux_map_value); 165 166 static const struct snd_kcontrol_new pcm_out_lpbk_mux_control = 167 SOC_DAPM_ENUM("PCM Out Lpbk Select", pcm_out_lpbk_mux_map_enum); 168 169 static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { 170 /* inter-connections */ 171 SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0, 172 mtk_pcm_1_playback_ch1_mix, 173 ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)), 174 SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0, 175 mtk_pcm_1_playback_ch2_mix, 176 ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)), 177 178 SND_SOC_DAPM_SUPPLY("PCM_1_EN", 179 PCM_INTF_CON1, PCM_EN_SFT, 0, 180 mtk_pcm_en_event, 181 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 182 183 /* pcm in lpbk */ 184 SND_SOC_DAPM_MUX("PCM_In_Lpbk_Mux", 185 SND_SOC_NOPM, 0, 0, &pcm_in_lpbk_mux_control), 186 187 /* pcm out lpbk */ 188 SND_SOC_DAPM_MUX("PCM_Out_Lpbk_Mux", 189 SND_SOC_NOPM, 0, 0, &pcm_out_lpbk_mux_control), 190 }; 191 192 static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { 193 {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"}, 194 {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"}, 195 196 {"PCM 1 Playback", NULL, "PCM_1_EN"}, 197 {"PCM 1 Capture", NULL, "PCM_1_EN"}, 198 199 {"PCM_1_PB_CH1", "DL2_CH1 Switch", "DL2"}, 200 {"PCM_1_PB_CH2", "DL2_CH2 Switch", "DL2"}, 201 202 {"PCM_1_PB_CH1", "DL4_CH1 Switch", "DL4"}, 203 {"PCM_1_PB_CH2", "DL4_CH2 Switch", "DL4"}, 204 205 /* pcm out lpbk */ 206 {"PCM_Out_Lpbk_Mux", "Lpbk", "PCM 1 Playback"}, 207 {"I2S0", NULL, "PCM_Out_Lpbk_Mux"}, 208 209 /* pcm in lpbk */ 210 {"PCM_In_Lpbk_Mux", "Lpbk", "PCM 1 Capture"}, 211 {"I2S3", NULL, "PCM_In_Lpbk_Mux"}, 212 }; 213 214 /* dai ops */ 215 static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream, 216 struct snd_pcm_hw_params *params, 217 struct snd_soc_dai *dai) 218 { 219 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 220 struct mt8186_afe_private *afe_priv = afe->platform_priv; 221 struct snd_soc_dapm_widget *p = snd_soc_dai_get_widget_playback(dai); 222 struct snd_soc_dapm_widget *c = snd_soc_dai_get_widget_capture(dai); 223 int pcm_id = dai->id; 224 struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id]; 225 unsigned int rate = params_rate(params); 226 unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id); 227 snd_pcm_format_t format = params_format(params); 228 unsigned int data_width = 229 snd_pcm_format_width(format); 230 unsigned int wlen_width = 231 snd_pcm_format_physical_width(format); 232 unsigned int pcm_con = 0; 233 234 dev_dbg(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n", 235 __func__, dai->id, substream->stream, p->active, c->active); 236 dev_dbg(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n", 237 __func__, rate, rate_reg, data_width, wlen_width); 238 239 if (p->active || c->active) 240 return 0; 241 242 switch (dai->id) { 243 case MT8186_DAI_PCM: 244 pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT; 245 pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT; 246 pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT; 247 pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT; 248 pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT; 249 pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT; 250 pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT; 251 pcm_con |= 0 << PCM_SYNC_LENGTH_SFT; 252 253 /* sampling rate */ 254 pcm_con |= rate_reg << PCM_MODE_SFT; 255 256 /* format */ 257 pcm_con |= pcm_priv->fmt << PCM_FMT_SFT; 258 259 /* 24bit data width */ 260 if (data_width > 16) 261 pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT; 262 else 263 pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT; 264 265 /* wlen width*/ 266 if (wlen_width > 16) 267 pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT; 268 else 269 pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT; 270 271 /* clock invert */ 272 pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT; 273 pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT; 274 275 regmap_update_bits(afe->regmap, PCM_INTF_CON1, 0xfffffffe, pcm_con); 276 break; 277 default: 278 dev_err(afe->dev, "%s(), id %d not support\n", __func__, dai->id); 279 return -EINVAL; 280 } 281 282 return 0; 283 } 284 285 static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 286 { 287 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 288 struct mt8186_afe_private *afe_priv = afe->platform_priv; 289 struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id]; 290 291 /* DAI mode*/ 292 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 293 case SND_SOC_DAIFMT_I2S: 294 pcm_priv->fmt = AUD_PCM_FMT_I2S; 295 break; 296 case SND_SOC_DAIFMT_LEFT_J: 297 pcm_priv->fmt = AUD_PCM_FMT_EIAJ; 298 break; 299 case SND_SOC_DAIFMT_DSP_A: 300 pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_A; 301 break; 302 case SND_SOC_DAIFMT_DSP_B: 303 pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_B; 304 break; 305 default: 306 pcm_priv->fmt = AUD_PCM_FMT_I2S; 307 } 308 309 /* DAI clock inversion*/ 310 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 311 case SND_SOC_DAIFMT_NB_NF: 312 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; 313 pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; 314 break; 315 case SND_SOC_DAIFMT_NB_IF: 316 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; 317 pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; 318 break; 319 case SND_SOC_DAIFMT_IB_NF: 320 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; 321 pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; 322 break; 323 case SND_SOC_DAIFMT_IB_IF: 324 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; 325 pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; 326 break; 327 default: 328 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; 329 pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; 330 break; 331 } 332 333 return 0; 334 } 335 336 static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { 337 .hw_params = mtk_dai_pcm_hw_params, 338 .set_fmt = mtk_dai_pcm_set_fmt, 339 }; 340 341 /* dai driver */ 342 #define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\ 343 SNDRV_PCM_RATE_16000 |\ 344 SNDRV_PCM_RATE_32000 |\ 345 SNDRV_PCM_RATE_48000) 346 347 #define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 348 SNDRV_PCM_FMTBIT_S24_LE |\ 349 SNDRV_PCM_FMTBIT_S32_LE) 350 351 static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { 352 { 353 .name = "PCM 1", 354 .id = MT8186_DAI_PCM, 355 .playback = { 356 .stream_name = "PCM 1 Playback", 357 .channels_min = 1, 358 .channels_max = 2, 359 .rates = MTK_PCM_RATES, 360 .formats = MTK_PCM_FORMATS, 361 }, 362 .capture = { 363 .stream_name = "PCM 1 Capture", 364 .channels_min = 1, 365 .channels_max = 2, 366 .rates = MTK_PCM_RATES, 367 .formats = MTK_PCM_FORMATS, 368 }, 369 .ops = &mtk_dai_pcm_ops, 370 .symmetric_rate = 1, 371 .symmetric_sample_bits = 1, 372 }, 373 }; 374 375 static struct mtk_afe_pcm_priv *init_pcm_priv_data(struct mtk_base_afe *afe) 376 { 377 struct mtk_afe_pcm_priv *pcm_priv; 378 379 pcm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_pcm_priv), 380 GFP_KERNEL); 381 if (!pcm_priv) 382 return NULL; 383 384 pcm_priv->id = MT8186_DAI_PCM; 385 pcm_priv->fmt = AUD_PCM_FMT_I2S; 386 pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; 387 pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; 388 389 return pcm_priv; 390 } 391 392 int mt8186_dai_pcm_register(struct mtk_base_afe *afe) 393 { 394 struct mt8186_afe_private *afe_priv = afe->platform_priv; 395 struct mtk_afe_pcm_priv *pcm_priv; 396 struct mtk_base_afe_dai *dai; 397 398 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 399 if (!dai) 400 return -ENOMEM; 401 402 list_add(&dai->list, &afe->sub_dais); 403 404 dai->dai_drivers = mtk_dai_pcm_driver; 405 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); 406 407 dai->dapm_widgets = mtk_dai_pcm_widgets; 408 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); 409 dai->dapm_routes = mtk_dai_pcm_routes; 410 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); 411 412 pcm_priv = init_pcm_priv_data(afe); 413 if (!pcm_priv) 414 return -ENOMEM; 415 416 afe_priv->dai_priv[MT8186_DAI_PCM] = pcm_priv; 417 418 return 0; 419 } 420