1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright (c) 2020, The Linux Foundation. All rights reserved. 4 // 5 // sc7180.c -- ALSA SoC Machine driver for SC7180 6 7 #include <dt-bindings/sound/sc7180-lpass.h> 8 #include <dt-bindings/sound/qcom,q6afe.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/platform_device.h> 13 #include <sound/core.h> 14 #include <sound/jack.h> 15 #include <sound/pcm.h> 16 #include <sound/soc.h> 17 #include <uapi/linux/input-event-codes.h> 18 19 #include "../codecs/rt5682.h" 20 #include "../codecs/rt5682s.h" 21 #include "common.h" 22 #include "qdsp6/q6afe.h" 23 24 #define DEFAULT_MCLK_RATE 19200000 25 #define MI2S_BCLK_RATE 1536000 26 #define RT5682_PLL1_FREQ (48000 * 512) 27 28 #define DRIVER_NAME "SC7180" 29 30 struct sc7180_snd_data { 31 struct snd_soc_card card; 32 u32 pri_mi2s_clk_count; 33 struct snd_soc_jack hs_jack; 34 struct snd_soc_jack hdmi_jack; 35 struct gpio_desc *dmic_sel; 36 int dmic_switch; 37 }; 38 39 static void sc7180_jack_free(struct snd_jack *jack) 40 { 41 struct snd_soc_component *component = jack->private_data; 42 43 snd_soc_component_set_jack(component, NULL, NULL); 44 } 45 46 static struct snd_soc_jack_pin sc7180_jack_pins[] = { 47 { 48 .pin = "Headphone Jack", 49 .mask = SND_JACK_HEADPHONE, 50 }, 51 { 52 .pin = "Headset Mic", 53 .mask = SND_JACK_MICROPHONE, 54 }, 55 }; 56 57 static int sc7180_headset_init(struct snd_soc_pcm_runtime *rtd) 58 { 59 struct snd_soc_card *card = rtd->card; 60 struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card); 61 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 62 struct snd_soc_component *component = codec_dai->component; 63 struct snd_jack *jack; 64 int rval; 65 66 rval = snd_soc_card_jack_new_pins(card, "Headset Jack", 67 SND_JACK_HEADSET | 68 SND_JACK_HEADPHONE | 69 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 70 SND_JACK_BTN_2 | SND_JACK_BTN_3, 71 &pdata->hs_jack, 72 sc7180_jack_pins, 73 ARRAY_SIZE(sc7180_jack_pins)); 74 75 if (rval < 0) { 76 dev_err(card->dev, "Unable to add Headset Jack\n"); 77 return rval; 78 } 79 80 jack = pdata->hs_jack.jack; 81 82 snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 83 snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 84 snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 85 snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 86 87 jack->private_data = component; 88 jack->private_free = sc7180_jack_free; 89 90 return snd_soc_component_set_jack(component, &pdata->hs_jack, NULL); 91 } 92 93 static int sc7180_hdmi_init(struct snd_soc_pcm_runtime *rtd) 94 { 95 struct snd_soc_card *card = rtd->card; 96 struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card); 97 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 98 struct snd_soc_component *component = codec_dai->component; 99 struct snd_jack *jack; 100 int rval; 101 102 rval = snd_soc_card_jack_new( 103 card, "HDMI Jack", 104 SND_JACK_LINEOUT, 105 &pdata->hdmi_jack); 106 107 if (rval < 0) { 108 dev_err(card->dev, "Unable to add HDMI Jack\n"); 109 return rval; 110 } 111 112 jack = pdata->hdmi_jack.jack; 113 jack->private_data = component; 114 jack->private_free = sc7180_jack_free; 115 116 return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL); 117 } 118 119 static int sc7180_init(struct snd_soc_pcm_runtime *rtd) 120 { 121 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 122 123 switch (cpu_dai->id) { 124 case MI2S_PRIMARY: 125 return sc7180_headset_init(rtd); 126 case MI2S_SECONDARY: 127 return 0; 128 case LPASS_DP_RX: 129 return sc7180_hdmi_init(rtd); 130 default: 131 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 132 cpu_dai->id); 133 return -EINVAL; 134 } 135 return 0; 136 } 137 138 static int sc7180_qdsp_init(struct snd_soc_pcm_runtime *rtd) 139 { 140 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 141 142 switch (cpu_dai->id) { 143 case PRIMARY_MI2S_RX: 144 return sc7180_headset_init(rtd); 145 case PRIMARY_MI2S_TX: 146 case TERTIARY_MI2S_RX: 147 return 0; 148 case DISPLAY_PORT_RX: 149 return sc7180_hdmi_init(rtd); 150 default: 151 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 152 cpu_dai->id); 153 return -EINVAL; 154 } 155 return 0; 156 } 157 158 static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime *rtd) 159 { 160 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 161 int pll_id, pll_source, pll_in, pll_out, clk_id, ret; 162 163 if (!strcmp(codec_dai->name, "rt5682-aif1")) { 164 pll_source = RT5682_PLL1_S_MCLK; 165 pll_id = 0; 166 clk_id = RT5682_SCLK_S_PLL1; 167 pll_out = RT5682_PLL1_FREQ; 168 pll_in = DEFAULT_MCLK_RATE; 169 } else if (!strcmp(codec_dai->name, "rt5682s-aif1")) { 170 pll_source = RT5682S_PLL_S_MCLK; 171 pll_id = RT5682S_PLL2; 172 clk_id = RT5682S_SCLK_S_PLL2; 173 pll_out = RT5682_PLL1_FREQ; 174 pll_in = DEFAULT_MCLK_RATE; 175 } else { 176 return 0; 177 } 178 snd_soc_dai_set_fmt(codec_dai, 179 SND_SOC_DAIFMT_BC_FC | 180 SND_SOC_DAIFMT_NB_NF | 181 SND_SOC_DAIFMT_I2S); 182 183 /* Configure PLL1 for codec */ 184 ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, 185 pll_in, pll_out); 186 if (ret) { 187 dev_err(rtd->dev, "can't set codec pll: %d\n", ret); 188 return ret; 189 } 190 191 /* Configure sysclk for codec */ 192 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, pll_out, 193 SND_SOC_CLOCK_IN); 194 if (ret) 195 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", 196 ret); 197 198 return ret; 199 } 200 201 static int sc7180_snd_startup(struct snd_pcm_substream *substream) 202 { 203 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 204 struct snd_soc_card *card = rtd->card; 205 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 206 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 207 int ret; 208 209 switch (cpu_dai->id) { 210 case MI2S_PRIMARY: 211 if (++data->pri_mi2s_clk_count == 1) { 212 snd_soc_dai_set_sysclk(cpu_dai, 213 LPASS_MCLK0, 214 DEFAULT_MCLK_RATE, 215 SNDRV_PCM_STREAM_PLAYBACK); 216 } 217 218 ret = sc7180_startup_realtek_codec(rtd); 219 if (ret) 220 return ret; 221 222 break; 223 case MI2S_SECONDARY: 224 break; 225 case LPASS_DP_RX: 226 break; 227 default: 228 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 229 cpu_dai->id); 230 return -EINVAL; 231 } 232 return 0; 233 } 234 235 static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream) 236 { 237 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 238 struct snd_soc_card *card = rtd->card; 239 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 240 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 241 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 242 int ret; 243 244 switch (cpu_dai->id) { 245 case PRIMARY_MI2S_RX: 246 case PRIMARY_MI2S_TX: 247 if (++data->pri_mi2s_clk_count == 1) { 248 snd_soc_dai_set_sysclk(cpu_dai, 249 Q6AFE_LPASS_CLK_ID_MCLK_1, 250 DEFAULT_MCLK_RATE, 251 SNDRV_PCM_STREAM_PLAYBACK); 252 snd_soc_dai_set_sysclk(cpu_dai, 253 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 254 MI2S_BCLK_RATE, 255 SNDRV_PCM_STREAM_PLAYBACK); 256 } 257 258 snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); 259 260 ret = sc7180_startup_realtek_codec(rtd); 261 if (ret) 262 return ret; 263 264 break; 265 case TERTIARY_MI2S_RX: 266 snd_soc_dai_set_sysclk(cpu_dai, 267 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, 268 MI2S_BCLK_RATE, 269 SNDRV_PCM_STREAM_PLAYBACK); 270 271 snd_soc_dai_set_fmt(codec_dai, 272 SND_SOC_DAIFMT_BC_FC | 273 SND_SOC_DAIFMT_NB_NF | 274 SND_SOC_DAIFMT_I2S); 275 snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); 276 break; 277 case DISPLAY_PORT_RX: 278 break; 279 default: 280 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 281 cpu_dai->id); 282 return -EINVAL; 283 } 284 return 0; 285 } 286 287 static int dmic_get(struct snd_kcontrol *kcontrol, 288 struct snd_ctl_elem_value *ucontrol) 289 { 290 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 291 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(dapm->card); 292 293 ucontrol->value.integer.value[0] = data->dmic_switch; 294 return 0; 295 } 296 297 static int dmic_set(struct snd_kcontrol *kcontrol, 298 struct snd_ctl_elem_value *ucontrol) 299 { 300 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 301 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(dapm->card); 302 303 data->dmic_switch = ucontrol->value.integer.value[0]; 304 gpiod_set_value(data->dmic_sel, data->dmic_switch); 305 return 0; 306 } 307 308 static void sc7180_snd_shutdown(struct snd_pcm_substream *substream) 309 { 310 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 311 struct snd_soc_card *card = rtd->card; 312 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 313 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 314 315 switch (cpu_dai->id) { 316 case MI2S_PRIMARY: 317 if (--data->pri_mi2s_clk_count == 0) { 318 snd_soc_dai_set_sysclk(cpu_dai, 319 LPASS_MCLK0, 320 0, 321 SNDRV_PCM_STREAM_PLAYBACK); 322 } 323 break; 324 case MI2S_SECONDARY: 325 break; 326 case LPASS_DP_RX: 327 break; 328 default: 329 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 330 cpu_dai->id); 331 break; 332 } 333 } 334 335 static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream) 336 { 337 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 338 struct snd_soc_card *card = rtd->card; 339 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 340 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 341 342 switch (cpu_dai->id) { 343 case PRIMARY_MI2S_RX: 344 case PRIMARY_MI2S_TX: 345 if (--data->pri_mi2s_clk_count == 0) { 346 snd_soc_dai_set_sysclk(cpu_dai, 347 Q6AFE_LPASS_CLK_ID_MCLK_1, 348 0, 349 SNDRV_PCM_STREAM_PLAYBACK); 350 snd_soc_dai_set_sysclk(cpu_dai, 351 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 352 0, 353 SNDRV_PCM_STREAM_PLAYBACK); 354 } 355 break; 356 case TERTIARY_MI2S_RX: 357 snd_soc_dai_set_sysclk(cpu_dai, 358 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, 359 0, 360 SNDRV_PCM_STREAM_PLAYBACK); 361 break; 362 case DISPLAY_PORT_RX: 363 break; 364 default: 365 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 366 cpu_dai->id); 367 break; 368 } 369 } 370 371 static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd) 372 { 373 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 374 375 switch (cpu_dai->id) { 376 case MI2S_PRIMARY: 377 return 0; 378 case MI2S_SECONDARY: 379 return 0; 380 case LPASS_DP_RX: 381 return sc7180_hdmi_init(rtd); 382 default: 383 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 384 cpu_dai->id); 385 return -EINVAL; 386 } 387 return 0; 388 } 389 390 static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream) 391 { 392 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 393 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 394 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 395 struct snd_pcm_runtime *runtime = substream->runtime; 396 397 switch (cpu_dai->id) { 398 case MI2S_PRIMARY: 399 snd_soc_dai_set_fmt(codec_dai, 400 SND_SOC_DAIFMT_CBS_CFS | 401 SND_SOC_DAIFMT_NB_NF | 402 SND_SOC_DAIFMT_I2S); 403 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; 404 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 32); 405 406 break; 407 case MI2S_SECONDARY: 408 break; 409 case LPASS_DP_RX: 410 break; 411 default: 412 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 413 cpu_dai->id); 414 return -EINVAL; 415 } 416 return 0; 417 } 418 419 static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 420 struct snd_pcm_hw_params *params) 421 { 422 struct snd_interval *rate = hw_param_interval(params, 423 SNDRV_PCM_HW_PARAM_RATE); 424 struct snd_interval *channels = hw_param_interval(params, 425 SNDRV_PCM_HW_PARAM_CHANNELS); 426 427 rate->min = rate->max = 48000; 428 channels->min = channels->max = 2; 429 430 return 0; 431 } 432 433 static const struct snd_soc_ops sc7180_ops = { 434 .startup = sc7180_snd_startup, 435 .shutdown = sc7180_snd_shutdown, 436 }; 437 438 static const struct snd_soc_ops sc7180_qdsp_ops = { 439 .startup = sc7180_qdsp_snd_startup, 440 .shutdown = sc7180_qdsp_snd_shutdown, 441 }; 442 443 static const struct snd_soc_ops sc7180_adau7002_ops = { 444 .startup = sc7180_adau7002_snd_startup, 445 }; 446 447 static const struct snd_soc_dapm_widget sc7180_snd_widgets[] = { 448 SND_SOC_DAPM_HP("Headphone Jack", NULL), 449 SND_SOC_DAPM_MIC("Headset Mic", NULL), 450 }; 451 452 static const struct snd_kcontrol_new sc7180_snd_controls[] = { 453 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 454 SOC_DAPM_PIN_SWITCH("Headset Mic"), 455 }; 456 457 static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets[] = { 458 SND_SOC_DAPM_MIC("DMIC", NULL), 459 }; 460 461 static const char * const dmic_mux_text[] = { 462 "Front Mic", 463 "Rear Mic", 464 }; 465 466 static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum, 467 SND_SOC_NOPM, 0, dmic_mux_text); 468 469 static const struct snd_kcontrol_new sc7180_dmic_mux_control = 470 SOC_DAPM_ENUM_EXT("DMIC Select Mux", sc7180_dmic_enum, 471 dmic_get, dmic_set); 472 473 static const struct snd_soc_dapm_widget sc7180_snd_dual_mic_widgets[] = { 474 SND_SOC_DAPM_HP("Headphone Jack", NULL), 475 SND_SOC_DAPM_MIC("Headset Mic", NULL), 476 SND_SOC_DAPM_MIC("DMIC", NULL), 477 SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, &sc7180_dmic_mux_control), 478 }; 479 480 static const struct snd_kcontrol_new sc7180_snd_dual_mic_controls[] = { 481 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 482 SOC_DAPM_PIN_SWITCH("Headset Mic"), 483 }; 484 485 static const struct snd_soc_dapm_route sc7180_snd_dual_mic_audio_route[] = { 486 {"Dmic Mux", "Front Mic", "DMIC"}, 487 {"Dmic Mux", "Rear Mic", "DMIC"}, 488 }; 489 490 static int sc7180_snd_platform_probe(struct platform_device *pdev) 491 { 492 struct snd_soc_card *card; 493 struct sc7180_snd_data *data; 494 struct device *dev = &pdev->dev; 495 struct snd_soc_dai_link *link; 496 int ret; 497 int i; 498 bool qdsp = false, no_headphone = false; 499 500 /* Allocate the private data */ 501 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 502 if (!data) 503 return -ENOMEM; 504 505 card = &data->card; 506 snd_soc_card_set_drvdata(card, data); 507 508 card->owner = THIS_MODULE; 509 card->driver_name = DRIVER_NAME; 510 card->dev = dev; 511 card->dapm_widgets = sc7180_snd_widgets; 512 card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets); 513 card->controls = sc7180_snd_controls; 514 card->num_controls = ARRAY_SIZE(sc7180_snd_controls); 515 516 if (of_property_read_bool(dev->of_node, "dmic-gpios")) { 517 card->dapm_widgets = sc7180_snd_dual_mic_widgets, 518 card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_dual_mic_widgets), 519 card->controls = sc7180_snd_dual_mic_controls, 520 card->num_controls = ARRAY_SIZE(sc7180_snd_dual_mic_controls), 521 card->dapm_routes = sc7180_snd_dual_mic_audio_route, 522 card->num_dapm_routes = ARRAY_SIZE(sc7180_snd_dual_mic_audio_route), 523 data->dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW); 524 if (IS_ERR(data->dmic_sel)) { 525 dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", PTR_ERR(data->dmic_sel)); 526 return PTR_ERR(data->dmic_sel); 527 } 528 } 529 530 if (of_device_is_compatible(dev->of_node, "google,sc7180-coachz")) { 531 no_headphone = true; 532 card->dapm_widgets = sc7180_adau7002_snd_widgets; 533 card->num_dapm_widgets = ARRAY_SIZE(sc7180_adau7002_snd_widgets); 534 } else if (of_device_is_compatible(dev->of_node, "qcom,sc7180-qdsp6-sndcard")) { 535 qdsp = true; 536 } 537 538 ret = qcom_snd_parse_of(card); 539 if (ret) 540 return ret; 541 542 for_each_card_prelinks(card, i, link) { 543 if (no_headphone) { 544 link->ops = &sc7180_adau7002_ops; 545 link->init = sc7180_adau7002_init; 546 } else if (qdsp) { 547 if (link->no_pcm == 1) { 548 link->ops = &sc7180_qdsp_ops; 549 link->be_hw_params_fixup = sc7180_qdsp_be_hw_params_fixup; 550 link->init = sc7180_qdsp_init; 551 } 552 } else { 553 link->ops = &sc7180_ops; 554 link->init = sc7180_init; 555 } 556 } 557 558 return devm_snd_soc_register_card(dev, card); 559 } 560 561 static const struct of_device_id sc7180_snd_device_id[] = { 562 {.compatible = "google,sc7180-trogdor"}, 563 {.compatible = "google,sc7180-coachz"}, 564 {.compatible = "qcom,sc7180-qdsp6-sndcard"}, 565 {}, 566 }; 567 MODULE_DEVICE_TABLE(of, sc7180_snd_device_id); 568 569 static struct platform_driver sc7180_snd_driver = { 570 .probe = sc7180_snd_platform_probe, 571 .driver = { 572 .name = "msm-snd-sc7180", 573 .of_match_table = sc7180_snd_device_id, 574 .pm = &snd_soc_pm_ops, 575 }, 576 }; 577 module_platform_driver(sc7180_snd_driver); 578 579 MODULE_DESCRIPTION("sc7180 ASoC Machine Driver"); 580 MODULE_LICENSE("GPL"); 581