1 // SPDX-License-Identifier: GPL-2.0-only
3 // Copyright (c) 2020, The Linux Foundation. All rights reserved.
5 // sc7180.c -- ALSA SoC Machine driver for SC7180
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>
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>
20 #include "../codecs/rt5682.h"
21 #include "../codecs/rt5682s.h"
23 #include "qdsp6/q6afe.h"
25 #define DEFAULT_MCLK_RATE 19200000
26 #define MI2S_BCLK_RATE 1536000
27 #define RT5682_PLL1_FREQ (48000 * 512)
29 #define DRIVER_NAME "SC7180"
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;
40 static void sc7180_jack_free(struct snd_jack *jack)
42 struct snd_soc_component *component = jack->private_data;
44 snd_soc_component_set_jack(component, NULL, NULL);
47 static struct snd_soc_jack_pin sc7180_jack_pins[] = {
49 .pin = "Headphone Jack",
50 .mask = SND_JACK_HEADPHONE,
54 .mask = SND_JACK_MICROPHONE,
58 static int sc7180_headset_init(struct snd_soc_pcm_runtime *rtd)
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;
67 rval = snd_soc_card_jack_new_pins(card, "Headset Jack",
70 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
71 SND_JACK_BTN_2 | SND_JACK_BTN_3,
74 ARRAY_SIZE(sc7180_jack_pins));
77 dev_err(card->dev, "Unable to add Headset Jack\n");
81 jack = pdata->hs_jack.jack;
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);
88 jack->private_data = component;
89 jack->private_free = sc7180_jack_free;
91 return snd_soc_component_set_jack(component, &pdata->hs_jack, NULL);
94 static int sc7180_hdmi_init(struct snd_soc_pcm_runtime *rtd)
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;
103 rval = snd_soc_card_jack_new(
109 dev_err(card->dev, "Unable to add HDMI Jack\n");
113 jack = pdata->hdmi_jack.jack;
114 jack->private_data = component;
115 jack->private_free = sc7180_jack_free;
117 return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL);
120 static int sc7180_init(struct snd_soc_pcm_runtime *rtd)
122 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
124 switch (cpu_dai->id) {
126 return sc7180_headset_init(rtd);
130 return sc7180_hdmi_init(rtd);
132 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
139 static int sc7180_qdsp_init(struct snd_soc_pcm_runtime *rtd)
141 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
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:
149 case DISPLAY_PORT_RX:
150 return sc7180_hdmi_init(rtd);
152 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
159 static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime *rtd)
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;
164 if (!strcmp(codec_dai->name, "rt5682-aif1")) {
165 pll_source = RT5682_PLL1_S_MCLK;
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;
179 snd_soc_dai_set_fmt(codec_dai,
180 SND_SOC_DAIFMT_BC_FC |
181 SND_SOC_DAIFMT_NB_NF |
184 /* Configure PLL1 for codec */
185 ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source,
188 dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
192 /* Configure sysclk for codec */
193 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, pll_out,
196 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
202 static int sc7180_snd_startup(struct snd_pcm_substream *substream)
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);
210 switch (cpu_dai->id) {
212 if (++data->pri_mi2s_clk_count == 1) {
213 snd_soc_dai_set_sysclk(cpu_dai,
216 SNDRV_PCM_STREAM_PLAYBACK);
219 ret = sc7180_startup_realtek_codec(rtd);
229 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
236 static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream)
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);
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,
252 SNDRV_PCM_STREAM_PLAYBACK);
253 snd_soc_dai_set_sysclk(cpu_dai,
254 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
256 SNDRV_PCM_STREAM_PLAYBACK);
259 snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
261 ret = sc7180_startup_realtek_codec(rtd);
266 case TERTIARY_MI2S_RX:
267 snd_soc_dai_set_sysclk(cpu_dai,
268 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
270 SNDRV_PCM_STREAM_PLAYBACK);
272 snd_soc_dai_set_fmt(codec_dai,
273 SND_SOC_DAIFMT_BC_FC |
274 SND_SOC_DAIFMT_NB_NF |
276 snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
278 case DISPLAY_PORT_RX:
281 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
288 static int dmic_get(struct snd_kcontrol *kcontrol,
289 struct snd_ctl_elem_value *ucontrol)
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);
294 ucontrol->value.integer.value[0] = data->dmic_switch;
298 static int dmic_set(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
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);
304 data->dmic_switch = ucontrol->value.integer.value[0];
305 gpiod_set_value(data->dmic_sel, data->dmic_switch);
309 static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
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);
316 switch (cpu_dai->id) {
318 if (--data->pri_mi2s_clk_count == 0) {
319 snd_soc_dai_set_sysclk(cpu_dai,
322 SNDRV_PCM_STREAM_PLAYBACK);
330 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
336 static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream)
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);
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,
350 SNDRV_PCM_STREAM_PLAYBACK);
351 snd_soc_dai_set_sysclk(cpu_dai,
352 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
354 SNDRV_PCM_STREAM_PLAYBACK);
357 case TERTIARY_MI2S_RX:
358 snd_soc_dai_set_sysclk(cpu_dai,
359 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
361 SNDRV_PCM_STREAM_PLAYBACK);
363 case DISPLAY_PORT_RX:
366 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
372 static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd)
374 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
376 switch (cpu_dai->id) {
382 return sc7180_hdmi_init(rtd);
384 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
391 static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream)
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;
398 switch (cpu_dai->id) {
400 snd_soc_dai_set_fmt(codec_dai,
401 SND_SOC_DAIFMT_CBS_CFS |
402 SND_SOC_DAIFMT_NB_NF |
404 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
405 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 32);
413 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
420 static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
421 struct snd_pcm_hw_params *params)
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);
428 rate->min = rate->max = 48000;
429 channels->min = channels->max = 2;
434 static const struct snd_soc_ops sc7180_ops = {
435 .startup = sc7180_snd_startup,
436 .shutdown = sc7180_snd_shutdown,
439 static const struct snd_soc_ops sc7180_qdsp_ops = {
440 .startup = sc7180_qdsp_snd_startup,
441 .shutdown = sc7180_qdsp_snd_shutdown,
444 static const struct snd_soc_ops sc7180_adau7002_ops = {
445 .startup = sc7180_adau7002_snd_startup,
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),
453 static const struct snd_kcontrol_new sc7180_snd_controls[] = {
454 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
455 SOC_DAPM_PIN_SWITCH("Headset Mic"),
458 static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets[] = {
459 SND_SOC_DAPM_MIC("DMIC", NULL),
462 static const char * const dmic_mux_text[] = {
467 static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum,
468 SND_SOC_NOPM, 0, dmic_mux_text);
470 static const struct snd_kcontrol_new sc7180_dmic_mux_control =
471 SOC_DAPM_ENUM_EXT("DMIC Select Mux", sc7180_dmic_enum,
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),
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"),
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"},
491 static int sc7180_snd_platform_probe(struct platform_device *pdev)
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;
499 bool qdsp = false, no_headphone = false;
501 /* Allocate the private data */
502 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
507 snd_soc_card_set_drvdata(card, data);
509 card->owner = THIS_MODULE;
510 card->driver_name = DRIVER_NAME;
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);
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);
531 if (of_device_is_compatible(dev->of_node, "google,sc7180-coachz")) {
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")) {
539 ret = qcom_snd_parse_of(card);
543 for_each_card_prelinks(card, i, link) {
545 link->ops = &sc7180_adau7002_ops;
546 link->init = sc7180_adau7002_init;
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;
554 link->ops = &sc7180_ops;
555 link->init = sc7180_init;
559 return devm_snd_soc_register_card(dev, card);
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"},
568 MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);
570 static struct platform_driver sc7180_snd_driver = {
571 .probe = sc7180_snd_platform_probe,
573 .name = "msm-snd-sc7180",
574 .of_match_table = sc7180_snd_device_id,
575 .pm = &snd_soc_pm_ops,
578 module_platform_driver(sc7180_snd_driver);
580 MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
581 MODULE_LICENSE("GPL v2");