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