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 int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
169 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
170 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
173 /* We need default MCLK and PLL settings for the accessory detection */
174 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
177 dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
181 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
183 dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
187 /* Enable Headset and 4 Buttons Jack detection */
188 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
189 SND_JACK_HEADSET | SND_JACK_LINEOUT |
190 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
191 SND_JACK_BTN_2 | SND_JACK_BTN_3,
192 &rockchip_sound_jack,
193 rockchip_sound_jack_pins,
194 ARRAY_SIZE(rockchip_sound_jack_pins));
197 dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
202 rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
204 rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
206 rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
208 rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
210 da7219_aad_jack_det(component, &rockchip_sound_jack);
215 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
216 struct snd_pcm_hw_params *params)
218 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
222 mclk = params_rate(params) * SOUND_FS;
224 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
226 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
227 __func__, mclk, ret);
231 /* Wait for DMIC stable */
232 msleep(dmic_wakeup_delay);
237 static int rockchip_sound_startup(struct snd_pcm_substream *substream)
239 struct snd_pcm_runtime *runtime = substream->runtime;
241 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
242 return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
246 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
247 .startup = rockchip_sound_startup,
248 .hw_params = rockchip_sound_max98357a_hw_params,
251 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
252 .startup = rockchip_sound_startup,
253 .hw_params = rockchip_sound_rt5514_hw_params,
256 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
257 .startup = rockchip_sound_startup,
258 .hw_params = rockchip_sound_da7219_hw_params,
261 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
262 .startup = rockchip_sound_startup,
263 .hw_params = rockchip_sound_dmic_hw_params,
266 static struct snd_soc_card rockchip_sound_card = {
267 .name = "rk3399-gru-sound",
268 .owner = THIS_MODULE,
269 .dapm_widgets = rockchip_dapm_widgets,
270 .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
271 .controls = rockchip_controls,
272 .num_controls = ARRAY_SIZE(rockchip_controls),
284 SND_SOC_DAILINK_DEFS(cdndp,
285 DAILINK_COMP_ARRAY(COMP_EMPTY()),
286 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")),
287 DAILINK_COMP_ARRAY(COMP_EMPTY()));
289 SND_SOC_DAILINK_DEFS(da7219,
290 DAILINK_COMP_ARRAY(COMP_EMPTY()),
291 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")),
292 DAILINK_COMP_ARRAY(COMP_EMPTY()));
294 SND_SOC_DAILINK_DEFS(dmic,
295 DAILINK_COMP_ARRAY(COMP_EMPTY()),
296 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")),
297 DAILINK_COMP_ARRAY(COMP_EMPTY()));
299 SND_SOC_DAILINK_DEFS(max98357a,
300 DAILINK_COMP_ARRAY(COMP_EMPTY()),
301 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
302 DAILINK_COMP_ARRAY(COMP_EMPTY()));
304 SND_SOC_DAILINK_DEFS(rt5514,
305 DAILINK_COMP_ARRAY(COMP_EMPTY()),
306 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")),
307 DAILINK_COMP_ARRAY(COMP_EMPTY()));
309 SND_SOC_DAILINK_DEFS(rt5514_dsp,
310 DAILINK_COMP_ARRAY(COMP_EMPTY()),
311 DAILINK_COMP_ARRAY(COMP_DUMMY()),
312 DAILINK_COMP_ARRAY(COMP_EMPTY()));
314 static const struct snd_soc_dai_link rockchip_dais[] = {
317 .stream_name = "DP PCM",
318 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
319 SND_SOC_DAIFMT_CBS_CFS,
320 SND_SOC_DAILINK_REG(cdndp),
324 .stream_name = "DA7219 PCM",
325 .init = rockchip_sound_da7219_init,
326 .ops = &rockchip_sound_da7219_ops,
327 /* set da7219 as slave */
328 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
329 SND_SOC_DAIFMT_CBS_CFS,
330 SND_SOC_DAILINK_REG(da7219),
334 .stream_name = "DMIC PCM",
335 .ops = &rockchip_sound_dmic_ops,
336 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
337 SND_SOC_DAIFMT_CBS_CFS,
338 SND_SOC_DAILINK_REG(dmic),
340 [DAILINK_MAX98357A] = {
342 .stream_name = "MAX98357A PCM",
343 .ops = &rockchip_sound_max98357a_ops,
344 /* set max98357a as slave */
345 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
346 SND_SOC_DAIFMT_CBS_CFS,
347 SND_SOC_DAILINK_REG(max98357a),
351 .stream_name = "RT5514 PCM",
352 .ops = &rockchip_sound_rt5514_ops,
353 /* set rt5514 as slave */
354 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
355 SND_SOC_DAIFMT_CBS_CFS,
356 SND_SOC_DAILINK_REG(rt5514),
358 /* RT5514 DSP for voice wakeup via spi bus */
359 [DAILINK_RT5514_DSP] = {
360 .name = "RT5514 DSP",
361 .stream_name = "Wake on Voice",
362 SND_SOC_DAILINK_REG(rt5514_dsp),
366 static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
368 {"HDMI", NULL, "TX"},
371 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
373 {"Headphones", NULL, "HPL"},
374 {"Headphones", NULL, "HPR"},
377 {"MIC", NULL, "Headset Mic"},
380 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
382 {"DMic", NULL, "Int Mic"},
385 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
387 {"Speakers", NULL, "Speaker"},
390 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
392 {"DMIC1L", NULL, "Int Mic"},
393 {"DMIC1R", NULL, "Int Mic"},
396 struct rockchip_sound_route {
397 const struct snd_soc_dapm_route *routes;
401 static const struct rockchip_sound_route rockchip_routes[] = {
403 .routes = rockchip_sound_cdndp_routes,
404 .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
407 .routes = rockchip_sound_da7219_routes,
408 .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
411 .routes = rockchip_sound_dmic_routes,
412 .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
414 [DAILINK_MAX98357A] = {
415 .routes = rockchip_sound_max98357a_routes,
416 .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
419 .routes = rockchip_sound_rt5514_routes,
420 .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
422 [DAILINK_RT5514_DSP] = {},
425 struct dailink_match_data {
426 const char *compatible;
427 struct bus_type *bus_type;
430 static const struct dailink_match_data dailink_match[] = {
432 .compatible = "rockchip,rk3399-cdn-dp",
435 .compatible = "dlg,da7219",
438 .compatible = "dmic-codec",
440 [DAILINK_MAX98357A] = {
441 .compatible = "maxim,max98357a",
444 .compatible = "realtek,rt5514",
445 .bus_type = &i2c_bus_type,
447 [DAILINK_RT5514_DSP] = {
448 .compatible = "realtek,rt5514",
449 .bus_type = &spi_bus_type,
453 static int rockchip_sound_codec_node_match(struct device_node *np_codec)
458 for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
459 if (!of_device_is_compatible(np_codec,
460 dailink_match[i].compatible))
463 if (dailink_match[i].bus_type) {
464 dev = bus_find_device_by_of_node(dailink_match[i].bus_type,
476 static int rockchip_sound_of_parse_dais(struct device *dev,
477 struct snd_soc_card *card)
479 struct device_node *np_cpu, *np_cpu0, *np_cpu1;
480 struct device_node *np_codec;
481 struct snd_soc_dai_link *dai;
482 struct snd_soc_dapm_route *routes;
486 card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
492 for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
493 num_routes += rockchip_routes[i].num_routes;
494 routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
498 card->dapm_routes = routes;
500 np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
501 np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
503 card->num_dapm_routes = 0;
505 for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
506 np_codec = of_parse_phandle(dev->of_node,
507 "rockchip,codec", i);
511 if (!of_device_is_available(np_codec))
514 index = rockchip_sound_codec_node_match(np_codec);
522 case DAILINK_RT5514_DSP:
531 dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
532 rockchip_dais[index].name);
536 dai = &card->dai_link[card->num_links++];
537 *dai = rockchip_dais[index];
539 if (!dai->codecs->name)
540 dai->codecs->of_node = np_codec;
541 dai->platforms->of_node = np_cpu;
542 dai->cpus->of_node = np_cpu;
544 if (card->num_dapm_routes + rockchip_routes[index].num_routes >
546 dev_err(dev, "Too many routes\n");
550 memcpy(routes + card->num_dapm_routes,
551 rockchip_routes[index].routes,
552 rockchip_routes[index].num_routes * sizeof(*routes));
553 card->num_dapm_routes += rockchip_routes[index].num_routes;
559 static int rockchip_sound_probe(struct platform_device *pdev)
561 struct snd_soc_card *card = &rockchip_sound_card;
564 ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
566 dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
570 /* Set DMIC wakeup delay */
571 ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
574 dmic_wakeup_delay = 0;
576 "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
579 card->dev = &pdev->dev;
580 return devm_snd_soc_register_card(&pdev->dev, card);
583 static const struct of_device_id rockchip_sound_of_match[] = {
584 { .compatible = "rockchip,rk3399-gru-sound", },
588 static struct platform_driver rockchip_sound_driver = {
589 .probe = rockchip_sound_probe,
592 .of_match_table = rockchip_sound_of_match,
594 .pm = &snd_soc_pm_ops,
599 module_platform_driver(rockchip_sound_driver);
601 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
602 MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
603 MODULE_LICENSE("GPL v2");
604 MODULE_ALIAS("platform:" DRV_NAME);
605 MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);