xref: /openbmc/linux/sound/soc/samsung/tm2_wm5110.c (revision 60772e48)
1 /*
2  * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd.
3  *
4  * Authors: Inha Song <ideal.song@samsung.com>
5  *          Sylwester Nawrocki <s.nawrocki@samsung.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12 
13 #include <linux/clk.h>
14 #include <linux/gpio.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 
21 #include "i2s.h"
22 #include "../codecs/wm5110.h"
23 
24 /*
25  * The source clock is XCLKOUT with its mux set to the external fixed rate
26  * oscillator (XXTI).
27  */
28 #define MCLK_RATE	24000000U
29 
30 #define TM2_DAI_AIF1	0
31 #define TM2_DAI_AIF2	1
32 
33 struct tm2_machine_priv {
34 	struct snd_soc_codec *codec;
35 	unsigned int sysclk_rate;
36 	struct gpio_desc *gpio_mic_bias;
37 };
38 
39 static int tm2_start_sysclk(struct snd_soc_card *card)
40 {
41 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
42 	struct snd_soc_codec *codec = priv->codec;
43 	int ret;
44 
45 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL1_REFCLK,
46 				    ARIZONA_FLL_SRC_MCLK1,
47 				    MCLK_RATE,
48 				    priv->sysclk_rate);
49 	if (ret < 0) {
50 		dev_err(codec->dev, "Failed to set FLL1 source: %d\n", ret);
51 		return ret;
52 	}
53 
54 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL1,
55 				    ARIZONA_FLL_SRC_MCLK1,
56 				    MCLK_RATE,
57 				    priv->sysclk_rate);
58 	if (ret < 0) {
59 		dev_err(codec->dev, "Failed to start FLL1: %d\n", ret);
60 		return ret;
61 	}
62 
63 	ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
64 				       ARIZONA_CLK_SRC_FLL1,
65 				       priv->sysclk_rate,
66 				       SND_SOC_CLOCK_IN);
67 	if (ret < 0) {
68 		dev_err(codec->dev, "Failed to set SYSCLK source: %d\n", ret);
69 		return ret;
70 	}
71 
72 	return 0;
73 }
74 
75 static int tm2_stop_sysclk(struct snd_soc_card *card)
76 {
77 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
78 	struct snd_soc_codec *codec = priv->codec;
79 	int ret;
80 
81 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL1, 0, 0, 0);
82 	if (ret < 0) {
83 		dev_err(codec->dev, "Failed to stop FLL1: %d\n", ret);
84 		return ret;
85 	}
86 
87 	ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
88 				       ARIZONA_CLK_SRC_FLL1, 0, 0);
89 	if (ret < 0) {
90 		dev_err(codec->dev, "Failed to stop SYSCLK: %d\n", ret);
91 		return ret;
92 	}
93 
94 	return 0;
95 }
96 
97 static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
98 				struct snd_pcm_hw_params *params)
99 {
100 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
101 	struct snd_soc_codec *codec = rtd->codec;
102 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card);
103 
104 	switch (params_rate(params)) {
105 	case 4000:
106 	case 8000:
107 	case 12000:
108 	case 16000:
109 	case 24000:
110 	case 32000:
111 	case 48000:
112 	case 96000:
113 	case 192000:
114 		/* Highest possible SYSCLK frequency: 147.456MHz */
115 		priv->sysclk_rate = 147456000U;
116 		break;
117 	case 11025:
118 	case 22050:
119 	case 44100:
120 	case 88200:
121 	case 176400:
122 		/* Highest possible SYSCLK frequency: 135.4752 MHz */
123 		priv->sysclk_rate = 135475200U;
124 		break;
125 	default:
126 		dev_err(codec->dev, "Not supported sample rate: %d\n",
127 			params_rate(params));
128 		return -EINVAL;
129 	}
130 
131 	return tm2_start_sysclk(rtd->card);
132 }
133 
134 static struct snd_soc_ops tm2_aif1_ops = {
135 	.hw_params = tm2_aif1_hw_params,
136 };
137 
138 static int tm2_aif2_hw_params(struct snd_pcm_substream *substream,
139 				struct snd_pcm_hw_params *params)
140 {
141 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 	struct snd_soc_codec *codec = rtd->codec;
143 	unsigned int asyncclk_rate;
144 	int ret;
145 
146 	switch (params_rate(params)) {
147 	case 8000:
148 	case 12000:
149 	case 16000:
150 		/* Highest possible ASYNCCLK frequency: 49.152MHz */
151 		asyncclk_rate = 49152000U;
152 		break;
153 	case 11025:
154 		/* Highest possible ASYNCCLK frequency: 45.1584 MHz */
155 		asyncclk_rate = 45158400U;
156 		break;
157 	default:
158 		dev_err(codec->dev, "Not supported sample rate: %d\n",
159 			params_rate(params));
160 		return -EINVAL;
161 	}
162 
163 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL2_REFCLK,
164 				    ARIZONA_FLL_SRC_MCLK1,
165 				    MCLK_RATE,
166 				    asyncclk_rate);
167 	if (ret < 0) {
168 		dev_err(codec->dev, "Failed to set FLL2 source: %d\n", ret);
169 		return ret;
170 	}
171 
172 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL2,
173 				    ARIZONA_FLL_SRC_MCLK1,
174 				    MCLK_RATE,
175 				    asyncclk_rate);
176 	if (ret < 0) {
177 		dev_err(codec->dev, "Failed to start FLL2: %d\n", ret);
178 		return ret;
179 	}
180 
181 	ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
182 				       ARIZONA_CLK_SRC_FLL2,
183 				       asyncclk_rate,
184 				       SND_SOC_CLOCK_IN);
185 	if (ret < 0) {
186 		dev_err(codec->dev, "Failed to set ASYNCCLK source: %d\n", ret);
187 		return ret;
188 	}
189 
190 	return 0;
191 }
192 
193 static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
194 {
195 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
196 	struct snd_soc_codec *codec = rtd->codec;
197 	int ret;
198 
199 	/* disable FLL2 */
200 	ret = snd_soc_codec_set_pll(codec, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1,
201 				    0, 0);
202 	if (ret < 0)
203 		dev_err(codec->dev, "Failed to stop FLL2: %d\n", ret);
204 
205 	return ret;
206 }
207 
208 static struct snd_soc_ops tm2_aif2_ops = {
209 	.hw_params = tm2_aif2_hw_params,
210 	.hw_free = tm2_aif2_hw_free,
211 };
212 
213 static int tm2_mic_bias(struct snd_soc_dapm_widget *w,
214 				struct snd_kcontrol *kcontrol, int event)
215 {
216 	struct snd_soc_card *card = w->dapm->card;
217 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
218 
219 	switch (event) {
220 	case SND_SOC_DAPM_PRE_PMU:
221 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  1);
222 		break;
223 	case SND_SOC_DAPM_POST_PMD:
224 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  0);
225 		break;
226 	}
227 
228 	return 0;
229 }
230 
231 static int tm2_set_bias_level(struct snd_soc_card *card,
232 				struct snd_soc_dapm_context *dapm,
233 				enum snd_soc_bias_level level)
234 {
235 	struct snd_soc_pcm_runtime *rtd;
236 
237 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
238 
239 	if (dapm->dev != rtd->codec_dai->dev)
240 		return 0;
241 
242 	switch (level) {
243 	case SND_SOC_BIAS_STANDBY:
244 		if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
245 			tm2_start_sysclk(card);
246 		break;
247 	case SND_SOC_BIAS_OFF:
248 		tm2_stop_sysclk(card);
249 		break;
250 	default:
251 		break;
252 	}
253 
254 	return 0;
255 }
256 
257 static struct snd_soc_aux_dev tm2_speaker_amp_dev;
258 
259 static int tm2_late_probe(struct snd_soc_card *card)
260 {
261 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
262 	struct snd_soc_dai_link_component dlc = { 0 };
263 	unsigned int ch_map[] = { 0, 1 };
264 	struct snd_soc_dai *amp_pdm_dai;
265 	struct snd_soc_pcm_runtime *rtd;
266 	struct snd_soc_dai *aif1_dai;
267 	struct snd_soc_dai *aif2_dai;
268 	int ret;
269 
270 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF1].name);
271 	aif1_dai = rtd->codec_dai;
272 	priv->codec = rtd->codec;
273 
274 	ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
275 	if (ret < 0) {
276 		dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret);
277 		return ret;
278 	}
279 
280 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF2].name);
281 	aif2_dai = rtd->codec_dai;
282 
283 	ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
284 	if (ret < 0) {
285 		dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret);
286 		return ret;
287 	}
288 
289 	dlc.of_node = tm2_speaker_amp_dev.codec_of_node;
290 	amp_pdm_dai = snd_soc_find_dai(&dlc);
291 	if (!amp_pdm_dai)
292 		return -ENODEV;
293 
294 	/* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */
295 	ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map),
296 					  ch_map, 0, NULL);
297 	if (ret < 0)
298 		return ret;
299 
300 	ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16);
301 	if (ret < 0)
302 		return ret;
303 
304 	return 0;
305 }
306 
307 static const struct snd_kcontrol_new tm2_controls[] = {
308 	SOC_DAPM_PIN_SWITCH("HP"),
309 	SOC_DAPM_PIN_SWITCH("SPK"),
310 	SOC_DAPM_PIN_SWITCH("RCV"),
311 	SOC_DAPM_PIN_SWITCH("VPS"),
312 	SOC_DAPM_PIN_SWITCH("HDMI"),
313 
314 	SOC_DAPM_PIN_SWITCH("Main Mic"),
315 	SOC_DAPM_PIN_SWITCH("Sub Mic"),
316 	SOC_DAPM_PIN_SWITCH("Third Mic"),
317 
318 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
319 };
320 
321 static const struct snd_soc_dapm_widget tm2_dapm_widgets[] = {
322 	SND_SOC_DAPM_HP("HP", NULL),
323 	SND_SOC_DAPM_SPK("SPK", NULL),
324 	SND_SOC_DAPM_SPK("RCV", NULL),
325 	SND_SOC_DAPM_LINE("VPS", NULL),
326 	SND_SOC_DAPM_LINE("HDMI", NULL),
327 
328 	SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias),
329 	SND_SOC_DAPM_MIC("Sub Mic", NULL),
330 	SND_SOC_DAPM_MIC("Third Mic", NULL),
331 
332 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
333 };
334 
335 static const struct snd_soc_component_driver tm2_component = {
336 	.name	= "tm2-audio",
337 };
338 
339 static struct snd_soc_dai_driver tm2_ext_dai[] = {
340 	{
341 		.name = "Voice call",
342 		.playback = {
343 			.channels_min = 1,
344 			.channels_max = 4,
345 			.rate_min = 8000,
346 			.rate_max = 48000,
347 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
348 					SNDRV_PCM_RATE_48000),
349 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
350 		},
351 		.capture = {
352 			.channels_min = 1,
353 			.channels_max = 4,
354 			.rate_min = 8000,
355 			.rate_max = 48000,
356 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
357 					SNDRV_PCM_RATE_48000),
358 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
359 		},
360 	},
361 	{
362 		.name = "Bluetooth",
363 		.playback = {
364 			.channels_min = 1,
365 			.channels_max = 4,
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 		.capture = {
372 			.channels_min = 1,
373 			.channels_max = 2,
374 			.rate_min = 8000,
375 			.rate_max = 16000,
376 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
377 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
378 		},
379 	},
380 };
381 
382 static struct snd_soc_dai_link tm2_dai_links[] = {
383 	{
384 		.name		= "WM5110 AIF1",
385 		.stream_name	= "HiFi Primary",
386 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
387 		.codec_dai_name = "wm5110-aif1",
388 		.ops		= &tm2_aif1_ops,
389 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
390 				  SND_SOC_DAIFMT_CBM_CFM,
391 	}, {
392 		.name		= "WM5110 Voice",
393 		.stream_name	= "Voice call",
394 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
395 		.codec_dai_name = "wm5110-aif2",
396 		.ops		= &tm2_aif2_ops,
397 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
398 				  SND_SOC_DAIFMT_CBM_CFM,
399 		.ignore_suspend = 1,
400 	}, {
401 		.name		= "WM5110 BT",
402 		.stream_name	= "Bluetooth",
403 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
404 		.codec_dai_name = "wm5110-aif3",
405 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
406 				  SND_SOC_DAIFMT_CBM_CFM,
407 		.ignore_suspend = 1,
408 	}
409 };
410 
411 static struct snd_soc_card tm2_card = {
412 	.owner			= THIS_MODULE,
413 
414 	.dai_link		= tm2_dai_links,
415 	.num_links		= ARRAY_SIZE(tm2_dai_links),
416 	.controls		= tm2_controls,
417 	.num_controls		= ARRAY_SIZE(tm2_controls),
418 	.dapm_widgets		= tm2_dapm_widgets,
419 	.num_dapm_widgets	= ARRAY_SIZE(tm2_dapm_widgets),
420 	.aux_dev		= &tm2_speaker_amp_dev,
421 	.num_aux_devs		= 1,
422 
423 	.late_probe		= tm2_late_probe,
424 	.set_bias_level		= tm2_set_bias_level,
425 };
426 
427 static int tm2_probe(struct platform_device *pdev)
428 {
429 	struct device *dev = &pdev->dev;
430 	struct snd_soc_card *card = &tm2_card;
431 	struct tm2_machine_priv *priv;
432 	struct device_node *cpu_dai_node, *codec_dai_node;
433 	int ret, i;
434 
435 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
436 	if (!priv)
437 		return -ENOMEM;
438 
439 	snd_soc_card_set_drvdata(card, priv);
440 	card->dev = dev;
441 
442 	priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", GPIOD_OUT_HIGH);
443 	if (IS_ERR(priv->gpio_mic_bias)) {
444 		dev_err(dev, "Failed to get mic bias gpio\n");
445 		return PTR_ERR(priv->gpio_mic_bias);
446 	}
447 
448 	ret = snd_soc_of_parse_card_name(card, "model");
449 	if (ret < 0) {
450 		dev_err(dev, "Card name is not specified\n");
451 		return ret;
452 	}
453 
454 	ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
455 	if (ret < 0) {
456 		dev_err(dev, "Audio routing is not specified or invalid\n");
457 		return ret;
458 	}
459 
460 	card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node,
461 							"audio-amplifier", 0);
462 	if (!card->aux_dev[0].codec_of_node) {
463 		dev_err(dev, "audio-amplifier property invalid or missing\n");
464 		return -EINVAL;
465 	}
466 
467 	cpu_dai_node = of_parse_phandle(dev->of_node, "i2s-controller", 0);
468 	if (!cpu_dai_node) {
469 		dev_err(dev, "i2s-controllers property invalid or missing\n");
470 		ret = -EINVAL;
471 		goto amp_node_put;
472 	}
473 
474 	codec_dai_node = of_parse_phandle(dev->of_node, "audio-codec", 0);
475 	if (!codec_dai_node) {
476 		dev_err(dev, "audio-codec property invalid or missing\n");
477 		ret = -EINVAL;
478 		goto cpu_dai_node_put;
479 	}
480 
481 	for (i = 0; i < card->num_links; i++) {
482 		card->dai_link[i].cpu_name = NULL;
483 		card->dai_link[i].platform_name = NULL;
484 		card->dai_link[i].codec_of_node = codec_dai_node;
485 		card->dai_link[i].cpu_of_node = cpu_dai_node;
486 		card->dai_link[i].platform_of_node = cpu_dai_node;
487 	}
488 
489 	ret = devm_snd_soc_register_component(dev, &tm2_component,
490 				tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai));
491 	if (ret < 0) {
492 		dev_err(dev, "Failed to register component: %d\n", ret);
493 		goto codec_dai_node_put;
494 	}
495 
496 	ret = devm_snd_soc_register_card(dev, card);
497 	if (ret < 0) {
498 		dev_err(dev, "Failed to register card: %d\n", ret);
499 		goto codec_dai_node_put;
500 	}
501 
502 codec_dai_node_put:
503 	of_node_put(codec_dai_node);
504 cpu_dai_node_put:
505 	of_node_put(cpu_dai_node);
506 amp_node_put:
507 	of_node_put(card->aux_dev[0].codec_of_node);
508 	return ret;
509 }
510 
511 static int tm2_pm_prepare(struct device *dev)
512 {
513 	struct snd_soc_card *card = dev_get_drvdata(dev);
514 
515 	return tm2_stop_sysclk(card);
516 }
517 
518 static void tm2_pm_complete(struct device *dev)
519 {
520 	struct snd_soc_card *card = dev_get_drvdata(dev);
521 
522 	tm2_start_sysclk(card);
523 }
524 
525 static const struct dev_pm_ops tm2_pm_ops = {
526 	.prepare	= tm2_pm_prepare,
527 	.suspend	= snd_soc_suspend,
528 	.resume		= snd_soc_resume,
529 	.complete	= tm2_pm_complete,
530 	.freeze		= snd_soc_suspend,
531 	.thaw		= snd_soc_resume,
532 	.poweroff	= snd_soc_poweroff,
533 	.restore	= snd_soc_resume,
534 };
535 
536 static const struct of_device_id tm2_of_match[] = {
537 	{ .compatible = "samsung,tm2-audio" },
538 	{ },
539 };
540 MODULE_DEVICE_TABLE(of, tm2_of_match);
541 
542 static struct platform_driver tm2_driver = {
543 	.driver = {
544 		.name		= "tm2-audio",
545 		.pm		= &tm2_pm_ops,
546 		.of_match_table	= tm2_of_match,
547 	},
548 	.probe	= tm2_probe,
549 };
550 module_platform_driver(tm2_driver);
551 
552 MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>");
553 MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support");
554 MODULE_LICENSE("GPL v2");
555