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_to_dapm(kcontrol); 291 struct snd_soc_card *card = snd_soc_dapm_to_card(dapm); 292 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(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_to_dapm(kcontrol); 302 struct snd_soc_card *card = snd_soc_dapm_to_card(dapm); 303 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 304 305 data->dmic_switch = ucontrol->value.integer.value[0]; 306 gpiod_set_value(data->dmic_sel, data->dmic_switch); 307 return 0; 308 } 309 310 static void sc7180_snd_shutdown(struct snd_pcm_substream *substream) 311 { 312 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 313 struct snd_soc_card *card = rtd->card; 314 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 315 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 316 317 switch (cpu_dai->id) { 318 case MI2S_PRIMARY: 319 if (--data->pri_mi2s_clk_count == 0) { 320 snd_soc_dai_set_sysclk(cpu_dai, 321 LPASS_MCLK0, 322 0, 323 SNDRV_PCM_STREAM_PLAYBACK); 324 } 325 break; 326 case MI2S_SECONDARY: 327 break; 328 case LPASS_DP_RX: 329 break; 330 default: 331 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 332 cpu_dai->id); 333 break; 334 } 335 } 336 337 static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream) 338 { 339 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 340 struct snd_soc_card *card = rtd->card; 341 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); 342 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 343 344 switch (cpu_dai->id) { 345 case PRIMARY_MI2S_RX: 346 case PRIMARY_MI2S_TX: 347 if (--data->pri_mi2s_clk_count == 0) { 348 snd_soc_dai_set_sysclk(cpu_dai, 349 Q6AFE_LPASS_CLK_ID_MCLK_1, 350 0, 351 SNDRV_PCM_STREAM_PLAYBACK); 352 snd_soc_dai_set_sysclk(cpu_dai, 353 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 354 0, 355 SNDRV_PCM_STREAM_PLAYBACK); 356 } 357 break; 358 case TERTIARY_MI2S_RX: 359 snd_soc_dai_set_sysclk(cpu_dai, 360 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, 361 0, 362 SNDRV_PCM_STREAM_PLAYBACK); 363 break; 364 case DISPLAY_PORT_RX: 365 break; 366 default: 367 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 368 cpu_dai->id); 369 break; 370 } 371 } 372 373 static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd) 374 { 375 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 376 377 switch (cpu_dai->id) { 378 case MI2S_PRIMARY: 379 return 0; 380 case MI2S_SECONDARY: 381 return 0; 382 case LPASS_DP_RX: 383 return sc7180_hdmi_init(rtd); 384 default: 385 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 386 cpu_dai->id); 387 return -EINVAL; 388 } 389 return 0; 390 } 391 392 static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream) 393 { 394 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 395 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 396 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 397 struct snd_pcm_runtime *runtime = substream->runtime; 398 399 switch (cpu_dai->id) { 400 case MI2S_PRIMARY: 401 snd_soc_dai_set_fmt(codec_dai, 402 SND_SOC_DAIFMT_CBC_CFC | 403 SND_SOC_DAIFMT_NB_NF | 404 SND_SOC_DAIFMT_I2S); 405 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; 406 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 32); 407 408 break; 409 case MI2S_SECONDARY: 410 break; 411 case LPASS_DP_RX: 412 break; 413 default: 414 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, 415 cpu_dai->id); 416 return -EINVAL; 417 } 418 return 0; 419 } 420 421 static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 422 struct snd_pcm_hw_params *params) 423 { 424 struct snd_interval *rate = hw_param_interval(params, 425 SNDRV_PCM_HW_PARAM_RATE); 426 struct snd_interval *channels = hw_param_interval(params, 427 SNDRV_PCM_HW_PARAM_CHANNELS); 428 429 rate->min = rate->max = 48000; 430 channels->min = channels->max = 2; 431 432 return 0; 433 } 434 435 static const struct snd_soc_ops sc7180_ops = { 436 .startup = sc7180_snd_startup, 437 .shutdown = sc7180_snd_shutdown, 438 }; 439 440 static const struct snd_soc_ops sc7180_qdsp_ops = { 441 .startup = sc7180_qdsp_snd_startup, 442 .shutdown = sc7180_qdsp_snd_shutdown, 443 }; 444 445 static const struct snd_soc_ops sc7180_adau7002_ops = { 446 .startup = sc7180_adau7002_snd_startup, 447 }; 448 449 static const struct snd_soc_dapm_widget sc7180_snd_widgets[] = { 450 SND_SOC_DAPM_HP("Headphone Jack", NULL), 451 SND_SOC_DAPM_MIC("Headset Mic", NULL), 452 }; 453 454 static const struct snd_kcontrol_new sc7180_snd_controls[] = { 455 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 456 SOC_DAPM_PIN_SWITCH("Headset Mic"), 457 }; 458 459 static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets[] = { 460 SND_SOC_DAPM_MIC("DMIC", NULL), 461 }; 462 463 static const char * const dmic_mux_text[] = { 464 "Front Mic", 465 "Rear Mic", 466 }; 467 468 static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum, 469 SND_SOC_NOPM, 0, dmic_mux_text); 470 471 static const struct snd_kcontrol_new sc7180_dmic_mux_control = 472 SOC_DAPM_ENUM_EXT("DMIC Select Mux", sc7180_dmic_enum, 473 dmic_get, dmic_set); 474 475 static const struct snd_soc_dapm_widget sc7180_snd_dual_mic_widgets[] = { 476 SND_SOC_DAPM_HP("Headphone Jack", NULL), 477 SND_SOC_DAPM_MIC("Headset Mic", NULL), 478 SND_SOC_DAPM_MIC("DMIC", NULL), 479 SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, &sc7180_dmic_mux_control), 480 }; 481 482 static const struct snd_kcontrol_new sc7180_snd_dual_mic_controls[] = { 483 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 484 SOC_DAPM_PIN_SWITCH("Headset Mic"), 485 }; 486 487 static const struct snd_soc_dapm_route sc7180_snd_dual_mic_audio_route[] = { 488 {"Dmic Mux", "Front Mic", "DMIC"}, 489 {"Dmic Mux", "Rear Mic", "DMIC"}, 490 }; 491 492 static int sc7180_snd_platform_probe(struct platform_device *pdev) 493 { 494 struct snd_soc_card *card; 495 struct sc7180_snd_data *data; 496 struct device *dev = &pdev->dev; 497 struct snd_soc_dai_link *link; 498 int ret; 499 int i; 500 bool qdsp = false, no_headphone = false; 501 502 /* Allocate the private data */ 503 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 504 if (!data) 505 return -ENOMEM; 506 507 card = &data->card; 508 snd_soc_card_set_drvdata(card, data); 509 510 card->owner = THIS_MODULE; 511 card->driver_name = DRIVER_NAME; 512 card->dev = dev; 513 card->dapm_widgets = sc7180_snd_widgets; 514 card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets); 515 card->controls = sc7180_snd_controls; 516 card->num_controls = ARRAY_SIZE(sc7180_snd_controls); 517 518 if (of_property_present(dev->of_node, "dmic-gpios")) { 519 card->dapm_widgets = sc7180_snd_dual_mic_widgets, 520 card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_dual_mic_widgets), 521 card->controls = sc7180_snd_dual_mic_controls, 522 card->num_controls = ARRAY_SIZE(sc7180_snd_dual_mic_controls), 523 card->dapm_routes = sc7180_snd_dual_mic_audio_route, 524 card->num_dapm_routes = ARRAY_SIZE(sc7180_snd_dual_mic_audio_route), 525 data->dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW); 526 if (IS_ERR(data->dmic_sel)) { 527 dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", PTR_ERR(data->dmic_sel)); 528 return PTR_ERR(data->dmic_sel); 529 } 530 } 531 532 if (of_device_is_compatible(dev->of_node, "google,sc7180-coachz")) { 533 no_headphone = true; 534 card->dapm_widgets = sc7180_adau7002_snd_widgets; 535 card->num_dapm_widgets = ARRAY_SIZE(sc7180_adau7002_snd_widgets); 536 } else if (of_device_is_compatible(dev->of_node, "qcom,sc7180-qdsp6-sndcard")) { 537 qdsp = true; 538 } 539 540 ret = qcom_snd_parse_of(card); 541 if (ret) 542 return ret; 543 544 for_each_card_prelinks(card, i, link) { 545 if (no_headphone) { 546 link->ops = &sc7180_adau7002_ops; 547 link->init = sc7180_adau7002_init; 548 } else if (qdsp) { 549 if (link->no_pcm == 1) { 550 link->ops = &sc7180_qdsp_ops; 551 link->be_hw_params_fixup = sc7180_qdsp_be_hw_params_fixup; 552 link->init = sc7180_qdsp_init; 553 } 554 } else { 555 link->ops = &sc7180_ops; 556 link->init = sc7180_init; 557 } 558 } 559 560 return devm_snd_soc_register_card(dev, card); 561 } 562 563 static const struct of_device_id sc7180_snd_device_id[] = { 564 {.compatible = "google,sc7180-trogdor"}, 565 {.compatible = "google,sc7180-coachz"}, 566 {.compatible = "qcom,sc7180-qdsp6-sndcard"}, 567 {}, 568 }; 569 MODULE_DEVICE_TABLE(of, sc7180_snd_device_id); 570 571 static struct platform_driver sc7180_snd_driver = { 572 .probe = sc7180_snd_platform_probe, 573 .driver = { 574 .name = "msm-snd-sc7180", 575 .of_match_table = sc7180_snd_device_id, 576 .pm = &snd_soc_pm_ops, 577 }, 578 }; 579 module_platform_driver(sc7180_snd_driver); 580 581 MODULE_DESCRIPTION("sc7180 ASoC Machine Driver"); 582 MODULE_LICENSE("GPL"); 583