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
30struct 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
39static 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
46static 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
57static 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
93static 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
119static 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
138static 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
158static 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
201static int sc7180_snd_startup(struct snd_pcm_substream *substream)
202{
203	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
235static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream)
236{
237	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
287static 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
297static 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
308static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
309{
310	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
335static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream)
336{
337	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
371static 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
390static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream)
391{
392	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
419static 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
433static const struct snd_soc_ops sc7180_ops = {
434	.startup = sc7180_snd_startup,
435	.shutdown = sc7180_snd_shutdown,
436};
437
438static const struct snd_soc_ops sc7180_qdsp_ops = {
439	.startup = sc7180_qdsp_snd_startup,
440	.shutdown = sc7180_qdsp_snd_shutdown,
441};
442
443static const struct snd_soc_ops sc7180_adau7002_ops = {
444	.startup = sc7180_adau7002_snd_startup,
445};
446
447static 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
452static const struct snd_kcontrol_new sc7180_snd_controls[] = {
453	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
454	SOC_DAPM_PIN_SWITCH("Headset Mic"),
455};
456
457static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets[] = {
458	SND_SOC_DAPM_MIC("DMIC", NULL),
459};
460
461static const char * const dmic_mux_text[] = {
462	"Front Mic",
463	"Rear Mic",
464};
465
466static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum,
467			    SND_SOC_NOPM, 0, dmic_mux_text);
468
469static 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
473static 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
480static 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
485static 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
490static 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
561static 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};
567MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);
568
569static 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};
577module_platform_driver(sc7180_snd_driver);
578
579MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
580MODULE_LICENSE("GPL");
581