1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
5 * Copyright (c) 2016, ROCKCHIP CORPORATION. All rights reserved.
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"
27 #define DRV_NAME "rk3399-gru-sound"
31 static unsigned int dmic_wakeup_delay;
33 static struct snd_soc_jack rockchip_sound_jack;
35 /* Headset jack detection DAPM pins */
36 static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = {
39 .mask = SND_JACK_HEADPHONE,
43 .mask = SND_JACK_MICROPHONE,
48 static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
49 SND_SOC_DAPM_HP("Headphones", NULL),
50 SND_SOC_DAPM_SPK("Speakers", NULL),
51 SND_SOC_DAPM_MIC("Headset Mic", NULL),
52 SND_SOC_DAPM_MIC("Int Mic", NULL),
53 SND_SOC_DAPM_LINE("HDMI", NULL),
56 static const struct snd_kcontrol_new rockchip_controls[] = {
57 SOC_DAPM_PIN_SWITCH("Headphones"),
58 SOC_DAPM_PIN_SWITCH("Speakers"),
59 SOC_DAPM_PIN_SWITCH("Headset Mic"),
60 SOC_DAPM_PIN_SWITCH("Int Mic"),
61 SOC_DAPM_PIN_SWITCH("HDMI"),
64 static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
65 struct snd_pcm_hw_params *params)
67 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
71 mclk = params_rate(params) * SOUND_FS;
73 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
75 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
83 static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
84 struct snd_pcm_hw_params *params)
86 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
87 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
88 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
92 mclk = params_rate(params) * SOUND_FS;
94 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
97 dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
101 ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
102 mclk, SND_SOC_CLOCK_IN);
104 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
105 __func__, params_rate(params) * 512, ret);
109 /* Wait for DMIC stable */
110 msleep(dmic_wakeup_delay);
115 static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream,
116 struct snd_pcm_hw_params *params)
118 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
119 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
120 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
123 /* in bypass mode, the mclk has to be one of the frequencies below */
124 switch (params_rate(params)) {
144 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
147 dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
151 ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
154 dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
158 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
160 dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
167 static struct snd_soc_jack cdn_dp_card_jack;
169 static int rockchip_sound_cdndp_init(struct snd_soc_pcm_runtime *rtd)
171 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
172 struct snd_soc_card *card = rtd->card;
175 /* Enable jack detection. */
176 ret = snd_soc_card_jack_new(card, "DP Jack", SND_JACK_LINEOUT,
179 dev_err(card->dev, "Can't create DP Jack %d\n", ret);
183 return snd_soc_component_set_jack(component, &cdn_dp_card_jack, NULL);
186 static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
188 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
189 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
192 /* We need default MCLK and PLL settings for the accessory detection */
193 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
196 dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
200 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
202 dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
206 /* Enable Headset and 4 Buttons Jack detection */
207 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
208 SND_JACK_HEADSET | SND_JACK_LINEOUT |
209 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
210 SND_JACK_BTN_2 | SND_JACK_BTN_3,
211 &rockchip_sound_jack,
212 rockchip_sound_jack_pins,
213 ARRAY_SIZE(rockchip_sound_jack_pins));
216 dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
221 rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
223 rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
225 rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
227 rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
229 da7219_aad_jack_det(component, &rockchip_sound_jack);
234 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
235 struct snd_pcm_hw_params *params)
237 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
241 mclk = params_rate(params) * SOUND_FS;
243 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
245 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
246 __func__, mclk, ret);
250 /* Wait for DMIC stable */
251 msleep(dmic_wakeup_delay);
256 static int rockchip_sound_startup(struct snd_pcm_substream *substream)
258 struct snd_pcm_runtime *runtime = substream->runtime;
260 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
261 return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
265 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
266 .startup = rockchip_sound_startup,
267 .hw_params = rockchip_sound_max98357a_hw_params,
270 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
271 .startup = rockchip_sound_startup,
272 .hw_params = rockchip_sound_rt5514_hw_params,
275 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
276 .startup = rockchip_sound_startup,
277 .hw_params = rockchip_sound_da7219_hw_params,
280 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
281 .startup = rockchip_sound_startup,
282 .hw_params = rockchip_sound_dmic_hw_params,
285 static struct snd_soc_card rockchip_sound_card = {
286 .name = "rk3399-gru-sound",
287 .owner = THIS_MODULE,
288 .dapm_widgets = rockchip_dapm_widgets,
289 .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
290 .controls = rockchip_controls,
291 .num_controls = ARRAY_SIZE(rockchip_controls),
303 SND_SOC_DAILINK_DEFS(cdndp,
304 DAILINK_COMP_ARRAY(COMP_EMPTY()),
305 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")),
306 DAILINK_COMP_ARRAY(COMP_EMPTY()));
308 SND_SOC_DAILINK_DEFS(da7219,
309 DAILINK_COMP_ARRAY(COMP_EMPTY()),
310 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")),
311 DAILINK_COMP_ARRAY(COMP_EMPTY()));
313 SND_SOC_DAILINK_DEFS(dmic,
314 DAILINK_COMP_ARRAY(COMP_EMPTY()),
315 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")),
316 DAILINK_COMP_ARRAY(COMP_EMPTY()));
318 SND_SOC_DAILINK_DEFS(max98357a,
319 DAILINK_COMP_ARRAY(COMP_EMPTY()),
320 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
321 DAILINK_COMP_ARRAY(COMP_EMPTY()));
323 SND_SOC_DAILINK_DEFS(rt5514,
324 DAILINK_COMP_ARRAY(COMP_EMPTY()),
325 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")),
326 DAILINK_COMP_ARRAY(COMP_EMPTY()));
328 SND_SOC_DAILINK_DEFS(rt5514_dsp,
329 DAILINK_COMP_ARRAY(COMP_EMPTY()),
330 DAILINK_COMP_ARRAY(COMP_DUMMY()),
331 DAILINK_COMP_ARRAY(COMP_EMPTY()));
333 static const struct snd_soc_dai_link rockchip_dais[] = {
336 .stream_name = "DP PCM",
337 .init = rockchip_sound_cdndp_init,
338 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
339 SND_SOC_DAIFMT_CBS_CFS,
340 SND_SOC_DAILINK_REG(cdndp),
344 .stream_name = "DA7219 PCM",
345 .init = rockchip_sound_da7219_init,
346 .ops = &rockchip_sound_da7219_ops,
347 /* set da7219 as slave */
348 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
349 SND_SOC_DAIFMT_CBS_CFS,
350 SND_SOC_DAILINK_REG(da7219),
354 .stream_name = "DMIC PCM",
355 .ops = &rockchip_sound_dmic_ops,
356 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
357 SND_SOC_DAIFMT_CBS_CFS,
358 SND_SOC_DAILINK_REG(dmic),
360 [DAILINK_MAX98357A] = {
362 .stream_name = "MAX98357A PCM",
363 .ops = &rockchip_sound_max98357a_ops,
364 /* set max98357a as slave */
365 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
366 SND_SOC_DAIFMT_CBS_CFS,
367 SND_SOC_DAILINK_REG(max98357a),
371 .stream_name = "RT5514 PCM",
372 .ops = &rockchip_sound_rt5514_ops,
373 /* set rt5514 as slave */
374 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
375 SND_SOC_DAIFMT_CBS_CFS,
376 SND_SOC_DAILINK_REG(rt5514),
378 /* RT5514 DSP for voice wakeup via spi bus */
379 [DAILINK_RT5514_DSP] = {
380 .name = "RT5514 DSP",
381 .stream_name = "Wake on Voice",
382 SND_SOC_DAILINK_REG(rt5514_dsp),
386 static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
388 {"HDMI", NULL, "TX"},
391 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
393 {"Headphones", NULL, "HPL"},
394 {"Headphones", NULL, "HPR"},
397 {"MIC", NULL, "Headset Mic"},
400 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
402 {"DMic", NULL, "Int Mic"},
405 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
407 {"Speakers", NULL, "Speaker"},
410 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
412 {"DMIC1L", NULL, "Int Mic"},
413 {"DMIC1R", NULL, "Int Mic"},
416 struct rockchip_sound_route {
417 const struct snd_soc_dapm_route *routes;
421 static const struct rockchip_sound_route rockchip_routes[] = {
423 .routes = rockchip_sound_cdndp_routes,
424 .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
427 .routes = rockchip_sound_da7219_routes,
428 .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
431 .routes = rockchip_sound_dmic_routes,
432 .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
434 [DAILINK_MAX98357A] = {
435 .routes = rockchip_sound_max98357a_routes,
436 .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
439 .routes = rockchip_sound_rt5514_routes,
440 .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
442 [DAILINK_RT5514_DSP] = {},
445 struct dailink_match_data {
446 const char *compatible;
447 struct bus_type *bus_type;
450 static const struct dailink_match_data dailink_match[] = {
452 .compatible = "rockchip,rk3399-cdn-dp",
455 .compatible = "dlg,da7219",
458 .compatible = "dmic-codec",
460 [DAILINK_MAX98357A] = {
461 .compatible = "maxim,max98357a",
464 .compatible = "realtek,rt5514",
465 .bus_type = &i2c_bus_type,
467 [DAILINK_RT5514_DSP] = {
468 .compatible = "realtek,rt5514",
469 .bus_type = &spi_bus_type,
473 static int rockchip_sound_codec_node_match(struct device_node *np_codec)
478 for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
479 if (!of_device_is_compatible(np_codec,
480 dailink_match[i].compatible))
483 if (dailink_match[i].bus_type) {
484 dev = bus_find_device_by_of_node(dailink_match[i].bus_type,
496 static int rockchip_sound_of_parse_dais(struct device *dev,
497 struct snd_soc_card *card)
499 struct device_node *np_cpu, *np_cpu0, *np_cpu1;
500 struct device_node *np_codec;
501 struct snd_soc_dai_link *dai;
502 struct snd_soc_dapm_route *routes;
506 card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
512 for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
513 num_routes += rockchip_routes[i].num_routes;
514 routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
518 card->dapm_routes = routes;
520 np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
521 np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
523 card->num_dapm_routes = 0;
525 for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
526 np_codec = of_parse_phandle(dev->of_node,
527 "rockchip,codec", i);
531 if (!of_device_is_available(np_codec))
534 index = rockchip_sound_codec_node_match(np_codec);
542 case DAILINK_RT5514_DSP:
551 dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
552 rockchip_dais[index].name);
556 dai = &card->dai_link[card->num_links++];
557 *dai = rockchip_dais[index];
559 if (!dai->codecs->name)
560 dai->codecs->of_node = np_codec;
561 dai->platforms->of_node = np_cpu;
562 dai->cpus->of_node = np_cpu;
564 if (card->num_dapm_routes + rockchip_routes[index].num_routes >
566 dev_err(dev, "Too many routes\n");
570 memcpy(routes + card->num_dapm_routes,
571 rockchip_routes[index].routes,
572 rockchip_routes[index].num_routes * sizeof(*routes));
573 card->num_dapm_routes += rockchip_routes[index].num_routes;
579 static int rockchip_sound_probe(struct platform_device *pdev)
581 struct snd_soc_card *card = &rockchip_sound_card;
584 ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
586 dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
590 /* Set DMIC wakeup delay */
591 ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
594 dmic_wakeup_delay = 0;
596 "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
599 card->dev = &pdev->dev;
600 return devm_snd_soc_register_card(&pdev->dev, card);
603 static const struct of_device_id rockchip_sound_of_match[] = {
604 { .compatible = "rockchip,rk3399-gru-sound", },
608 static struct platform_driver rockchip_sound_driver = {
609 .probe = rockchip_sound_probe,
612 .of_match_table = rockchip_sound_of_match,
614 .pm = &snd_soc_pm_ops,
619 module_platform_driver(rockchip_sound_driver);
621 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
622 MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
623 MODULE_LICENSE("GPL v2");
624 MODULE_ALIAS("platform:" DRV_NAME);
625 MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);