OSDN Git Service

treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 201
[uclinux-h8/linux.git] / sound / soc / rockchip / rk3399_gru_sound.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
4  *
5  * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
6  */
7
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/slab.h>
11 #include <linux/gpio.h>
12 #include <linux/of_gpio.h>
13 #include <linux/delay.h>
14 #include <linux/spi/spi.h>
15 #include <linux/i2c.h>
16 #include <linux/input.h>
17 #include <sound/core.h>
18 #include <sound/jack.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include "rockchip_i2s.h"
23 #include "../codecs/da7219.h"
24 #include "../codecs/da7219-aad.h"
25 #include "../codecs/rt5514.h"
26
27 #define DRV_NAME "rk3399-gru-sound"
28
29 #define SOUND_FS        256
30
31 static unsigned int dmic_wakeup_delay;
32
33 static struct snd_soc_jack rockchip_sound_jack;
34
35 static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
36         SND_SOC_DAPM_HP("Headphones", NULL),
37         SND_SOC_DAPM_SPK("Speakers", NULL),
38         SND_SOC_DAPM_MIC("Headset Mic", NULL),
39         SND_SOC_DAPM_MIC("Int Mic", NULL),
40         SND_SOC_DAPM_LINE("HDMI", NULL),
41 };
42
43 static const struct snd_kcontrol_new rockchip_controls[] = {
44         SOC_DAPM_PIN_SWITCH("Headphones"),
45         SOC_DAPM_PIN_SWITCH("Speakers"),
46         SOC_DAPM_PIN_SWITCH("Headset Mic"),
47         SOC_DAPM_PIN_SWITCH("Int Mic"),
48         SOC_DAPM_PIN_SWITCH("HDMI"),
49 };
50
51 static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
52                              struct snd_pcm_hw_params *params)
53 {
54         struct snd_soc_pcm_runtime *rtd = substream->private_data;
55         unsigned int mclk;
56         int ret;
57
58         /* max98357a supports these sample rates */
59         switch (params_rate(params)) {
60         case 8000:
61         case 16000:
62         case 48000:
63         case 96000:
64                 mclk = params_rate(params) * SOUND_FS;
65                 break;
66         default:
67                 dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
68                                 __func__, params_rate(params));
69                 return -EINVAL;
70         }
71
72         ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
73         if (ret) {
74                 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
75                                 __func__, mclk, ret);
76                 return ret;
77         }
78
79         return 0;
80 }
81
82 static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
83                              struct snd_pcm_hw_params *params)
84 {
85         struct snd_soc_pcm_runtime *rtd = substream->private_data;
86         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
87         struct snd_soc_dai *codec_dai = rtd->codec_dai;
88         unsigned int mclk;
89         int ret;
90
91         mclk = params_rate(params) * SOUND_FS;
92
93         ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
94                                      SND_SOC_CLOCK_OUT);
95         if (ret < 0) {
96                 dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
97                 return ret;
98         }
99
100         ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
101                                      mclk, SND_SOC_CLOCK_IN);
102         if (ret) {
103                 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
104                                 __func__, params_rate(params) * 512, ret);
105                 return ret;
106         }
107
108         /* Wait for DMIC stable */
109         msleep(dmic_wakeup_delay);
110
111         return 0;
112 }
113
114 static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream,
115                              struct snd_pcm_hw_params *params)
116 {
117         struct snd_soc_pcm_runtime *rtd = substream->private_data;
118         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
119         struct snd_soc_dai *codec_dai = rtd->codec_dai;
120         int mclk, ret;
121
122         /* in bypass mode, the mclk has to be one of the frequencies below */
123         switch (params_rate(params)) {
124         case 8000:
125         case 16000:
126         case 24000:
127         case 32000:
128         case 48000:
129         case 64000:
130         case 96000:
131                 mclk = 12288000;
132                 break;
133         case 11025:
134         case 22050:
135         case 44100:
136         case 88200:
137                 mclk = 11289600;
138                 break;
139         default:
140                 return -EINVAL;
141         }
142
143         ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
144                                      SND_SOC_CLOCK_OUT);
145         if (ret < 0) {
146                 dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
147                 return ret;
148         }
149
150         ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
151                                      SND_SOC_CLOCK_IN);
152         if (ret < 0) {
153                 dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
154                 return ret;
155         }
156
157         ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
158         if (ret < 0) {
159                 dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
160                 return ret;
161         }
162
163         return 0;
164 }
165
166 static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
167 {
168         struct snd_soc_component *component = rtd->codec_dais[0]->component;
169         struct snd_soc_dai *codec_dai = rtd->codec_dai;
170         int ret;
171
172         /* We need default MCLK and PLL settings for the accessory detection */
173         ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
174                                      SND_SOC_CLOCK_IN);
175         if (ret < 0) {
176                 dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
177                 return ret;
178         }
179
180         ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
181         if (ret < 0) {
182                 dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
183                 return ret;
184         }
185
186         /* Enable Headset and 4 Buttons Jack detection */
187         ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
188                                     SND_JACK_HEADSET | SND_JACK_LINEOUT |
189                                     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
190                                     SND_JACK_BTN_2 | SND_JACK_BTN_3,
191                                     &rockchip_sound_jack, NULL, 0);
192
193         if (ret) {
194                 dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
195                 return ret;
196         }
197
198         snd_jack_set_key(
199                 rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
200         snd_jack_set_key(
201                 rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
202         snd_jack_set_key(
203                 rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
204         snd_jack_set_key(
205                 rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
206
207         da7219_aad_jack_det(component, &rockchip_sound_jack);
208
209         return 0;
210 }
211
212 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
213                              struct snd_pcm_hw_params *params)
214 {
215         struct snd_soc_pcm_runtime *rtd = substream->private_data;
216         unsigned int mclk;
217         int ret;
218
219         mclk = params_rate(params) * SOUND_FS;
220
221         ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
222         if (ret) {
223                 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
224                                 __func__, mclk, ret);
225                 return ret;
226         }
227
228         /* Wait for DMIC stable */
229         msleep(dmic_wakeup_delay);
230
231         return 0;
232 }
233
234 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
235         .hw_params = rockchip_sound_max98357a_hw_params,
236 };
237
238 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
239         .hw_params = rockchip_sound_rt5514_hw_params,
240 };
241
242 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
243         .hw_params = rockchip_sound_da7219_hw_params,
244 };
245
246 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
247         .hw_params = rockchip_sound_dmic_hw_params,
248 };
249
250 static struct snd_soc_card rockchip_sound_card = {
251         .name = "rk3399-gru-sound",
252         .owner = THIS_MODULE,
253         .dapm_widgets = rockchip_dapm_widgets,
254         .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
255         .controls = rockchip_controls,
256         .num_controls = ARRAY_SIZE(rockchip_controls),
257 };
258
259 enum {
260         DAILINK_CDNDP,
261         DAILINK_DA7219,
262         DAILINK_DMIC,
263         DAILINK_MAX98357A,
264         DAILINK_RT5514,
265         DAILINK_RT5514_DSP,
266 };
267
268 static const struct snd_soc_dai_link rockchip_dais[] = {
269         [DAILINK_CDNDP] = {
270                 .name = "DP",
271                 .stream_name = "DP PCM",
272                 .codec_dai_name = "spdif-hifi",
273                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
274                         SND_SOC_DAIFMT_CBS_CFS,
275         },
276         [DAILINK_DA7219] = {
277                 .name = "DA7219",
278                 .stream_name = "DA7219 PCM",
279                 .codec_dai_name = "da7219-hifi",
280                 .init = rockchip_sound_da7219_init,
281                 .ops = &rockchip_sound_da7219_ops,
282                 /* set da7219 as slave */
283                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
284                         SND_SOC_DAIFMT_CBS_CFS,
285         },
286         [DAILINK_DMIC] = {
287                 .name = "DMIC",
288                 .stream_name = "DMIC PCM",
289                 .codec_dai_name = "dmic-hifi",
290                 .ops = &rockchip_sound_dmic_ops,
291                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
292                         SND_SOC_DAIFMT_CBS_CFS,
293         },
294         [DAILINK_MAX98357A] = {
295                 .name = "MAX98357A",
296                 .stream_name = "MAX98357A PCM",
297                 .codec_dai_name = "HiFi",
298                 .ops = &rockchip_sound_max98357a_ops,
299                 /* set max98357a as slave */
300                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
301                         SND_SOC_DAIFMT_CBS_CFS,
302         },
303         [DAILINK_RT5514] = {
304                 .name = "RT5514",
305                 .stream_name = "RT5514 PCM",
306                 .codec_dai_name = "rt5514-aif1",
307                 .ops = &rockchip_sound_rt5514_ops,
308                 /* set rt5514 as slave */
309                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
310                         SND_SOC_DAIFMT_CBS_CFS,
311         },
312         /* RT5514 DSP for voice wakeup via spi bus */
313         [DAILINK_RT5514_DSP] = {
314                 .name = "RT5514 DSP",
315                 .stream_name = "Wake on Voice",
316                 .codec_name = "snd-soc-dummy",
317                 .codec_dai_name = "snd-soc-dummy-dai",
318         },
319 };
320
321 static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
322         /* Output */
323         {"HDMI", NULL, "TX"},
324 };
325
326 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
327         /* Output */
328         {"Headphones", NULL, "HPL"},
329         {"Headphones", NULL, "HPR"},
330
331         /* Input */
332         {"MIC", NULL, "Headset Mic"},
333 };
334
335 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
336         /* Input */
337         {"DMic", NULL, "Int Mic"},
338 };
339
340 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
341         /* Output */
342         {"Speakers", NULL, "Speaker"},
343 };
344
345 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
346         /* Input */
347         {"DMIC1L", NULL, "Int Mic"},
348         {"DMIC1R", NULL, "Int Mic"},
349 };
350
351 struct rockchip_sound_route {
352         const struct snd_soc_dapm_route *routes;
353         int num_routes;
354 };
355
356 static const struct rockchip_sound_route rockchip_routes[] = {
357         [DAILINK_CDNDP] = {
358                 .routes = rockchip_sound_cdndp_routes,
359                 .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
360         },
361         [DAILINK_DA7219] = {
362                 .routes = rockchip_sound_da7219_routes,
363                 .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
364         },
365         [DAILINK_DMIC] = {
366                 .routes = rockchip_sound_dmic_routes,
367                 .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
368         },
369         [DAILINK_MAX98357A] = {
370                 .routes = rockchip_sound_max98357a_routes,
371                 .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
372         },
373         [DAILINK_RT5514] = {
374                 .routes = rockchip_sound_rt5514_routes,
375                 .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
376         },
377         [DAILINK_RT5514_DSP] = {},
378 };
379
380 struct dailink_match_data {
381         const char *compatible;
382         struct bus_type *bus_type;
383 };
384
385 static const struct dailink_match_data dailink_match[] = {
386         [DAILINK_CDNDP] = {
387                 .compatible = "rockchip,rk3399-cdn-dp",
388         },
389         [DAILINK_DA7219] = {
390                 .compatible = "dlg,da7219",
391         },
392         [DAILINK_DMIC] = {
393                 .compatible = "dmic-codec",
394         },
395         [DAILINK_MAX98357A] = {
396                 .compatible = "maxim,max98357a",
397         },
398         [DAILINK_RT5514] = {
399                 .compatible = "realtek,rt5514",
400                 .bus_type = &i2c_bus_type,
401         },
402         [DAILINK_RT5514_DSP] = {
403                 .compatible = "realtek,rt5514",
404                 .bus_type = &spi_bus_type,
405         },
406 };
407
408 static int of_dev_node_match(struct device *dev, void *data)
409 {
410         return dev->of_node == data;
411 }
412
413 static int rockchip_sound_codec_node_match(struct device_node *np_codec)
414 {
415         struct device *dev;
416         int i;
417
418         for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
419                 if (!of_device_is_compatible(np_codec,
420                                              dailink_match[i].compatible))
421                         continue;
422
423                 if (dailink_match[i].bus_type) {
424                         dev = bus_find_device(dailink_match[i].bus_type, NULL,
425                                               np_codec, of_dev_node_match);
426                         if (!dev)
427                                 continue;
428                         put_device(dev);
429                 }
430
431                 return i;
432         }
433         return -1;
434 }
435
436 static int rockchip_sound_of_parse_dais(struct device *dev,
437                                         struct snd_soc_card *card)
438 {
439         struct device_node *np_cpu, *np_cpu0, *np_cpu1;
440         struct device_node *np_codec;
441         struct snd_soc_dai_link *dai;
442         struct snd_soc_dapm_route *routes;
443         int i, index;
444         int num_routes;
445
446         card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
447                                       GFP_KERNEL);
448         if (!card->dai_link)
449                 return -ENOMEM;
450
451         num_routes = 0;
452         for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
453                 num_routes += rockchip_routes[i].num_routes;
454         routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
455                               GFP_KERNEL);
456         if (!routes)
457                 return -ENOMEM;
458         card->dapm_routes = routes;
459
460         np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
461         np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
462
463         card->num_dapm_routes = 0;
464         card->num_links = 0;
465         for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
466                 np_codec = of_parse_phandle(dev->of_node,
467                                             "rockchip,codec", i);
468                 if (!np_codec)
469                         break;
470
471                 if (!of_device_is_available(np_codec))
472                         continue;
473
474                 index = rockchip_sound_codec_node_match(np_codec);
475                 if (index < 0)
476                         continue;
477
478                 switch (index) {
479                 case DAILINK_CDNDP:
480                         np_cpu = np_cpu1;
481                         break;
482                 case DAILINK_RT5514_DSP:
483                         np_cpu = np_codec;
484                         break;
485                 default:
486                         np_cpu = np_cpu0;
487                         break;
488                 }
489
490                 if (!np_cpu) {
491                         dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
492                                 rockchip_dais[index].name);
493                         return -EINVAL;
494                 }
495
496                 dai = &card->dai_link[card->num_links++];
497                 *dai = rockchip_dais[index];
498
499                 if (!dai->codec_name)
500                         dai->codec_of_node = np_codec;
501                 dai->platform_of_node = np_cpu;
502                 dai->cpu_of_node = np_cpu;
503
504                 if (card->num_dapm_routes + rockchip_routes[index].num_routes >
505                     num_routes) {
506                         dev_err(dev, "Too many routes\n");
507                         return -EINVAL;
508                 }
509
510                 memcpy(routes + card->num_dapm_routes,
511                        rockchip_routes[index].routes,
512                        rockchip_routes[index].num_routes * sizeof(*routes));
513                 card->num_dapm_routes += rockchip_routes[index].num_routes;
514         }
515
516         return 0;
517 }
518
519 static int rockchip_sound_probe(struct platform_device *pdev)
520 {
521         struct snd_soc_card *card = &rockchip_sound_card;
522         int ret;
523
524         ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
525         if (ret < 0) {
526                 dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
527                 return ret;
528         }
529
530         /* Set DMIC wakeup delay */
531         ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
532                                         &dmic_wakeup_delay);
533         if (ret) {
534                 dmic_wakeup_delay = 0;
535                 dev_dbg(&pdev->dev,
536                         "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
537         }
538
539         card->dev = &pdev->dev;
540         return devm_snd_soc_register_card(&pdev->dev, card);
541 }
542
543 static const struct of_device_id rockchip_sound_of_match[] = {
544         { .compatible = "rockchip,rk3399-gru-sound", },
545         {},
546 };
547
548 static struct platform_driver rockchip_sound_driver = {
549         .probe = rockchip_sound_probe,
550         .driver = {
551                 .name = DRV_NAME,
552                 .of_match_table = rockchip_sound_of_match,
553 #ifdef CONFIG_PM
554                 .pm = &snd_soc_pm_ops,
555 #endif
556         },
557 };
558
559 module_platform_driver(rockchip_sound_driver);
560
561 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
562 MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
563 MODULE_LICENSE("GPL v2");
564 MODULE_ALIAS("platform:" DRV_NAME);
565 MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);