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/consumer.h>
10 #include <linux/module.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>
19 #include "../codecs/rt5682.h"
20 #include "../codecs/rt5682s.h"
22 #include "qdsp6/q6afe.h"
24 #define DEFAULT_MCLK_RATE 19200000
25 #define MI2S_BCLK_RATE 1536000
26 #define RT5682_PLL1_FREQ (48000 * 512)
28 #define DRIVER_NAME "SC7180"
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
;
39 static void sc7180_jack_free(struct snd_jack
*jack
)
41 struct snd_soc_component
*component
= jack
->private_data
;
43 snd_soc_component_set_jack(component
, NULL
, NULL
);
46 static struct snd_soc_jack_pin sc7180_jack_pins
[] = {
48 .pin
= "Headphone Jack",
49 .mask
= SND_JACK_HEADPHONE
,
53 .mask
= SND_JACK_MICROPHONE
,
57 static int sc7180_headset_init(struct snd_soc_pcm_runtime
*rtd
)
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
;
66 rval
= snd_soc_card_jack_new_pins(card
, "Headset Jack",
69 SND_JACK_BTN_0
| SND_JACK_BTN_1
|
70 SND_JACK_BTN_2
| SND_JACK_BTN_3
,
73 ARRAY_SIZE(sc7180_jack_pins
));
76 dev_err(card
->dev
, "Unable to add Headset Jack\n");
80 jack
= pdata
->hs_jack
.jack
;
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
);
87 jack
->private_data
= component
;
88 jack
->private_free
= sc7180_jack_free
;
90 return snd_soc_component_set_jack(component
, &pdata
->hs_jack
, NULL
);
93 static int sc7180_hdmi_init(struct snd_soc_pcm_runtime
*rtd
)
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
;
102 rval
= snd_soc_card_jack_new(
108 dev_err(card
->dev
, "Unable to add HDMI Jack\n");
112 jack
= pdata
->hdmi_jack
.jack
;
113 jack
->private_data
= component
;
114 jack
->private_free
= sc7180_jack_free
;
116 return snd_soc_component_set_jack(component
, &pdata
->hdmi_jack
, NULL
);
119 static int sc7180_init(struct snd_soc_pcm_runtime
*rtd
)
121 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(rtd
, 0);
123 switch (cpu_dai
->id
) {
125 return sc7180_headset_init(rtd
);
129 return sc7180_hdmi_init(rtd
);
131 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
138 static int sc7180_qdsp_init(struct snd_soc_pcm_runtime
*rtd
)
140 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(rtd
, 0);
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
:
148 case DISPLAY_PORT_RX
:
149 return sc7180_hdmi_init(rtd
);
151 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
158 static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime
*rtd
)
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
;
163 if (!strcmp(codec_dai
->name
, "rt5682-aif1")) {
164 pll_source
= RT5682_PLL1_S_MCLK
;
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
;
178 snd_soc_dai_set_fmt(codec_dai
,
179 SND_SOC_DAIFMT_BC_FC
|
180 SND_SOC_DAIFMT_NB_NF
|
183 /* Configure PLL1 for codec */
184 ret
= snd_soc_dai_set_pll(codec_dai
, pll_id
, pll_source
,
187 dev_err(rtd
->dev
, "can't set codec pll: %d\n", ret
);
191 /* Configure sysclk for codec */
192 ret
= snd_soc_dai_set_sysclk(codec_dai
, clk_id
, pll_out
,
195 dev_err(rtd
->dev
, "snd_soc_dai_set_sysclk err = %d\n",
201 static int sc7180_snd_startup(struct snd_pcm_substream
*substream
)
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);
209 switch (cpu_dai
->id
) {
211 if (++data
->pri_mi2s_clk_count
== 1) {
212 snd_soc_dai_set_sysclk(cpu_dai
,
215 SNDRV_PCM_STREAM_PLAYBACK
);
218 ret
= sc7180_startup_realtek_codec(rtd
);
228 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
235 static int sc7180_qdsp_snd_startup(struct snd_pcm_substream
*substream
)
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);
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
,
251 SNDRV_PCM_STREAM_PLAYBACK
);
252 snd_soc_dai_set_sysclk(cpu_dai
,
253 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT
,
255 SNDRV_PCM_STREAM_PLAYBACK
);
258 snd_soc_dai_set_fmt(cpu_dai
, SND_SOC_DAIFMT_BP_FP
);
260 ret
= sc7180_startup_realtek_codec(rtd
);
265 case TERTIARY_MI2S_RX
:
266 snd_soc_dai_set_sysclk(cpu_dai
,
267 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT
,
269 SNDRV_PCM_STREAM_PLAYBACK
);
271 snd_soc_dai_set_fmt(codec_dai
,
272 SND_SOC_DAIFMT_BC_FC
|
273 SND_SOC_DAIFMT_NB_NF
|
275 snd_soc_dai_set_fmt(cpu_dai
, SND_SOC_DAIFMT_BP_FP
);
277 case DISPLAY_PORT_RX
:
280 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
287 static int dmic_get(struct snd_kcontrol
*kcontrol
,
288 struct snd_ctl_elem_value
*ucontrol
)
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
);
293 ucontrol
->value
.integer
.value
[0] = data
->dmic_switch
;
297 static int dmic_set(struct snd_kcontrol
*kcontrol
,
298 struct snd_ctl_elem_value
*ucontrol
)
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
);
303 data
->dmic_switch
= ucontrol
->value
.integer
.value
[0];
304 gpiod_set_value(data
->dmic_sel
, data
->dmic_switch
);
308 static void sc7180_snd_shutdown(struct snd_pcm_substream
*substream
)
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);
315 switch (cpu_dai
->id
) {
317 if (--data
->pri_mi2s_clk_count
== 0) {
318 snd_soc_dai_set_sysclk(cpu_dai
,
321 SNDRV_PCM_STREAM_PLAYBACK
);
329 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
335 static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream
*substream
)
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);
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
,
349 SNDRV_PCM_STREAM_PLAYBACK
);
350 snd_soc_dai_set_sysclk(cpu_dai
,
351 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT
,
353 SNDRV_PCM_STREAM_PLAYBACK
);
356 case TERTIARY_MI2S_RX
:
357 snd_soc_dai_set_sysclk(cpu_dai
,
358 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT
,
360 SNDRV_PCM_STREAM_PLAYBACK
);
362 case DISPLAY_PORT_RX
:
365 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
371 static int sc7180_adau7002_init(struct snd_soc_pcm_runtime
*rtd
)
373 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(rtd
, 0);
375 switch (cpu_dai
->id
) {
381 return sc7180_hdmi_init(rtd
);
383 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
390 static int sc7180_adau7002_snd_startup(struct snd_pcm_substream
*substream
)
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
;
397 switch (cpu_dai
->id
) {
399 snd_soc_dai_set_fmt(codec_dai
,
400 SND_SOC_DAIFMT_CBS_CFS
|
401 SND_SOC_DAIFMT_NB_NF
|
403 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32_LE
;
404 snd_pcm_hw_constraint_msbits(runtime
, 0, 32, 32);
412 dev_err(rtd
->dev
, "%s: invalid dai id 0x%x\n", __func__
,
419 static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime
*rtd
,
420 struct snd_pcm_hw_params
*params
)
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
);
427 rate
->min
= rate
->max
= 48000;
428 channels
->min
= channels
->max
= 2;
433 static const struct snd_soc_ops sc7180_ops
= {
434 .startup
= sc7180_snd_startup
,
435 .shutdown
= sc7180_snd_shutdown
,
438 static const struct snd_soc_ops sc7180_qdsp_ops
= {
439 .startup
= sc7180_qdsp_snd_startup
,
440 .shutdown
= sc7180_qdsp_snd_shutdown
,
443 static const struct snd_soc_ops sc7180_adau7002_ops
= {
444 .startup
= sc7180_adau7002_snd_startup
,
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
),
452 static const struct snd_kcontrol_new sc7180_snd_controls
[] = {
453 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
454 SOC_DAPM_PIN_SWITCH("Headset Mic"),
457 static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets
[] = {
458 SND_SOC_DAPM_MIC("DMIC", NULL
),
461 static const char * const dmic_mux_text
[] = {
466 static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum
,
467 SND_SOC_NOPM
, 0, dmic_mux_text
);
469 static const struct snd_kcontrol_new sc7180_dmic_mux_control
=
470 SOC_DAPM_ENUM_EXT("DMIC Select Mux", sc7180_dmic_enum
,
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
),
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"),
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"},
490 static int sc7180_snd_platform_probe(struct platform_device
*pdev
)
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
;
498 bool qdsp
= false, no_headphone
= false;
500 /* Allocate the private data */
501 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
506 snd_soc_card_set_drvdata(card
, data
);
508 card
->owner
= THIS_MODULE
;
509 card
->driver_name
= DRIVER_NAME
;
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
);
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
);
530 if (of_device_is_compatible(dev
->of_node
, "google,sc7180-coachz")) {
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")) {
538 ret
= qcom_snd_parse_of(card
);
542 for_each_card_prelinks(card
, i
, link
) {
544 link
->ops
= &sc7180_adau7002_ops
;
545 link
->init
= sc7180_adau7002_init
;
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
;
553 link
->ops
= &sc7180_ops
;
554 link
->init
= sc7180_init
;
558 return devm_snd_soc_register_card(dev
, card
);
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"},
567 MODULE_DEVICE_TABLE(of
, sc7180_snd_device_id
);
569 static struct platform_driver sc7180_snd_driver
= {
570 .probe
= sc7180_snd_platform_probe
,
572 .name
= "msm-snd-sc7180",
573 .of_match_table
= sc7180_snd_device_id
,
574 .pm
= &snd_soc_pm_ops
,
577 module_platform_driver(sc7180_snd_driver
);
579 MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
580 MODULE_LICENSE("GPL");