1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright(c) 2021 Intel Corporation. 3 // Copyright(c) 2021 Nuvoton Corporation. 4 5 /* 6 * Intel SOF Machine Driver with Nuvoton headphone codec NAU8825 7 * and speaker codec RT1019P MAX98360a or MAX98373 8 */ 9 #include <linux/i2c.h> 10 #include <linux/input.h> 11 #include <linux/module.h> 12 #include <linux/platform_device.h> 13 #include <linux/dmi.h> 14 #include <sound/core.h> 15 #include <sound/jack.h> 16 #include <sound/pcm.h> 17 #include <sound/pcm_params.h> 18 #include <sound/soc.h> 19 #include <sound/sof.h> 20 #include <sound/soc-acpi.h> 21 #include "../../codecs/nau8825.h" 22 #include "../common/soc-intel-quirks.h" 23 #include "sof_board_helpers.h" 24 #include "sof_realtek_common.h" 25 #include "sof_maxim_common.h" 26 #include "sof_nuvoton_common.h" 27 #include "sof_ssp_common.h" 28 29 #define SOF_NAU8825_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) 30 #define SOF_NAU8825_SSP_CODEC_MASK (GENMASK(2, 0)) 31 #define SOF_NAU8825_SSP_AMP_SHIFT 4 32 #define SOF_NAU8825_SSP_AMP_MASK (GENMASK(6, 4)) 33 #define SOF_NAU8825_SSP_AMP(quirk) \ 34 (((quirk) << SOF_NAU8825_SSP_AMP_SHIFT) & SOF_NAU8825_SSP_AMP_MASK) 35 #define SOF_NAU8825_NUM_HDMIDEV_SHIFT 7 36 #define SOF_NAU8825_NUM_HDMIDEV_MASK (GENMASK(9, 7)) 37 #define SOF_NAU8825_NUM_HDMIDEV(quirk) \ 38 (((quirk) << SOF_NAU8825_NUM_HDMIDEV_SHIFT) & SOF_NAU8825_NUM_HDMIDEV_MASK) 39 40 /* BT audio offload: reserve 3 bits for future */ 41 #define SOF_BT_OFFLOAD_SSP_SHIFT 10 42 #define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(12, 10)) 43 #define SOF_BT_OFFLOAD_SSP(quirk) \ 44 (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) 45 #define SOF_SSP_BT_OFFLOAD_PRESENT BIT(13) 46 47 static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0); 48 49 static struct snd_soc_jack_pin jack_pins[] = { 50 { 51 .pin = "Headphone Jack", 52 .mask = SND_JACK_HEADPHONE, 53 }, 54 { 55 .pin = "Headset Mic", 56 .mask = SND_JACK_MICROPHONE, 57 }, 58 }; 59 60 static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 61 { 62 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 63 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 64 struct snd_soc_jack *jack = &ctx->headset_jack; 65 int ret; 66 67 /* 68 * Headset buttons map to the google Reference headset. 69 * These can be configured by userspace. 70 */ 71 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 72 SND_JACK_HEADSET | SND_JACK_BTN_0 | 73 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 74 SND_JACK_BTN_3, 75 jack, 76 jack_pins, 77 ARRAY_SIZE(jack_pins)); 78 if (ret) { 79 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 80 return ret; 81 } 82 83 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 84 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 85 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 86 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 87 88 ret = snd_soc_component_set_jack(component, jack, NULL); 89 if (ret) { 90 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 91 return ret; 92 } 93 94 return ret; 95 }; 96 97 static void sof_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd) 98 { 99 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 100 101 snd_soc_component_set_jack(component, NULL, NULL); 102 } 103 104 static int sof_nau8825_hw_params(struct snd_pcm_substream *substream, 105 struct snd_pcm_hw_params *params) 106 { 107 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 108 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 109 int clk_freq, ret; 110 111 clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */ 112 113 if (clk_freq <= 0) { 114 dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq); 115 return -EINVAL; 116 } 117 118 /* Configure clock for codec */ 119 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, 120 SND_SOC_CLOCK_IN); 121 if (ret < 0) { 122 dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); 123 return ret; 124 } 125 126 /* Configure pll for codec */ 127 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, 128 params_rate(params) * 256); 129 if (ret < 0) { 130 dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); 131 return ret; 132 } 133 134 return ret; 135 } 136 137 static struct snd_soc_ops sof_nau8825_ops = { 138 .hw_params = sof_nau8825_hw_params, 139 }; 140 141 static struct snd_soc_dai_link_component platform_component[] = { 142 { 143 /* name might be overridden during probe */ 144 .name = "0000:00:1f.3" 145 } 146 }; 147 148 static int sof_card_late_probe(struct snd_soc_card *card) 149 { 150 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); 151 struct snd_soc_dapm_context *dapm = &card->dapm; 152 int err; 153 154 if (ctx->amp_type == CODEC_MAX98373) { 155 /* Disable Left and Right Spk pin after boot */ 156 snd_soc_dapm_disable_pin(dapm, "Left Spk"); 157 snd_soc_dapm_disable_pin(dapm, "Right Spk"); 158 err = snd_soc_dapm_sync(dapm); 159 if (err < 0) 160 return err; 161 } 162 163 return sof_intel_board_card_late_probe(card); 164 } 165 166 static const struct snd_kcontrol_new sof_controls[] = { 167 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 168 SOC_DAPM_PIN_SWITCH("Headset Mic"), 169 SOC_DAPM_PIN_SWITCH("Left Spk"), 170 SOC_DAPM_PIN_SWITCH("Right Spk"), 171 }; 172 173 static const struct snd_soc_dapm_widget sof_widgets[] = { 174 SND_SOC_DAPM_HP("Headphone Jack", NULL), 175 SND_SOC_DAPM_MIC("Headset Mic", NULL), 176 SND_SOC_DAPM_SPK("Left Spk", NULL), 177 SND_SOC_DAPM_SPK("Right Spk", NULL), 178 }; 179 180 static const struct snd_soc_dapm_route sof_map[] = { 181 /* HP jack connectors - unknown if we have jack detection */ 182 { "Headphone Jack", NULL, "HPOL" }, 183 { "Headphone Jack", NULL, "HPOR" }, 184 185 /* other jacks */ 186 { "MIC", NULL, "Headset Mic" }, 187 }; 188 189 /* sof audio machine driver for nau8825 codec */ 190 static struct snd_soc_card sof_audio_card_nau8825 = { 191 .name = "nau8825", /* the sof- prefix is added by the core */ 192 .owner = THIS_MODULE, 193 .controls = sof_controls, 194 .num_controls = ARRAY_SIZE(sof_controls), 195 .dapm_widgets = sof_widgets, 196 .num_dapm_widgets = ARRAY_SIZE(sof_widgets), 197 .dapm_routes = sof_map, 198 .num_dapm_routes = ARRAY_SIZE(sof_map), 199 .fully_routed = true, 200 .late_probe = sof_card_late_probe, 201 }; 202 203 static struct snd_soc_dai_link_component nau8825_component[] = { 204 { 205 .name = "i2c-10508825:00", 206 .dai_name = "nau8825-hifi", 207 } 208 }; 209 210 static struct snd_soc_dai_link * 211 sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type, 212 int ssp_codec, int ssp_amp, int dmic_be_num, 213 int hdmi_num, bool idisp_codec) 214 { 215 struct snd_soc_dai_link_component *cpus; 216 struct snd_soc_dai_link *links; 217 int i; 218 int id = 0; 219 int ret; 220 221 links = devm_kcalloc(dev, sof_audio_card_nau8825.num_links, 222 sizeof(struct snd_soc_dai_link), GFP_KERNEL); 223 cpus = devm_kcalloc(dev, sof_audio_card_nau8825.num_links, 224 sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); 225 if (!links || !cpus) 226 goto devm_err; 227 228 /* codec SSP */ 229 links[id].name = devm_kasprintf(dev, GFP_KERNEL, 230 "SSP%d-Codec", ssp_codec); 231 if (!links[id].name) 232 goto devm_err; 233 234 links[id].id = id; 235 links[id].codecs = nau8825_component; 236 links[id].num_codecs = ARRAY_SIZE(nau8825_component); 237 links[id].platforms = platform_component; 238 links[id].num_platforms = ARRAY_SIZE(platform_component); 239 links[id].init = sof_nau8825_codec_init; 240 links[id].exit = sof_nau8825_codec_exit; 241 links[id].ops = &sof_nau8825_ops; 242 links[id].dpcm_playback = 1; 243 links[id].dpcm_capture = 1; 244 links[id].no_pcm = 1; 245 links[id].cpus = &cpus[id]; 246 links[id].num_cpus = 1; 247 248 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, 249 "SSP%d Pin", 250 ssp_codec); 251 if (!links[id].cpus->dai_name) 252 goto devm_err; 253 254 id++; 255 256 /* dmic */ 257 if (dmic_be_num > 0) { 258 /* at least we have dmic01 */ 259 ret = sof_intel_board_set_dmic_link(dev, &links[id], id, 260 SOF_DMIC_01); 261 if (ret) 262 return NULL; 263 264 id++; 265 } 266 267 if (dmic_be_num > 1) { 268 /* set up 2 BE links at most */ 269 ret = sof_intel_board_set_dmic_link(dev, &links[id], id, 270 SOF_DMIC_16K); 271 if (ret) 272 return NULL; 273 274 id++; 275 } 276 277 /* HDMI */ 278 for (i = 1; i <= hdmi_num; i++) { 279 ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], id, 280 i, idisp_codec); 281 if (ret) 282 return NULL; 283 284 id++; 285 } 286 287 /* speaker amp */ 288 if (amp_type != CODEC_NONE) { 289 links[id].name = devm_kasprintf(dev, GFP_KERNEL, 290 "SSP%d-Codec", ssp_amp); 291 if (!links[id].name) 292 goto devm_err; 293 294 links[id].id = id; 295 296 switch (amp_type) { 297 case CODEC_MAX98360A: 298 max_98360a_dai_link(&links[id]); 299 break; 300 case CODEC_MAX98373: 301 links[id].codecs = max_98373_components; 302 links[id].num_codecs = ARRAY_SIZE(max_98373_components); 303 links[id].init = max_98373_spk_codec_init; 304 links[id].ops = &max_98373_ops; 305 break; 306 case CODEC_NAU8318: 307 nau8318_set_dai_link(&links[id]); 308 break; 309 case CODEC_RT1015P: 310 sof_rt1015p_dai_link(&links[id]); 311 break; 312 case CODEC_RT1019P: 313 sof_rt1019p_dai_link(&links[id]); 314 break; 315 default: 316 dev_err(dev, "invalid amp type %d\n", amp_type); 317 return NULL; 318 } 319 320 links[id].platforms = platform_component; 321 links[id].num_platforms = ARRAY_SIZE(platform_component); 322 links[id].dpcm_playback = 1; 323 /* feedback stream or firmware-generated echo reference */ 324 links[id].dpcm_capture = 1; 325 326 links[id].no_pcm = 1; 327 links[id].cpus = &cpus[id]; 328 links[id].num_cpus = 1; 329 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, 330 "SSP%d Pin", 331 ssp_amp); 332 if (!links[id].cpus->dai_name) 333 goto devm_err; 334 id++; 335 } 336 337 /* BT audio offload */ 338 if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 339 int port = (sof_nau8825_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 340 SOF_BT_OFFLOAD_SSP_SHIFT; 341 342 links[id].id = id; 343 links[id].cpus = &cpus[id]; 344 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, 345 "SSP%d Pin", port); 346 if (!links[id].cpus->dai_name) 347 goto devm_err; 348 links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 349 if (!links[id].name) 350 goto devm_err; 351 links[id].codecs = &snd_soc_dummy_dlc; 352 links[id].num_codecs = 1; 353 links[id].platforms = platform_component; 354 links[id].num_platforms = ARRAY_SIZE(platform_component); 355 links[id].dpcm_playback = 1; 356 links[id].dpcm_capture = 1; 357 links[id].no_pcm = 1; 358 links[id].num_cpus = 1; 359 } 360 361 return links; 362 devm_err: 363 return NULL; 364 } 365 366 static int sof_audio_probe(struct platform_device *pdev) 367 { 368 struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; 369 struct snd_soc_dai_link *dai_links; 370 struct sof_card_private *ctx; 371 int ret, ssp_amp, ssp_codec; 372 373 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 374 if (!ctx) 375 return -ENOMEM; 376 377 if (pdev->id_entry && pdev->id_entry->driver_data) 378 sof_nau8825_quirk = (unsigned long)pdev->id_entry->driver_data; 379 380 ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); 381 ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); 382 383 dev_dbg(&pdev->dev, "sof_nau8825_quirk = %lx\n", sof_nau8825_quirk); 384 385 /* default number of DMIC DAI's */ 386 ctx->dmic_be_num = 2; 387 ctx->hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >> 388 SOF_NAU8825_NUM_HDMIDEV_SHIFT; 389 /* default number of HDMI DAI's */ 390 if (!ctx->hdmi_num) 391 ctx->hdmi_num = 3; 392 393 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) 394 ctx->hdmi.idisp_codec = true; 395 396 ssp_amp = (sof_nau8825_quirk & SOF_NAU8825_SSP_AMP_MASK) >> 397 SOF_NAU8825_SSP_AMP_SHIFT; 398 399 ssp_codec = sof_nau8825_quirk & SOF_NAU8825_SSP_CODEC_MASK; 400 401 /* compute number of dai links */ 402 sof_audio_card_nau8825.num_links = 1 + ctx->dmic_be_num + ctx->hdmi_num; 403 404 if (ctx->amp_type != CODEC_NONE) 405 sof_audio_card_nau8825.num_links++; 406 407 if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 408 sof_audio_card_nau8825.num_links++; 409 410 dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type, 411 ssp_codec, ssp_amp, 412 ctx->dmic_be_num, ctx->hdmi_num, 413 ctx->hdmi.idisp_codec); 414 if (!dai_links) 415 return -ENOMEM; 416 417 sof_audio_card_nau8825.dai_link = dai_links; 418 419 /* update codec_conf */ 420 switch (ctx->amp_type) { 421 case CODEC_MAX98373: 422 max_98373_set_codec_conf(&sof_audio_card_nau8825); 423 break; 424 case CODEC_RT1015P: 425 sof_rt1015p_codec_conf(&sof_audio_card_nau8825); 426 break; 427 case CODEC_NONE: 428 case CODEC_MAX98360A: 429 case CODEC_NAU8318: 430 case CODEC_RT1019P: 431 /* no codec conf required */ 432 break; 433 default: 434 dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type); 435 return -EINVAL; 436 } 437 438 sof_audio_card_nau8825.dev = &pdev->dev; 439 440 /* set platform name for each dailink */ 441 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_nau8825, 442 mach->mach_params.platform); 443 if (ret) 444 return ret; 445 446 snd_soc_card_set_drvdata(&sof_audio_card_nau8825, ctx); 447 448 return devm_snd_soc_register_card(&pdev->dev, 449 &sof_audio_card_nau8825); 450 } 451 452 static const struct platform_device_id board_ids[] = { 453 { 454 .name = "sof_nau8825", 455 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 456 SOF_NAU8825_NUM_HDMIDEV(4) | 457 SOF_BT_OFFLOAD_SSP(2) | 458 SOF_SSP_BT_OFFLOAD_PRESENT), 459 460 }, 461 { 462 .name = "adl_rt1019p_8825", 463 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 464 SOF_NAU8825_SSP_AMP(2) | 465 SOF_NAU8825_NUM_HDMIDEV(4)), 466 }, 467 { 468 .name = "adl_max98373_8825", 469 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 470 SOF_NAU8825_SSP_AMP(1) | 471 SOF_NAU8825_NUM_HDMIDEV(4) | 472 SOF_BT_OFFLOAD_SSP(2) | 473 SOF_SSP_BT_OFFLOAD_PRESENT), 474 }, 475 { 476 /* The limitation of length of char array, shorten the name */ 477 .name = "adl_mx98360a_8825", 478 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 479 SOF_NAU8825_SSP_AMP(1) | 480 SOF_NAU8825_NUM_HDMIDEV(4) | 481 SOF_BT_OFFLOAD_SSP(2) | 482 SOF_SSP_BT_OFFLOAD_PRESENT), 483 484 }, 485 { 486 .name = "adl_rt1015p_8825", 487 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 488 SOF_NAU8825_SSP_AMP(1) | 489 SOF_NAU8825_NUM_HDMIDEV(4) | 490 SOF_BT_OFFLOAD_SSP(2) | 491 SOF_SSP_BT_OFFLOAD_PRESENT), 492 }, 493 { 494 .name = "adl_nau8318_8825", 495 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 496 SOF_NAU8825_SSP_AMP(1) | 497 SOF_NAU8825_NUM_HDMIDEV(4) | 498 SOF_BT_OFFLOAD_SSP(2) | 499 SOF_SSP_BT_OFFLOAD_PRESENT), 500 }, 501 { 502 .name = "rpl_max98373_8825", 503 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 504 SOF_NAU8825_SSP_AMP(1) | 505 SOF_NAU8825_NUM_HDMIDEV(4) | 506 SOF_BT_OFFLOAD_SSP(2) | 507 SOF_SSP_BT_OFFLOAD_PRESENT), 508 }, 509 { 510 .name = "rpl_mx98360a_8825", 511 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 512 SOF_NAU8825_SSP_AMP(1) | 513 SOF_NAU8825_NUM_HDMIDEV(4) | 514 SOF_BT_OFFLOAD_SSP(2) | 515 SOF_SSP_BT_OFFLOAD_PRESENT), 516 }, 517 { 518 .name = "rpl_nau8318_8825", 519 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 520 SOF_NAU8825_SSP_AMP(1) | 521 SOF_NAU8825_NUM_HDMIDEV(4) | 522 SOF_BT_OFFLOAD_SSP(2) | 523 SOF_SSP_BT_OFFLOAD_PRESENT), 524 }, 525 { } 526 }; 527 MODULE_DEVICE_TABLE(platform, board_ids); 528 529 static struct platform_driver sof_audio = { 530 .probe = sof_audio_probe, 531 .driver = { 532 .name = "sof_nau8825", 533 .pm = &snd_soc_pm_ops, 534 }, 535 .id_table = board_ids, 536 }; 537 module_platform_driver(sof_audio) 538 539 /* Module information */ 540 MODULE_DESCRIPTION("SOF Audio Machine driver for NAU8825"); 541 MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>"); 542 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); 543 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 544 MODULE_LICENSE("GPL"); 545 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); 546 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 547 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_NUVOTON_COMMON); 548 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); 549 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); 550