1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * mt8196-nau8825.c -- mt8196 nau8825 ALSA SoC machine driver 4 * 5 * Copyright (c) 2025 MediaTek Inc. 6 * Author: Darren Ye <darren.ye@mediatek.com> 7 */ 8 9 #include <linux/input.h> 10 #include <linux/module.h> 11 #include <linux/of_device.h> 12 #include <linux/pm_runtime.h> 13 14 #include <sound/soc.h> 15 #include <sound/jack.h> 16 #include <sound/pcm_params.h> 17 18 #include "mt8196-afe-common.h" 19 20 #include "../../codecs/nau8825.h" 21 #include "../../codecs/rt5682s.h" 22 23 #include "../common/mtk-soc-card.h" 24 #include "../common/mtk-dsp-sof-common.h" 25 #include "../common/mtk-soundcard-driver.h" 26 #include "../common/mtk-afe-platform-driver.h" 27 28 #define NAU8825_HS_PRESENT BIT(0) 29 #define RT5682S_HS_PRESENT BIT(1) 30 #define RT5650_HS_PRESENT BIT(2) 31 32 /* 33 * Nau88l25 34 */ 35 #define NAU8825_CODEC_DAI "nau8825-hifi" 36 37 /* 38 * Rt5682s 39 */ 40 #define RT5682S_CODEC_DAI "rt5682s-aif1" 41 42 /* 43 * Rt5650 44 */ 45 #define RT5650_CODEC_DAI "rt5645-aif1" 46 47 #define SOF_DMA_DL1 "SOF_DMA_DL1" 48 #define SOF_DMA_DL_24CH "SOF_DMA_DL_24CH" 49 #define SOF_DMA_UL0 "SOF_DMA_UL0" 50 #define SOF_DMA_UL1 "SOF_DMA_UL1" 51 #define SOF_DMA_UL2 "SOF_DMA_UL2" 52 53 enum mt8196_jacks { 54 MT8196_JACK_HEADSET, 55 MT8196_JACK_DP, 56 MT8196_JACK_HDMI, 57 MT8196_JACK_MAX, 58 }; 59 60 static struct snd_soc_jack_pin mt8196_dp_jack_pins[] = { 61 { 62 .pin = "DP", 63 .mask = SND_JACK_AVOUT, 64 }, 65 }; 66 67 static struct snd_soc_jack_pin mt8196_hdmi_jack_pins[] = { 68 { 69 .pin = "HDMI", 70 .mask = SND_JACK_AVOUT, 71 }, 72 }; 73 74 static struct snd_soc_jack_pin nau8825_jack_pins[] = { 75 { 76 .pin = "Headphone Jack", 77 .mask = SND_JACK_HEADPHONE, 78 }, 79 { 80 .pin = "Headset Mic", 81 .mask = SND_JACK_MICROPHONE, 82 }, 83 }; 84 85 static const struct snd_kcontrol_new mt8196_dumb_spk_controls[] = { 86 SOC_DAPM_PIN_SWITCH("Ext Spk"), 87 }; 88 89 static const struct snd_soc_dapm_widget mt8196_dumb_spk_widgets[] = { 90 SND_SOC_DAPM_SPK("Ext Spk", NULL), 91 }; 92 93 static const struct snd_soc_dapm_widget mt8196_nau8825_widgets[] = { 94 SND_SOC_DAPM_HP("Headphone Jack", NULL), 95 SND_SOC_DAPM_MIC("Headset Mic", NULL), 96 SND_SOC_DAPM_SPK("Ext Spk", NULL), 97 SND_SOC_DAPM_SINK("DP"), 98 }; 99 100 static const struct snd_kcontrol_new mt8196_nau8825_controls[] = { 101 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 102 SOC_DAPM_PIN_SWITCH("Headset Mic"), 103 }; 104 105 #define EXT_SPK_AMP_W_NAME "Ext_Speaker_Amp" 106 107 static struct snd_soc_card mt8196_nau8825_soc_card; 108 109 static const struct snd_soc_dapm_widget mt8196_nau8825_card_widgets[] = { 110 /* SOF Uplink */ 111 SND_SOC_DAPM_MIXER("SOF_DMA_UL0", SND_SOC_NOPM, 0, 0, NULL, 0), 112 SND_SOC_DAPM_MIXER("SOF_DMA_UL1", SND_SOC_NOPM, 0, 0, NULL, 0), 113 SND_SOC_DAPM_MIXER("SOF_DMA_UL2", SND_SOC_NOPM, 0, 0, NULL, 0), 114 115 /* 116 * SOF Downlink 117 * the widgets on the machine driver cannot use the parameter with kcontrol 118 * because the widget domain is its platform driver. so sof downlink route 119 * is written in the i2s dai driver. 120 */ 121 }; 122 123 static const struct snd_soc_dapm_route mt8196_nau8825_card_routes[] = { 124 /* SOF Uplink */ 125 {"SOF_DMA_UL0", NULL, "UL0_CH1"}, 126 {"SOF_DMA_UL0", NULL, "UL0_CH2"}, 127 /* SOF Uplink */ 128 {"SOF_DMA_UL1", NULL, "UL1_CH1"}, 129 {"SOF_DMA_UL1", NULL, "UL1_CH2"}, 130 /* SOF Uplink */ 131 {"SOF_DMA_UL2", NULL, "UL2_CH1"}, 132 {"SOF_DMA_UL2", NULL, "UL2_CH2"}, 133 }; 134 135 static const struct snd_kcontrol_new mt8196_nau8825_card_controls[] = { 136 SOC_DAPM_PIN_SWITCH(EXT_SPK_AMP_W_NAME), 137 }; 138 139 /* 140 * define mtk_spk_i2s_mck node in dts when need mclk, 141 * BE i2s need assign snd_soc_ops = mt8196_nau8825_i2s_ops 142 */ 143 static int mt8196_nau8825_i2s_hw_params(struct snd_pcm_substream *substream, 144 struct snd_pcm_hw_params *params) 145 { 146 struct snd_soc_pcm_runtime *rtd = substream->private_data; 147 unsigned int rate = params_rate(params); 148 unsigned int mclk_fs_ratio = 128; 149 unsigned int mclk_fs = rate * mclk_fs_ratio; 150 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 151 152 return snd_soc_dai_set_sysclk(cpu_dai, 153 0, mclk_fs, SND_SOC_CLOCK_OUT); 154 } 155 156 static const struct snd_soc_ops mt8196_nau8825_i2s_ops = { 157 .hw_params = mt8196_nau8825_i2s_hw_params, 158 }; 159 160 static int mt8196_dptx_hw_params(struct snd_pcm_substream *substream, 161 struct snd_pcm_hw_params *params) 162 { 163 struct snd_soc_pcm_runtime *rtd = substream->private_data; 164 unsigned int rate = params_rate(params); 165 unsigned int mclk_fs_ratio = 256; 166 unsigned int mclk_fs = rate * mclk_fs_ratio; 167 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); 168 169 return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); 170 } 171 172 static const struct snd_soc_ops mt8196_dptx_ops = { 173 .hw_params = mt8196_dptx_hw_params, 174 }; 175 176 static int mt8196_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 177 struct snd_pcm_hw_params *params) 178 { 179 dev_info(rtd->dev, "fix format to 32bit\n"); 180 181 /* fix BE i2s format to 32bit, clean param mask first */ 182 snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 183 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); 184 185 params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 186 return 0; 187 } 188 189 static int mt8196_sof_be_hw_params(struct snd_pcm_substream *substream, 190 struct snd_pcm_hw_params *params) 191 { 192 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 193 struct snd_soc_component *cmpnt_afe = NULL; 194 struct snd_soc_pcm_runtime *runtime; 195 196 /* find afe component */ 197 for_each_card_rtds(rtd->card, runtime) { 198 cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME); 199 if (cmpnt_afe) { 200 dev_info(rtd->dev, "component->name: %s\n", cmpnt_afe->name); 201 break; 202 } 203 } 204 205 if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) { 206 dev_err(rtd->dev, "afe pm runtime is not active!!\n"); 207 return -EINVAL; 208 } 209 210 return 0; 211 } 212 213 static const struct snd_soc_ops mt8196_sof_be_ops = { 214 .hw_params = mt8196_sof_be_hw_params, 215 }; 216 217 static const struct sof_conn_stream g_sof_conn_streams[] = { 218 { 219 .sof_link = "AFE_SOF_DL1", 220 .sof_dma = SOF_DMA_DL1, 221 .stream_dir = SNDRV_PCM_STREAM_PLAYBACK 222 }, 223 { 224 .sof_link = "AFE_SOF_DL_24CH", 225 .sof_dma = SOF_DMA_DL_24CH, 226 .stream_dir = SNDRV_PCM_STREAM_PLAYBACK 227 }, 228 { 229 .sof_link = "AFE_SOF_UL0", 230 .sof_dma = SOF_DMA_UL0, 231 .stream_dir = SNDRV_PCM_STREAM_CAPTURE 232 }, 233 { 234 .sof_link = "AFE_SOF_UL1", 235 .sof_dma = SOF_DMA_UL1, 236 .stream_dir = SNDRV_PCM_STREAM_CAPTURE 237 }, 238 { 239 .sof_link = "AFE_SOF_UL2", 240 .sof_dma = SOF_DMA_UL2, 241 .stream_dir = SNDRV_PCM_STREAM_CAPTURE 242 }, 243 }; 244 245 /* FE */ 246 SND_SOC_DAILINK_DEFS(playback1, 247 DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 248 DAILINK_COMP_ARRAY(COMP_DUMMY()), 249 DAILINK_COMP_ARRAY(COMP_EMPTY())); 250 SND_SOC_DAILINK_DEFS(playback_24ch, 251 DAILINK_COMP_ARRAY(COMP_CPU("DL_24CH")), 252 DAILINK_COMP_ARRAY(COMP_DUMMY()), 253 DAILINK_COMP_ARRAY(COMP_EMPTY())); 254 SND_SOC_DAILINK_DEFS(capture0, 255 DAILINK_COMP_ARRAY(COMP_CPU("UL0")), 256 DAILINK_COMP_ARRAY(COMP_DUMMY()), 257 DAILINK_COMP_ARRAY(COMP_EMPTY())); 258 SND_SOC_DAILINK_DEFS(capture1, 259 DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 260 DAILINK_COMP_ARRAY(COMP_DUMMY()), 261 DAILINK_COMP_ARRAY(COMP_EMPTY())); 262 SND_SOC_DAILINK_DEFS(capture2, 263 DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 264 DAILINK_COMP_ARRAY(COMP_DUMMY()), 265 DAILINK_COMP_ARRAY(COMP_EMPTY())); 266 SND_SOC_DAILINK_DEFS(playback_hdmi, 267 DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), 268 DAILINK_COMP_ARRAY(COMP_DUMMY()), 269 DAILINK_COMP_ARRAY(COMP_EMPTY())); 270 SND_SOC_DAILINK_DEFS(playback2, 271 DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 272 DAILINK_COMP_ARRAY(COMP_DUMMY()), 273 DAILINK_COMP_ARRAY(COMP_EMPTY())); 274 SND_SOC_DAILINK_DEFS(capture_cm0, 275 DAILINK_COMP_ARRAY(COMP_CPU("UL_CM0")), 276 DAILINK_COMP_ARRAY(COMP_DUMMY()), 277 DAILINK_COMP_ARRAY(COMP_EMPTY())); 278 /* BE */ 279 SND_SOC_DAILINK_DEFS(ap_dmic, 280 DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")), 281 DAILINK_COMP_ARRAY(COMP_DUMMY()), 282 DAILINK_COMP_ARRAY(COMP_EMPTY())); 283 SND_SOC_DAILINK_DEFS(ap_dmic_ch34, 284 DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")), 285 DAILINK_COMP_ARRAY(COMP_DUMMY()), 286 DAILINK_COMP_ARRAY(COMP_EMPTY())); 287 SND_SOC_DAILINK_DEFS(ap_dmic_multich, 288 DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_MULTICH")), 289 DAILINK_COMP_ARRAY(COMP_DUMMY()), 290 DAILINK_COMP_ARRAY(COMP_EMPTY())); 291 SND_SOC_DAILINK_DEFS(i2sin6, 292 DAILINK_COMP_ARRAY(COMP_CPU("I2SIN6")), 293 DAILINK_COMP_ARRAY(COMP_DUMMY()), 294 DAILINK_COMP_ARRAY(COMP_EMPTY())); 295 SND_SOC_DAILINK_DEFS(i2sout3, 296 DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT3")), 297 DAILINK_COMP_ARRAY(COMP_DUMMY()), 298 DAILINK_COMP_ARRAY(COMP_EMPTY())); 299 SND_SOC_DAILINK_DEFS(i2sout4, 300 DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT4")), 301 DAILINK_COMP_ARRAY(COMP_DUMMY()), 302 DAILINK_COMP_ARRAY(COMP_EMPTY())); 303 SND_SOC_DAILINK_DEFS(i2sout6, 304 DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT6")), 305 DAILINK_COMP_ARRAY(COMP_DUMMY()), 306 DAILINK_COMP_ARRAY(COMP_EMPTY())); 307 SND_SOC_DAILINK_DEFS(tdm_dptx, 308 DAILINK_COMP_ARRAY(COMP_CPU("TDM_DPTX")), 309 DAILINK_COMP_ARRAY(COMP_DUMMY()), 310 DAILINK_COMP_ARRAY(COMP_EMPTY())); 311 SND_SOC_DAILINK_DEFS(AFE_SOF_DL_24CH, 312 DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL_24CH")), 313 DAILINK_COMP_ARRAY(COMP_DUMMY()), 314 DAILINK_COMP_ARRAY(COMP_EMPTY())); 315 SND_SOC_DAILINK_DEFS(AFE_SOF_DL1, 316 DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")), 317 DAILINK_COMP_ARRAY(COMP_DUMMY()), 318 DAILINK_COMP_ARRAY(COMP_EMPTY())); 319 SND_SOC_DAILINK_DEFS(AFE_SOF_UL0, 320 DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL0")), 321 DAILINK_COMP_ARRAY(COMP_DUMMY()), 322 DAILINK_COMP_ARRAY(COMP_EMPTY())); 323 SND_SOC_DAILINK_DEFS(AFE_SOF_UL1, 324 DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")), 325 DAILINK_COMP_ARRAY(COMP_DUMMY()), 326 DAILINK_COMP_ARRAY(COMP_EMPTY())); 327 SND_SOC_DAILINK_DEFS(AFE_SOF_UL2, 328 DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")), 329 DAILINK_COMP_ARRAY(COMP_DUMMY()), 330 DAILINK_COMP_ARRAY(COMP_EMPTY())); 331 332 static struct snd_soc_dai_link mt8196_nau8825_dai_links[] = { 333 /* 334 * The SOF topology expects PCM streams 0~4 to be available 335 * for the SOF PCM streams. Put the SOF BE definitions here 336 * so that the PCM device numbers are skipped over. 337 * (BE dailinks do not have PCM devices created.) 338 */ 339 { 340 .name = "AFE_SOF_DL_24CH", 341 .no_pcm = 1, 342 .playback_only = 1, 343 .ops = &mt8196_sof_be_ops, 344 SND_SOC_DAILINK_REG(AFE_SOF_DL_24CH), 345 }, 346 { 347 .name = "AFE_SOF_DL1", 348 .no_pcm = 1, 349 .playback_only = 1, 350 .ops = &mt8196_sof_be_ops, 351 SND_SOC_DAILINK_REG(AFE_SOF_DL1), 352 }, 353 { 354 .name = "AFE_SOF_UL0", 355 .no_pcm = 1, 356 .capture_only = 1, 357 .ops = &mt8196_sof_be_ops, 358 SND_SOC_DAILINK_REG(AFE_SOF_UL0), 359 }, 360 { 361 .name = "AFE_SOF_UL1", 362 .no_pcm = 1, 363 .capture_only = 1, 364 .ops = &mt8196_sof_be_ops, 365 SND_SOC_DAILINK_REG(AFE_SOF_UL1), 366 }, 367 { 368 .name = "AFE_SOF_UL2", 369 .no_pcm = 1, 370 .capture_only = 1, 371 .ops = &mt8196_sof_be_ops, 372 SND_SOC_DAILINK_REG(AFE_SOF_UL2), 373 }, 374 /* Front End DAI links */ 375 { 376 .name = "HDMI_FE", 377 .stream_name = "HDMI Playback", 378 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 379 SND_SOC_DPCM_TRIGGER_PRE}, 380 .dynamic = 1, 381 .playback_only = 1, 382 SND_SOC_DAILINK_REG(playback_hdmi), 383 }, 384 { 385 .name = "DL2_FE", 386 .stream_name = "DL2 Playback", 387 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 388 SND_SOC_DPCM_TRIGGER_PRE}, 389 .dynamic = 1, 390 .playback_only = 1, 391 SND_SOC_DAILINK_REG(playback2), 392 }, 393 { 394 .name = "UL_CM0_FE", 395 .stream_name = "UL_CM0 Capture", 396 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 397 SND_SOC_DPCM_TRIGGER_PRE}, 398 .dynamic = 1, 399 .capture_only = 1, 400 SND_SOC_DAILINK_REG(capture_cm0), 401 }, 402 { 403 .name = "DL_24CH_FE", 404 .stream_name = "DL_24CH Playback", 405 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 406 SND_SOC_DPCM_TRIGGER_PRE}, 407 .dynamic = 1, 408 .playback_only = 1, 409 SND_SOC_DAILINK_REG(playback_24ch), 410 }, 411 { 412 .name = "DL1_FE", 413 .stream_name = "DL1 Playback", 414 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 415 SND_SOC_DPCM_TRIGGER_PRE}, 416 .dynamic = 1, 417 .playback_only = 1, 418 SND_SOC_DAILINK_REG(playback1), 419 }, 420 { 421 .name = "UL0_FE", 422 .stream_name = "UL0 Capture", 423 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 424 SND_SOC_DPCM_TRIGGER_PRE}, 425 .dynamic = 1, 426 .capture_only = 1, 427 SND_SOC_DAILINK_REG(capture0), 428 }, 429 { 430 .name = "UL1_FE", 431 .stream_name = "UL1 Capture", 432 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 433 SND_SOC_DPCM_TRIGGER_PRE}, 434 .dynamic = 1, 435 .capture_only = 1, 436 SND_SOC_DAILINK_REG(capture1), 437 }, 438 { 439 .name = "UL2_FE", 440 .stream_name = "UL2 Capture", 441 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 442 SND_SOC_DPCM_TRIGGER_PRE}, 443 .dynamic = 1, 444 .capture_only = 1, 445 SND_SOC_DAILINK_REG(capture2), 446 }, 447 /* Back End DAI links */ 448 { 449 .name = "I2SIN6_BE", 450 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC 451 | SND_SOC_DAIFMT_GATED, 452 .ops = &mt8196_nau8825_i2s_ops, 453 .no_pcm = 1, 454 .capture_only = 1, 455 .ignore_suspend = 1, 456 .be_hw_params_fixup = mt8196_hw_params_fixup, 457 SND_SOC_DAILINK_REG(i2sin6), 458 }, 459 { 460 .name = "I2SOUT4_BE", 461 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC 462 | SND_SOC_DAIFMT_GATED, 463 .ops = &mt8196_nau8825_i2s_ops, 464 .no_pcm = 1, 465 .playback_only = 1, 466 .ignore_suspend = 1, 467 .ignore_pmdown_time = 1, 468 .be_hw_params_fixup = mt8196_hw_params_fixup, 469 SND_SOC_DAILINK_REG(i2sout4), 470 }, 471 { 472 .name = "I2SOUT6_BE", 473 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC 474 | SND_SOC_DAIFMT_GATED, 475 .ops = &mt8196_nau8825_i2s_ops, 476 .no_pcm = 1, 477 .playback_only = 1, 478 .ignore_suspend = 1, 479 .be_hw_params_fixup = mt8196_hw_params_fixup, 480 SND_SOC_DAILINK_REG(i2sout6), 481 }, 482 { 483 .name = "AP_DMIC_BE", 484 .no_pcm = 1, 485 .capture_only = 1, 486 .ignore_suspend = 1, 487 SND_SOC_DAILINK_REG(ap_dmic), 488 }, 489 { 490 .name = "AP_DMIC_CH34_BE", 491 .no_pcm = 1, 492 .capture_only = 1, 493 .ignore_suspend = 1, 494 SND_SOC_DAILINK_REG(ap_dmic_ch34), 495 }, 496 { 497 .name = "AP_DMIC_MULTICH_BE", 498 .no_pcm = 1, 499 .capture_only = 1, 500 .ignore_suspend = 1, 501 SND_SOC_DAILINK_REG(ap_dmic_multich), 502 }, 503 { 504 .name = "TDM_DPTX_BE", 505 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC 506 | SND_SOC_DAIFMT_GATED, 507 .ops = &mt8196_dptx_ops, 508 .be_hw_params_fixup = mt8196_hw_params_fixup, 509 .no_pcm = 1, 510 .playback_only = 1, 511 .ignore_suspend = 1, 512 SND_SOC_DAILINK_REG(tdm_dptx), 513 }, 514 { 515 .name = "I2SOUT3_BE", 516 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC 517 | SND_SOC_DAIFMT_GATED, 518 .ops = &mt8196_nau8825_i2s_ops, 519 .no_pcm = 1, 520 .playback_only = 1, 521 .ignore_suspend = 1, 522 SND_SOC_DAILINK_REG(i2sout3), 523 }, 524 }; 525 526 static int mt8196_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) 527 { 528 struct snd_soc_card *card = rtd->card; 529 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); 530 int ret = 0; 531 532 ret = snd_soc_dapm_new_controls(dapm, mt8196_dumb_spk_widgets, 533 ARRAY_SIZE(mt8196_dumb_spk_widgets)); 534 if (ret) { 535 dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret); 536 return ret; 537 } 538 539 ret = snd_soc_add_card_controls(card, mt8196_dumb_spk_controls, 540 ARRAY_SIZE(mt8196_dumb_spk_controls)); 541 if (ret) { 542 dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret); 543 return ret; 544 } 545 546 return 0; 547 } 548 549 static int mt8196_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) 550 { 551 struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); 552 struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_DP]; 553 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 554 int ret = 0; 555 556 ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_AVOUT, 557 jack, mt8196_dp_jack_pins, 558 ARRAY_SIZE(mt8196_dp_jack_pins)); 559 if (ret) { 560 dev_err(rtd->dev, "new jack failed: %d\n", ret); 561 return ret; 562 } 563 564 ret = snd_soc_component_set_jack(component, jack, NULL); 565 if (ret) { 566 dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n", 567 component->name, ret); 568 return ret; 569 } 570 571 return 0; 572 } 573 574 static int mt8196_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) 575 { 576 struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); 577 struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HDMI]; 578 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 579 int ret = 0; 580 581 ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", SND_JACK_AVOUT, 582 jack, mt8196_hdmi_jack_pins, 583 ARRAY_SIZE(mt8196_hdmi_jack_pins)); 584 if (ret) { 585 dev_err(rtd->dev, "new jack failed: %d\n", ret); 586 return ret; 587 } 588 589 ret = snd_soc_component_set_jack(component, jack, NULL); 590 if (ret) { 591 dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n", 592 component->name, ret); 593 return ret; 594 } 595 596 return 0; 597 } 598 599 static int mt8196_headset_codec_init(struct snd_soc_pcm_runtime *rtd) 600 { 601 struct snd_soc_card *card = rtd->card; 602 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); 603 struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); 604 struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HEADSET]; 605 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 606 int ret; 607 int type; 608 609 ret = snd_soc_dapm_new_controls(dapm, mt8196_nau8825_widgets, 610 ARRAY_SIZE(mt8196_nau8825_widgets)); 611 if (ret) { 612 dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret); 613 return ret; 614 } 615 616 ret = snd_soc_add_card_controls(card, mt8196_nau8825_controls, 617 ARRAY_SIZE(mt8196_nau8825_controls)); 618 if (ret) { 619 dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret); 620 return ret; 621 } 622 623 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 624 SND_JACK_HEADSET | SND_JACK_BTN_0 | 625 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 626 SND_JACK_BTN_3, 627 jack, 628 nau8825_jack_pins, 629 ARRAY_SIZE(nau8825_jack_pins)); 630 if (ret) { 631 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 632 return ret; 633 } 634 635 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 636 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 637 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 638 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 639 640 type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3; 641 ret = snd_soc_component_set_jack(component, jack, (void *)&type); 642 643 if (ret) { 644 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 645 return ret; 646 } 647 648 return 0; 649 }; 650 651 static void mt8196_headset_codec_exit(struct snd_soc_pcm_runtime *rtd) 652 { 653 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 654 655 snd_soc_component_set_jack(component, NULL, NULL); 656 } 657 658 static int mt8196_nau8825_hw_params(struct snd_pcm_substream *substream, 659 struct snd_pcm_hw_params *params) 660 { 661 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 662 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 663 unsigned int rate = params_rate(params); 664 unsigned int bit_width = params_width(params); 665 int clk_freq, ret; 666 667 clk_freq = rate * 2 * bit_width; 668 669 /* Configure clock for codec */ 670 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, 671 SND_SOC_CLOCK_IN); 672 if (ret < 0) { 673 dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); 674 return ret; 675 } 676 677 /* Configure pll for codec */ 678 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, 679 params_rate(params) * 256); 680 if (ret < 0) { 681 dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); 682 return ret; 683 } 684 685 return 0; 686 } 687 688 static const struct snd_soc_ops mt8196_nau8825_ops = { 689 .hw_params = mt8196_nau8825_hw_params, 690 }; 691 692 static int mt8196_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, 693 struct snd_pcm_hw_params *params) 694 { 695 struct snd_soc_pcm_runtime *rtd = substream->private_data; 696 struct snd_soc_card *card = rtd->card; 697 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 698 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 699 unsigned int rate = params_rate(params); 700 int bitwidth; 701 int ret; 702 703 bitwidth = snd_pcm_format_width(params_format(params)); 704 if (bitwidth < 0) { 705 dev_err(card->dev, "invalid bit width: %d\n", bitwidth); 706 return bitwidth; 707 } 708 709 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); 710 if (ret) { 711 dev_err(card->dev, "failed to set tdm slot\n"); 712 return ret; 713 } 714 715 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1, 716 rate * 32, rate * 512); 717 if (ret) { 718 dev_err(card->dev, "failed to set pll\n"); 719 return ret; 720 } 721 722 dev_info(card->dev, "%s set mclk rate: %d\n", __func__, rate * 512); 723 724 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_MCLK, 725 rate * 512, SND_SOC_CLOCK_IN); 726 if (ret) { 727 dev_err(card->dev, "failed to set sysclk\n"); 728 return ret; 729 } 730 731 return snd_soc_dai_set_sysclk(cpu_dai, 0, rate * 512, 732 SND_SOC_CLOCK_OUT); 733 } 734 735 static const struct snd_soc_ops mt8196_rt5682s_i2s_ops = { 736 .hw_params = mt8196_rt5682s_i2s_hw_params, 737 }; 738 739 static int mt8196_nau8825_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) 740 { 741 struct snd_soc_card *card = soc_card_data->card_data->card; 742 struct snd_soc_dai_link *dai_link; 743 bool init_nau8825 = false; 744 bool init_rt5682s = false; 745 bool init_rt5650 = false; 746 bool init_dumb = false; 747 int i; 748 749 dev_info(card->dev, "legacy: %d\n", legacy); 750 751 for_each_card_prelinks(card, i, dai_link) { 752 if (strcmp(dai_link->name, "TDM_DPTX_BE") == 0) { 753 if (dai_link->num_codecs && 754 strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 755 dai_link->init = mt8196_dptx_codec_init; 756 } else if (strcmp(dai_link->name, "I2SOUT3_BE") == 0) { 757 if (dai_link->num_codecs && 758 strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 759 dai_link->init = mt8196_hdmi_codec_init; 760 } else if (strcmp(dai_link->name, "I2SOUT6_BE") == 0 || 761 strcmp(dai_link->name, "I2SIN6_BE") == 0) { 762 if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) { 763 dai_link->ops = &mt8196_nau8825_ops; 764 if (!init_nau8825) { 765 dai_link->init = mt8196_headset_codec_init; 766 dai_link->exit = mt8196_headset_codec_exit; 767 init_nau8825 = true; 768 } 769 } else if (!strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) { 770 dai_link->ops = &mt8196_rt5682s_i2s_ops; 771 if (!init_rt5682s) { 772 dai_link->init = mt8196_headset_codec_init; 773 dai_link->exit = mt8196_headset_codec_exit; 774 init_rt5682s = true; 775 } 776 } else if (!strcmp(dai_link->codecs->dai_name, RT5650_CODEC_DAI)) { 777 dai_link->ops = &mt8196_rt5682s_i2s_ops; 778 if (!init_rt5650) { 779 dai_link->init = mt8196_headset_codec_init; 780 dai_link->exit = mt8196_headset_codec_exit; 781 init_rt5650 = true; 782 } 783 } else { 784 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { 785 if (!init_dumb) { 786 dai_link->init = mt8196_dumb_amp_init; 787 init_dumb = true; 788 } 789 } 790 } 791 } 792 } 793 794 return 0; 795 } 796 797 static const struct mtk_sof_priv mt8196_sof_priv = { 798 .conn_streams = g_sof_conn_streams, 799 .num_streams = ARRAY_SIZE(g_sof_conn_streams), 800 }; 801 802 static struct snd_soc_card mt8196_nau8825_soc_card = { 803 .owner = THIS_MODULE, 804 .dai_link = mt8196_nau8825_dai_links, 805 .num_links = ARRAY_SIZE(mt8196_nau8825_dai_links), 806 .dapm_widgets = mt8196_nau8825_card_widgets, 807 .num_dapm_widgets = ARRAY_SIZE(mt8196_nau8825_card_widgets), 808 .dapm_routes = mt8196_nau8825_card_routes, 809 .num_dapm_routes = ARRAY_SIZE(mt8196_nau8825_card_routes), 810 .controls = mt8196_nau8825_card_controls, 811 .num_controls = ARRAY_SIZE(mt8196_nau8825_card_controls), 812 }; 813 814 static const struct mtk_soundcard_pdata mt8196_nau8825_card = { 815 .card_name = "mt8196_nau8825", 816 .card_data = &(struct mtk_platform_card_data) { 817 .card = &mt8196_nau8825_soc_card, 818 .num_jacks = MT8196_JACK_MAX, 819 .flags = NAU8825_HS_PRESENT 820 }, 821 .sof_priv = &mt8196_sof_priv, 822 .soc_probe = mt8196_nau8825_soc_card_probe, 823 }; 824 825 static const struct mtk_soundcard_pdata mt8196_rt5682s_card = { 826 .card_name = "mt8196_rt5682s", 827 .card_data = &(struct mtk_platform_card_data) { 828 .card = &mt8196_nau8825_soc_card, 829 .num_jacks = MT8196_JACK_MAX, 830 .flags = RT5682S_HS_PRESENT 831 }, 832 .sof_priv = &mt8196_sof_priv, 833 .soc_probe = mt8196_nau8825_soc_card_probe, 834 }; 835 836 static const struct mtk_soundcard_pdata mt8196_rt5650_card = { 837 .card_name = "mt8196_rt5650", 838 .card_data = &(struct mtk_platform_card_data) { 839 .card = &mt8196_nau8825_soc_card, 840 .num_jacks = MT8196_JACK_MAX, 841 .flags = RT5650_HS_PRESENT 842 }, 843 .sof_priv = &mt8196_sof_priv, 844 .soc_probe = mt8196_nau8825_soc_card_probe, 845 }; 846 847 static const struct of_device_id mt8196_nau8825_dt_match[] = { 848 {.compatible = "mediatek,mt8196-nau8825-sound", .data = &mt8196_nau8825_card,}, 849 {.compatible = "mediatek,mt8196-rt5682s-sound", .data = &mt8196_rt5682s_card,}, 850 {.compatible = "mediatek,mt8196-rt5650-sound", .data = &mt8196_rt5650_card,}, 851 {} 852 }; 853 MODULE_DEVICE_TABLE(of, mt8196_nau8825_dt_match); 854 855 static struct platform_driver mt8196_nau8825_driver = { 856 .driver = { 857 .name = "mt8196-nau8825", 858 .of_match_table = mt8196_nau8825_dt_match, 859 .pm = &snd_soc_pm_ops, 860 }, 861 .probe = mtk_soundcard_common_probe, 862 }; 863 module_platform_driver(mt8196_nau8825_driver); 864 865 /* Module information */ 866 MODULE_DESCRIPTION("MT8196 nau8825 ALSA SoC machine driver"); 867 MODULE_AUTHOR("Darren Ye <darren.ye@mediatek.com>"); 868 MODULE_LICENSE("GPL"); 869 MODULE_ALIAS("mt8196 nau8825 soc card"); 870 871