710e2151141f683ffc4ef3fde3834f7e05e66249
[muen/linux.git] / sound / soc / samsung / tm2_wm5110.c
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",
443                                                 GPIOF_OUT_INIT_LOW);
444         if (IS_ERR(priv->gpio_mic_bias)) {
445                 dev_err(dev, "Failed to get mic bias gpio\n");
446                 return PTR_ERR(priv->gpio_mic_bias);
447         }
448
449         ret = snd_soc_of_parse_card_name(card, "model");
450         if (ret < 0) {
451                 dev_err(dev, "Card name is not specified\n");
452                 return ret;
453         }
454
455         ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
456         if (ret < 0) {
457                 dev_err(dev, "Audio routing is not specified or invalid\n");
458                 return ret;
459         }
460
461         card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node,
462                                                         "audio-amplifier", 0);
463         if (!card->aux_dev[0].codec_of_node) {
464                 dev_err(dev, "audio-amplifier property invalid or missing\n");
465                 return -EINVAL;
466         }
467
468         cpu_dai_node = of_parse_phandle(dev->of_node, "i2s-controller", 0);
469         if (!cpu_dai_node) {
470                 dev_err(dev, "i2s-controllers property invalid or missing\n");
471                 ret = -EINVAL;
472                 goto amp_node_put;
473         }
474
475         codec_dai_node = of_parse_phandle(dev->of_node, "audio-codec", 0);
476         if (!codec_dai_node) {
477                 dev_err(dev, "audio-codec property invalid or missing\n");
478                 ret = -EINVAL;
479                 goto cpu_dai_node_put;
480         }
481
482         for (i = 0; i < card->num_links; i++) {
483                 card->dai_link[i].cpu_name = NULL;
484                 card->dai_link[i].platform_name = NULL;
485                 card->dai_link[i].codec_of_node = codec_dai_node;
486                 card->dai_link[i].cpu_of_node = cpu_dai_node;
487                 card->dai_link[i].platform_of_node = cpu_dai_node;
488         }
489
490         ret = devm_snd_soc_register_component(dev, &tm2_component,
491                                 tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai));
492         if (ret < 0) {
493                 dev_err(dev, "Failed to register component: %d\n", ret);
494                 goto codec_dai_node_put;
495         }
496
497         ret = devm_snd_soc_register_card(dev, card);
498         if (ret < 0) {
499                 dev_err(dev, "Failed to register card: %d\n", ret);
500                 goto codec_dai_node_put;
501         }
502
503 codec_dai_node_put:
504         of_node_put(codec_dai_node);
505 cpu_dai_node_put:
506         of_node_put(cpu_dai_node);
507 amp_node_put:
508         of_node_put(card->aux_dev[0].codec_of_node);
509         return ret;
510 }
511
512 static int tm2_pm_prepare(struct device *dev)
513 {
514         struct snd_soc_card *card = dev_get_drvdata(dev);
515
516         return tm2_stop_sysclk(card);
517 }
518
519 static void tm2_pm_complete(struct device *dev)
520 {
521         struct snd_soc_card *card = dev_get_drvdata(dev);
522
523         tm2_start_sysclk(card);
524 }
525
526 static const struct dev_pm_ops tm2_pm_ops = {
527         .prepare        = tm2_pm_prepare,
528         .suspend        = snd_soc_suspend,
529         .resume         = snd_soc_resume,
530         .complete       = tm2_pm_complete,
531         .freeze         = snd_soc_suspend,
532         .thaw           = snd_soc_resume,
533         .poweroff       = snd_soc_poweroff,
534         .restore        = snd_soc_resume,
535 };
536
537 static const struct of_device_id tm2_of_match[] = {
538         { .compatible = "samsung,tm2-audio" },
539         { },
540 };
541 MODULE_DEVICE_TABLE(of, tm2_of_match);
542
543 static struct platform_driver tm2_driver = {
544         .driver = {
545                 .name           = "tm2-audio",
546                 .pm             = &tm2_pm_ops,
547                 .of_match_table = tm2_of_match,
548         },
549         .probe  = tm2_probe,
550 };
551 module_platform_driver(tm2_driver);
552
553 MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>");
554 MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support");
555 MODULE_LICENSE("GPL v2");