1// SPDX-License-Identifier: GPL-2.0+
2//
3// Midas audio support
4//
5// Copyright (C) 2018 Simon Shields <simon@lineageos.org>
6// Copyright (C) 2020 Samsung Electronics Co., Ltd.
7
8#include <linux/clk.h>
9#include <linux/gpio/consumer.h>
10#include <linux/mfd/wm8994/registers.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/regulator/consumer.h>
14#include <sound/jack.h>
15#include <sound/soc.h>
16#include <sound/soc-dapm.h>
17
18#include "i2s.h"
19#include "../codecs/wm8994.h"
20
21/*
22 * The MCLK1 clock source is XCLKOUT with its mux set to the external fixed rate
23 * oscillator (XXTI).
24 */
25#define MCLK1_RATE 24000000U
26#define MCLK2_RATE 32768U
27#define DEFAULT_FLL1_RATE 11289600U
28
29struct midas_priv {
30	struct regulator *reg_mic_bias;
31	struct regulator *reg_submic_bias;
32	struct gpio_desc *gpio_fm_sel;
33	struct gpio_desc *gpio_lineout_sel;
34	unsigned int fll1_rate;
35
36	struct snd_soc_jack headset_jack;
37};
38
39static struct snd_soc_jack_pin headset_jack_pins[] = {
40	{
41		.pin = "Headphone",
42		.mask = SND_JACK_HEADPHONE,
43	},
44	{
45		.pin = "Headset Mic",
46		.mask = SND_JACK_MICROPHONE,
47	},
48};
49
50static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate)
51{
52	struct snd_soc_card *card = rtd->card;
53	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
54	struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
55	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
56	int ret;
57
58	if (!rate)
59		rate = priv->fll1_rate;
60	/*
61	 * If no new rate is requested, set FLL1 to a sane default for jack
62	 * detection.
63	 */
64	if (!rate)
65		rate = DEFAULT_FLL1_RATE;
66
67	if (rate != priv->fll1_rate && priv->fll1_rate) {
68		/* while reconfiguring, switch to MCLK2 for SYSCLK */
69		ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
70					     MCLK2_RATE, SND_SOC_CLOCK_IN);
71		if (ret < 0) {
72			dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
73			return ret;
74		}
75	}
76
77	ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
78				  MCLK1_RATE, rate);
79	if (ret < 0) {
80		dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret);
81		return ret;
82	}
83	priv->fll1_rate = rate;
84
85	ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1,
86				     priv->fll1_rate, SND_SOC_CLOCK_IN);
87	if (ret < 0) {
88		dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret);
89		return ret;
90	}
91
92	ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0,
93				     SAMSUNG_I2S_OPCLK_PCLK);
94	if (ret < 0) {
95		dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret);
96		return ret;
97	}
98
99	return 0;
100}
101
102static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd)
103{
104	struct snd_soc_card *card = rtd->card;
105	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
106	struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
107	int ret;
108
109	ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
110				     MCLK2_RATE, SND_SOC_CLOCK_IN);
111	if (ret < 0) {
112		dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
113		return ret;
114	}
115
116	ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0);
117	if (ret < 0) {
118		dev_err(card->dev, "Unable to stop FLL1: %d\n", ret);
119		return ret;
120	}
121
122	priv->fll1_rate = 0;
123
124	return 0;
125}
126
127static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
128				struct snd_pcm_hw_params *params)
129{
130	struct snd_soc_pcm_runtime *rtd	= substream->private_data;
131	unsigned int pll_out;
132
133	/* AIF1CLK should be at least 3MHz for "optimal performance" */
134	if (params_rate(params) == 8000 || params_rate(params) == 11025)
135		pll_out = params_rate(params) * 512;
136	else
137		pll_out = params_rate(params) * 256;
138
139	return midas_start_fll1(rtd, pll_out);
140}
141
142static const struct snd_soc_ops midas_aif1_ops = {
143	.hw_params = midas_aif1_hw_params,
144};
145
146/*
147 * We only have a single external speaker, so mix stereo data
148 * to a single mono stream.
149 */
150static int midas_ext_spkmode(struct snd_soc_dapm_widget *w,
151			     struct snd_kcontrol *kcontrol, int event)
152{
153	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
154	int ret = 0;
155
156	switch (event) {
157	case SND_SOC_DAPM_PRE_PMU:
158		ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
159				  WM8994_SPKMIXR_TO_SPKOUTL_MASK,
160				  WM8994_SPKMIXR_TO_SPKOUTL);
161		break;
162	case SND_SOC_DAPM_POST_PMD:
163		ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
164				  WM8994_SPKMIXR_TO_SPKOUTL_MASK,
165				  0);
166		break;
167	}
168
169	return ret;
170}
171
172static int midas_mic_bias(struct snd_soc_dapm_widget *w,
173			  struct snd_kcontrol *kcontrol, int event)
174{
175	struct snd_soc_card *card = w->dapm->card;
176	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
177
178	switch (event) {
179	case SND_SOC_DAPM_PRE_PMU:
180		return regulator_enable(priv->reg_mic_bias);
181	case SND_SOC_DAPM_POST_PMD:
182		return regulator_disable(priv->reg_mic_bias);
183	}
184
185	return 0;
186}
187
188static int midas_submic_bias(struct snd_soc_dapm_widget *w,
189			     struct snd_kcontrol *kcontrol, int event)
190{
191	struct snd_soc_card *card = w->dapm->card;
192	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
193
194	switch (event) {
195	case SND_SOC_DAPM_PRE_PMU:
196		return regulator_enable(priv->reg_submic_bias);
197	case SND_SOC_DAPM_POST_PMD:
198		return regulator_disable(priv->reg_submic_bias);
199	}
200
201	return 0;
202}
203
204static int midas_fm_set(struct snd_soc_dapm_widget *w,
205			struct snd_kcontrol *kcontrol, int event)
206{
207	struct snd_soc_card *card = w->dapm->card;
208	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
209
210	if (!priv->gpio_fm_sel)
211		return 0;
212
213	switch (event) {
214	case SND_SOC_DAPM_PRE_PMU:
215		gpiod_set_value_cansleep(priv->gpio_fm_sel, 1);
216		break;
217	case SND_SOC_DAPM_POST_PMD:
218		gpiod_set_value_cansleep(priv->gpio_fm_sel, 0);
219		break;
220	}
221
222	return 0;
223}
224
225static int midas_line_set(struct snd_soc_dapm_widget *w,
226			  struct snd_kcontrol *kcontrol, int event)
227{
228	struct snd_soc_card *card = w->dapm->card;
229	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
230
231	if (!priv->gpio_lineout_sel)
232		return 0;
233
234	switch (event) {
235	case SND_SOC_DAPM_PRE_PMU:
236		gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1);
237		break;
238	case SND_SOC_DAPM_POST_PMD:
239		gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0);
240		break;
241	}
242
243	return 0;
244}
245
246static const struct snd_kcontrol_new midas_controls[] = {
247	SOC_DAPM_PIN_SWITCH("HP"),
248
249	SOC_DAPM_PIN_SWITCH("SPK"),
250	SOC_DAPM_PIN_SWITCH("RCV"),
251
252	SOC_DAPM_PIN_SWITCH("LINE"),
253	SOC_DAPM_PIN_SWITCH("HDMI"),
254
255	SOC_DAPM_PIN_SWITCH("Main Mic"),
256	SOC_DAPM_PIN_SWITCH("Sub Mic"),
257	SOC_DAPM_PIN_SWITCH("Headset Mic"),
258
259	SOC_DAPM_PIN_SWITCH("FM In"),
260};
261
262static const struct snd_soc_dapm_widget midas_dapm_widgets[] = {
263	SND_SOC_DAPM_HP("HP", NULL),
264
265	SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode),
266	SND_SOC_DAPM_SPK("RCV", NULL),
267
268	/* FIXME: toggle MAX77693 on i9300/i9305 */
269	SND_SOC_DAPM_LINE("LINE", midas_line_set),
270	SND_SOC_DAPM_LINE("HDMI", NULL),
271	SND_SOC_DAPM_LINE("FM In", midas_fm_set),
272
273	SND_SOC_DAPM_HP("Headphone", NULL),
274	SND_SOC_DAPM_MIC("Headset Mic", NULL),
275	SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias),
276	SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias),
277};
278
279static int midas_set_bias_level(struct snd_soc_card *card,
280				struct snd_soc_dapm_context *dapm,
281				enum snd_soc_bias_level level)
282{
283	struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
284						  &card->dai_link[0]);
285	struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
286
287	if (dapm->dev != aif1_dai->dev)
288		return 0;
289
290	switch (level) {
291	case SND_SOC_BIAS_STANDBY:
292		return midas_stop_fll1(rtd);
293	case SND_SOC_BIAS_PREPARE:
294		return midas_start_fll1(rtd, 0);
295	default:
296		break;
297	}
298
299	return 0;
300}
301
302static int midas_late_probe(struct snd_soc_card *card)
303{
304	struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
305							&card->dai_link[0]);
306	struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
307	struct midas_priv *priv = snd_soc_card_get_drvdata(card);
308	int ret;
309
310	/* Use MCLK2 as SYSCLK for boot */
311	ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE,
312				     SND_SOC_CLOCK_IN);
313	if (ret < 0) {
314		dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret);
315		return ret;
316	}
317
318	ret = snd_soc_card_jack_new_pins(card, "Headset",
319					 SND_JACK_HEADSET | SND_JACK_MECHANICAL |
320					 SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 |
321					 SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5,
322					 &priv->headset_jack,
323					 headset_jack_pins,
324					 ARRAY_SIZE(headset_jack_pins));
325	if (ret)
326		return ret;
327
328	wm8958_mic_detect(aif1_dai->component, &priv->headset_jack,
329			  NULL, NULL, NULL, NULL);
330	return 0;
331}
332
333static struct snd_soc_dai_driver midas_ext_dai[] = {
334	{
335		.name = "Voice call",
336		.playback = {
337			.channels_min = 1,
338			.channels_max = 2,
339			.rate_min = 8000,
340			.rate_max = 16000,
341			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
342			.formats = SNDRV_PCM_FMTBIT_S16_LE,
343		},
344		.capture = {
345			.channels_min = 1,
346			.channels_max = 2,
347			.rate_min = 8000,
348			.rate_max = 16000,
349			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
350			.formats = SNDRV_PCM_FMTBIT_S16_LE,
351		},
352	},
353	{
354		.name = "Bluetooth",
355		.playback = {
356			.channels_min = 1,
357			.channels_max = 2,
358			.rate_min = 8000,
359			.rate_max = 16000,
360			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
361			.formats = SNDRV_PCM_FMTBIT_S16_LE,
362		},
363		.capture = {
364			.channels_min = 1,
365			.channels_max = 2,
366			.rate_min = 8000,
367			.rate_max = 16000,
368			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
369			.formats = SNDRV_PCM_FMTBIT_S16_LE,
370		},
371	},
372};
373
374static const struct snd_soc_component_driver midas_component = {
375	.name	= "midas-audio",
376};
377
378SND_SOC_DAILINK_DEFS(wm1811_hifi,
379	DAILINK_COMP_ARRAY(COMP_EMPTY()),
380	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
381	DAILINK_COMP_ARRAY(COMP_EMPTY()));
382
383SND_SOC_DAILINK_DEFS(wm1811_voice,
384	DAILINK_COMP_ARRAY(COMP_EMPTY()),
385	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")),
386	DAILINK_COMP_ARRAY(COMP_EMPTY()));
387
388SND_SOC_DAILINK_DEFS(wm1811_bt,
389	DAILINK_COMP_ARRAY(COMP_EMPTY()),
390	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")),
391	DAILINK_COMP_ARRAY(COMP_EMPTY()));
392
393static struct snd_soc_dai_link midas_dai[] = {
394	{
395		.name = "WM8994 AIF1",
396		.stream_name = "HiFi Primary",
397		.ops = &midas_aif1_ops,
398		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
399			SND_SOC_DAIFMT_CBM_CFM,
400		SND_SOC_DAILINK_REG(wm1811_hifi),
401	}, {
402		.name = "WM1811 Voice",
403		.stream_name = "Voice call",
404		.ignore_suspend = 1,
405		SND_SOC_DAILINK_REG(wm1811_voice),
406	}, {
407		.name = "WM1811 BT",
408		.stream_name = "Bluetooth",
409		.ignore_suspend = 1,
410		SND_SOC_DAILINK_REG(wm1811_bt),
411	},
412};
413
414static struct snd_soc_card midas_card = {
415	.name = "Midas WM1811",
416	.owner = THIS_MODULE,
417
418	.dai_link = midas_dai,
419	.num_links = ARRAY_SIZE(midas_dai),
420	.controls = midas_controls,
421	.num_controls = ARRAY_SIZE(midas_controls),
422	.dapm_widgets = midas_dapm_widgets,
423	.num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets),
424
425	.set_bias_level = midas_set_bias_level,
426	.late_probe = midas_late_probe,
427};
428
429static int midas_probe(struct platform_device *pdev)
430{
431	struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL;
432	struct device_node *cpu = NULL, *codec = NULL;
433	struct snd_soc_card *card = &midas_card;
434	struct device *dev = &pdev->dev;
435	static struct snd_soc_dai_link *dai_link;
436	struct midas_priv *priv;
437	int ret, i;
438
439	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
440	if (!priv)
441		return -ENOMEM;
442
443	snd_soc_card_set_drvdata(card, priv);
444	card->dev = dev;
445
446	priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias");
447	if (IS_ERR(priv->reg_mic_bias)) {
448		dev_err(dev, "Failed to get mic bias regulator\n");
449		return PTR_ERR(priv->reg_mic_bias);
450	}
451
452	priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias");
453	if (IS_ERR(priv->reg_submic_bias)) {
454		dev_err(dev, "Failed to get submic bias regulator\n");
455		return PTR_ERR(priv->reg_submic_bias);
456	}
457
458	priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH);
459	if (IS_ERR(priv->gpio_fm_sel)) {
460		dev_err(dev, "Failed to get FM selection GPIO\n");
461		return PTR_ERR(priv->gpio_fm_sel);
462	}
463
464	priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel",
465						    GPIOD_OUT_HIGH);
466	if (IS_ERR(priv->gpio_lineout_sel)) {
467		dev_err(dev, "Failed to get line out selection GPIO\n");
468		return PTR_ERR(priv->gpio_lineout_sel);
469	}
470
471	ret = snd_soc_of_parse_card_name(card, "model");
472	if (ret < 0) {
473		dev_err(dev, "Card name is not specified\n");
474		return ret;
475	}
476
477	ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
478	if (ret < 0) {
479		/* Backwards compatible way */
480		ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
481		if (ret < 0) {
482			dev_err(dev, "Audio routing invalid/unspecified\n");
483			return ret;
484		}
485	}
486
487	cpu = of_get_child_by_name(dev->of_node, "cpu");
488	if (!cpu)
489		return -EINVAL;
490
491	codec = of_get_child_by_name(dev->of_node, "codec");
492	if (!codec) {
493		of_node_put(cpu);
494		return -EINVAL;
495	}
496
497	cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0);
498	of_node_put(cpu);
499	if (!cpu_dai_node) {
500		dev_err(dev, "parsing cpu/sound-dai failed\n");
501		of_node_put(codec);
502		return -EINVAL;
503	}
504
505	codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
506	of_node_put(codec);
507	if (!codec_dai_node) {
508		dev_err(dev, "audio-codec property invalid/missing\n");
509		ret = -EINVAL;
510		goto put_cpu_dai_node;
511	}
512
513	for_each_card_prelinks(card, i, dai_link) {
514		dai_link->codecs->of_node = codec_dai_node;
515		dai_link->cpus->of_node = cpu_dai_node;
516		dai_link->platforms->of_node = cpu_dai_node;
517	}
518
519	ret = devm_snd_soc_register_component(dev, &midas_component,
520			midas_ext_dai, ARRAY_SIZE(midas_ext_dai));
521	if (ret < 0) {
522		dev_err(dev, "Failed to register component: %d\n", ret);
523		goto put_codec_dai_node;
524	}
525
526	ret = devm_snd_soc_register_card(dev, card);
527	if (ret < 0) {
528		dev_err(dev, "Failed to register card: %d\n", ret);
529		goto put_codec_dai_node;
530	}
531
532	return 0;
533
534put_codec_dai_node:
535	of_node_put(codec_dai_node);
536put_cpu_dai_node:
537	of_node_put(cpu_dai_node);
538	return ret;
539}
540
541static const struct of_device_id midas_of_match[] = {
542	{ .compatible = "samsung,midas-audio" },
543	{ },
544};
545MODULE_DEVICE_TABLE(of, midas_of_match);
546
547static struct platform_driver midas_driver = {
548	.driver = {
549		.name = "midas-audio",
550		.of_match_table = midas_of_match,
551		.pm = &snd_soc_pm_ops,
552	},
553	.probe = midas_probe,
554};
555module_platform_driver(midas_driver);
556
557MODULE_AUTHOR("Simon Shields <simon@lineageos.org>");
558MODULE_DESCRIPTION("ASoC support for Midas");
559MODULE_LICENSE("GPL v2");
560