Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: mediatek: mt7986: support etdm in platform driver

Add mt7986 etdm dai driver support.

Signed-off-by: Maso Huang <maso.huang@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20230817101338.18782-3-maso.huang@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Maso Huang and committed by
Mark Brown
9f8df795 c4c3c32d

+411
+411
sound/soc/mediatek/mt7986/mt7986-dai-etdm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * MediaTek ALSA SoC Audio DAI eTDM Control 4 + * 5 + * Copyright (c) 2023 MediaTek Inc. 6 + * Authors: Vic Wu <vic.wu@mediatek.com> 7 + * Maso Huang <maso.huang@mediatek.com> 8 + */ 9 + 10 + #include <linux/bitfield.h> 11 + #include <linux/bitops.h> 12 + #include <linux/regmap.h> 13 + #include <sound/pcm_params.h> 14 + #include "mt7986-afe-common.h" 15 + #include "mt7986-reg.h" 16 + 17 + #define HOPPING_CLK 0 18 + #define APLL_CLK 1 19 + #define MTK_DAI_ETDM_FORMAT_I2S 0 20 + #define MTK_DAI_ETDM_FORMAT_DSPA 4 21 + #define MTK_DAI_ETDM_FORMAT_DSPB 5 22 + 23 + enum { 24 + MTK_ETDM_RATE_8K = 0, 25 + MTK_ETDM_RATE_12K = 1, 26 + MTK_ETDM_RATE_16K = 2, 27 + MTK_ETDM_RATE_24K = 3, 28 + MTK_ETDM_RATE_32K = 4, 29 + MTK_ETDM_RATE_48K = 5, 30 + MTK_ETDM_RATE_96K = 7, 31 + MTK_ETDM_RATE_192K = 9, 32 + MTK_ETDM_RATE_11K = 16, 33 + MTK_ETDM_RATE_22K = 17, 34 + MTK_ETDM_RATE_44K = 18, 35 + MTK_ETDM_RATE_88K = 19, 36 + MTK_ETDM_RATE_176K = 20, 37 + }; 38 + 39 + struct mtk_dai_etdm_priv { 40 + bool bck_inv; 41 + bool lrck_inv; 42 + bool slave_mode; 43 + unsigned int format; 44 + }; 45 + 46 + static unsigned int mt7986_etdm_rate_transform(struct device *dev, unsigned int rate) 47 + { 48 + switch (rate) { 49 + case 8000: 50 + return MTK_ETDM_RATE_8K; 51 + case 11025: 52 + return MTK_ETDM_RATE_11K; 53 + case 12000: 54 + return MTK_ETDM_RATE_12K; 55 + case 16000: 56 + return MTK_ETDM_RATE_16K; 57 + case 22050: 58 + return MTK_ETDM_RATE_22K; 59 + case 24000: 60 + return MTK_ETDM_RATE_24K; 61 + case 32000: 62 + return MTK_ETDM_RATE_32K; 63 + case 44100: 64 + return MTK_ETDM_RATE_44K; 65 + case 48000: 66 + return MTK_ETDM_RATE_48K; 67 + case 88200: 68 + return MTK_ETDM_RATE_88K; 69 + case 96000: 70 + return MTK_ETDM_RATE_96K; 71 + case 176400: 72 + return MTK_ETDM_RATE_176K; 73 + case 192000: 74 + return MTK_ETDM_RATE_192K; 75 + default: 76 + dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", 77 + __func__, rate, MTK_ETDM_RATE_48K); 78 + return MTK_ETDM_RATE_48K; 79 + } 80 + } 81 + 82 + static int get_etdm_wlen(unsigned int bitwidth) 83 + { 84 + return bitwidth <= 16 ? 16 : 32; 85 + } 86 + 87 + /* dai component */ 88 + /* interconnection */ 89 + 90 + static const struct snd_kcontrol_new o124_mix[] = { 91 + SOC_DAPM_SINGLE_AUTODISABLE("I032_Switch", AFE_CONN124_1, 0, 1, 0), 92 + }; 93 + 94 + static const struct snd_kcontrol_new o125_mix[] = { 95 + SOC_DAPM_SINGLE_AUTODISABLE("I033_Switch", AFE_CONN125_1, 1, 1, 0), 96 + }; 97 + 98 + static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = { 99 + 100 + /* DL */ 101 + SND_SOC_DAPM_MIXER("I150", SND_SOC_NOPM, 0, 0, NULL, 0), 102 + SND_SOC_DAPM_MIXER("I151", SND_SOC_NOPM, 0, 0, NULL, 0), 103 + /* UL */ 104 + SND_SOC_DAPM_MIXER("O124", SND_SOC_NOPM, 0, 0, o124_mix, ARRAY_SIZE(o124_mix)), 105 + SND_SOC_DAPM_MIXER("O125", SND_SOC_NOPM, 0, 0, o125_mix, ARRAY_SIZE(o125_mix)), 106 + }; 107 + 108 + static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { 109 + {"I150", NULL, "ETDM Capture"}, 110 + {"I151", NULL, "ETDM Capture"}, 111 + {"ETDM Playback", NULL, "O124"}, 112 + {"ETDM Playback", NULL, "O125"}, 113 + {"O124", "I032_Switch", "I032"}, 114 + {"O125", "I033_Switch", "I033"}, 115 + }; 116 + 117 + /* dai ops */ 118 + static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, 119 + struct snd_soc_dai *dai) 120 + { 121 + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 122 + struct mt7986_afe_private *afe_priv = afe->platform_priv; 123 + int ret; 124 + 125 + ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); 126 + if (ret) 127 + return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); 128 + 129 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, 0); 130 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, 0); 131 + 132 + return 0; 133 + } 134 + 135 + static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, 136 + struct snd_soc_dai *dai) 137 + { 138 + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 139 + struct mt7986_afe_private *afe_priv = afe->platform_priv; 140 + 141 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, 142 + CLK_OUT5_PDN); 143 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, 144 + CLK_IN5_PDN); 145 + 146 + clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); 147 + } 148 + 149 + static unsigned int get_etdm_ch_fixup(unsigned int channels) 150 + { 151 + if (channels > 16) 152 + return 24; 153 + else if (channels > 8) 154 + return 16; 155 + else if (channels > 4) 156 + return 8; 157 + else if (channels > 2) 158 + return 4; 159 + else 160 + return 2; 161 + } 162 + 163 + static int mtk_dai_etdm_config(struct mtk_base_afe *afe, 164 + struct snd_pcm_hw_params *params, 165 + struct snd_soc_dai *dai, 166 + int stream) 167 + { 168 + struct mt7986_afe_private *afe_priv = afe->platform_priv; 169 + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; 170 + unsigned int rate = params_rate(params); 171 + unsigned int etdm_rate = mt7986_etdm_rate_transform(afe->dev, rate); 172 + unsigned int afe_rate = mt7986_afe_rate_transform(afe->dev, rate); 173 + unsigned int channels = params_channels(params); 174 + unsigned int bit_width = params_width(params); 175 + unsigned int wlen = get_etdm_wlen(bit_width); 176 + unsigned int val = 0; 177 + unsigned int mask = 0; 178 + 179 + dev_dbg(afe->dev, "%s(), stream %d, rate %u, bitwidth %u\n", 180 + __func__, stream, rate, bit_width); 181 + 182 + /* CON0 */ 183 + mask |= ETDM_BIT_LEN_MASK; 184 + val |= FIELD_PREP(ETDM_BIT_LEN_MASK, bit_width - 1); 185 + mask |= ETDM_WRD_LEN_MASK; 186 + val |= FIELD_PREP(ETDM_WRD_LEN_MASK, wlen - 1); 187 + mask |= ETDM_FMT_MASK; 188 + val |= FIELD_PREP(ETDM_FMT_MASK, etdm_data->format); 189 + mask |= ETDM_CH_NUM_MASK; 190 + val |= FIELD_PREP(ETDM_CH_NUM_MASK, get_etdm_ch_fixup(channels) - 1); 191 + mask |= RELATCH_SRC_MASK; 192 + val |= FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK); 193 + 194 + switch (stream) { 195 + case SNDRV_PCM_STREAM_PLAYBACK: 196 + /* set ETDM_OUT5_CON0 */ 197 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, mask, val); 198 + 199 + /* set ETDM_OUT5_CON4 */ 200 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, 201 + OUT_RELATCH_MASK, OUT_RELATCH(afe_rate)); 202 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, 203 + OUT_CLK_SRC_MASK, OUT_CLK_SRC(APLL_CLK)); 204 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, 205 + OUT_SEL_FS_MASK, OUT_SEL_FS(etdm_rate)); 206 + 207 + /* set ETDM_OUT5_CON5 */ 208 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON5, 209 + ETDM_CLK_DIV_MASK, ETDM_CLK_DIV); 210 + break; 211 + case SNDRV_PCM_STREAM_CAPTURE: 212 + /* set ETDM_IN5_CON0 */ 213 + regmap_update_bits(afe->regmap, ETDM_IN5_CON0, mask, val); 214 + regmap_update_bits(afe->regmap, ETDM_IN5_CON0, 215 + ETDM_SYNC_MASK, ETDM_SYNC); 216 + 217 + /* set ETDM_IN5_CON2 */ 218 + regmap_update_bits(afe->regmap, ETDM_IN5_CON2, 219 + IN_CLK_SRC_MASK, IN_CLK_SRC(APLL_CLK)); 220 + 221 + /* set ETDM_IN5_CON3 */ 222 + regmap_update_bits(afe->regmap, ETDM_IN5_CON3, 223 + IN_SEL_FS_MASK, IN_SEL_FS(etdm_rate)); 224 + 225 + /* set ETDM_IN5_CON4 */ 226 + regmap_update_bits(afe->regmap, ETDM_IN5_CON4, 227 + IN_RELATCH_MASK, IN_RELATCH(afe_rate)); 228 + break; 229 + default: 230 + break; 231 + } 232 + 233 + return 0; 234 + } 235 + 236 + static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, 237 + struct snd_pcm_hw_params *params, 238 + struct snd_soc_dai *dai) 239 + { 240 + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 241 + 242 + mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK); 243 + mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE); 244 + 245 + return 0; 246 + } 247 + 248 + static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, 249 + struct snd_soc_dai *dai) 250 + { 251 + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 252 + 253 + dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id); 254 + switch (cmd) { 255 + case SNDRV_PCM_TRIGGER_START: 256 + case SNDRV_PCM_TRIGGER_RESUME: 257 + regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, 258 + ETDM_EN); 259 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, 260 + ETDM_EN); 261 + break; 262 + case SNDRV_PCM_TRIGGER_STOP: 263 + case SNDRV_PCM_TRIGGER_SUSPEND: 264 + regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, 265 + 0); 266 + regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, 267 + 0); 268 + break; 269 + default: 270 + break; 271 + } 272 + 273 + return 0; 274 + } 275 + 276 + static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 277 + { 278 + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 279 + struct mt7986_afe_private *afe_priv = afe->platform_priv; 280 + struct mtk_dai_etdm_priv *etdm_data; 281 + void *priv_data; 282 + 283 + switch (dai->id) { 284 + case MT7986_DAI_ETDM: 285 + break; 286 + default: 287 + dev_warn(afe->dev, "%s(), id %d not support\n", 288 + __func__, dai->id); 289 + return -EINVAL; 290 + } 291 + 292 + priv_data = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_etdm_priv), 293 + GFP_KERNEL); 294 + if (!priv_data) 295 + return -ENOMEM; 296 + 297 + afe_priv->dai_priv[dai->id] = priv_data; 298 + etdm_data = afe_priv->dai_priv[dai->id]; 299 + 300 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 301 + case SND_SOC_DAIFMT_I2S: 302 + etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; 303 + break; 304 + case SND_SOC_DAIFMT_DSP_A: 305 + etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA; 306 + break; 307 + case SND_SOC_DAIFMT_DSP_B: 308 + etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB; 309 + break; 310 + default: 311 + return -EINVAL; 312 + } 313 + 314 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 315 + case SND_SOC_DAIFMT_NB_NF: 316 + etdm_data->bck_inv = false; 317 + etdm_data->lrck_inv = false; 318 + break; 319 + case SND_SOC_DAIFMT_NB_IF: 320 + etdm_data->bck_inv = false; 321 + etdm_data->lrck_inv = true; 322 + break; 323 + case SND_SOC_DAIFMT_IB_NF: 324 + etdm_data->bck_inv = true; 325 + etdm_data->lrck_inv = false; 326 + break; 327 + case SND_SOC_DAIFMT_IB_IF: 328 + etdm_data->bck_inv = true; 329 + etdm_data->lrck_inv = true; 330 + break; 331 + default: 332 + return -EINVAL; 333 + } 334 + 335 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 336 + case SND_SOC_DAIFMT_CBM_CFM: 337 + etdm_data->slave_mode = true; 338 + break; 339 + case SND_SOC_DAIFMT_CBS_CFS: 340 + etdm_data->slave_mode = false; 341 + break; 342 + default: 343 + return -EINVAL; 344 + } 345 + 346 + return 0; 347 + } 348 + 349 + static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { 350 + .startup = mtk_dai_etdm_startup, 351 + .shutdown = mtk_dai_etdm_shutdown, 352 + .hw_params = mtk_dai_etdm_hw_params, 353 + .trigger = mtk_dai_etdm_trigger, 354 + .set_fmt = mtk_dai_etdm_set_fmt, 355 + }; 356 + 357 + /* dai driver */ 358 + #define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ 359 + SNDRV_PCM_RATE_88200 |\ 360 + SNDRV_PCM_RATE_96000 |\ 361 + SNDRV_PCM_RATE_176400 |\ 362 + SNDRV_PCM_RATE_192000) 363 + 364 + #define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 365 + SNDRV_PCM_FMTBIT_S24_LE |\ 366 + SNDRV_PCM_FMTBIT_S32_LE) 367 + 368 + static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = { 369 + { 370 + .name = "ETDM", 371 + .id = MT7986_DAI_ETDM, 372 + .capture = { 373 + .stream_name = "ETDM Capture", 374 + .channels_min = 1, 375 + .channels_max = 2, 376 + .rates = MTK_ETDM_RATES, 377 + .formats = MTK_ETDM_FORMATS, 378 + }, 379 + .playback = { 380 + .stream_name = "ETDM Playback", 381 + .channels_min = 1, 382 + .channels_max = 2, 383 + .rates = MTK_ETDM_RATES, 384 + .formats = MTK_ETDM_FORMATS, 385 + }, 386 + .ops = &mtk_dai_etdm_ops, 387 + .symmetric_rate = 1, 388 + .symmetric_sample_bits = 1, 389 + }, 390 + }; 391 + 392 + int mt7986_dai_etdm_register(struct mtk_base_afe *afe) 393 + { 394 + struct mtk_base_afe_dai *dai; 395 + 396 + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 397 + if (!dai) 398 + return -ENOMEM; 399 + 400 + list_add(&dai->list, &afe->sub_dais); 401 + 402 + dai->dai_drivers = mtk_dai_etdm_driver; 403 + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver); 404 + 405 + dai->dapm_widgets = mtk_dai_etdm_widgets; 406 + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets); 407 + dai->dapm_routes = mtk_dai_etdm_routes; 408 + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes); 409 + 410 + return 0; 411 + }