rk3399_gru_sound.c (16052B)
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 31static unsigned int dmic_wakeup_delay; 32 33static struct snd_soc_jack rockchip_sound_jack; 34 35/* Headset jack detection DAPM pins */ 36static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = { 37 { 38 .pin = "Headphones", 39 .mask = SND_JACK_HEADPHONE, 40 }, 41 { 42 .pin = "Headset Mic", 43 .mask = SND_JACK_MICROPHONE, 44 }, 45 46}; 47 48static 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), 54}; 55 56static 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"), 62}; 63 64static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream, 65 struct snd_pcm_hw_params *params) 66{ 67 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 68 unsigned int mclk; 69 int ret; 70 71 mclk = params_rate(params) * SOUND_FS; 72 73 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0); 74 if (ret) { 75 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", 76 __func__, mclk, ret); 77 return ret; 78 } 79 80 return 0; 81} 82 83static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, 84 struct snd_pcm_hw_params *params) 85{ 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); 89 unsigned int mclk; 90 int ret; 91 92 mclk = params_rate(params) * SOUND_FS; 93 94 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, 95 SND_SOC_CLOCK_OUT); 96 if (ret < 0) { 97 dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret); 98 return ret; 99 } 100 101 ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK, 102 mclk, SND_SOC_CLOCK_IN); 103 if (ret) { 104 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", 105 __func__, params_rate(params) * 512, ret); 106 return ret; 107 } 108 109 /* Wait for DMIC stable */ 110 msleep(dmic_wakeup_delay); 111 112 return 0; 113} 114 115static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream, 116 struct snd_pcm_hw_params *params) 117{ 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); 121 int mclk, ret; 122 123 /* in bypass mode, the mclk has to be one of the frequencies below */ 124 switch (params_rate(params)) { 125 case 8000: 126 case 16000: 127 case 24000: 128 case 32000: 129 case 48000: 130 case 64000: 131 case 96000: 132 mclk = 12288000; 133 break; 134 case 11025: 135 case 22050: 136 case 44100: 137 case 88200: 138 mclk = 11289600; 139 break; 140 default: 141 return -EINVAL; 142 } 143 144 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, 145 SND_SOC_CLOCK_OUT); 146 if (ret < 0) { 147 dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret); 148 return ret; 149 } 150 151 ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 152 SND_SOC_CLOCK_IN); 153 if (ret < 0) { 154 dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret); 155 return ret; 156 } 157 158 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); 159 if (ret < 0) { 160 dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret); 161 return ret; 162 } 163 164 return 0; 165} 166 167static struct snd_soc_jack cdn_dp_card_jack; 168 169static int rockchip_sound_cdndp_init(struct snd_soc_pcm_runtime *rtd) 170{ 171 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 172 struct snd_soc_card *card = rtd->card; 173 int ret; 174 175 /* Enable jack detection. */ 176 ret = snd_soc_card_jack_new(card, "DP Jack", SND_JACK_LINEOUT, 177 &cdn_dp_card_jack); 178 if (ret) { 179 dev_err(card->dev, "Can't create DP Jack %d\n", ret); 180 return ret; 181 } 182 183 return snd_soc_component_set_jack(component, &cdn_dp_card_jack, NULL); 184} 185 186static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) 187{ 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); 190 int ret; 191 192 /* We need default MCLK and PLL settings for the accessory detection */ 193 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000, 194 SND_SOC_CLOCK_IN); 195 if (ret < 0) { 196 dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret); 197 return ret; 198 } 199 200 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); 201 if (ret < 0) { 202 dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret); 203 return ret; 204 } 205 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)); 214 215 if (ret) { 216 dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); 217 return ret; 218 } 219 220 snd_jack_set_key( 221 rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 222 snd_jack_set_key( 223 rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); 224 snd_jack_set_key( 225 rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); 226 snd_jack_set_key( 227 rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); 228 229 da7219_aad_jack_det(component, &rockchip_sound_jack); 230 231 return 0; 232} 233 234static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, 235 struct snd_pcm_hw_params *params) 236{ 237 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 238 unsigned int mclk; 239 int ret; 240 241 mclk = params_rate(params) * SOUND_FS; 242 243 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0); 244 if (ret) { 245 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", 246 __func__, mclk, ret); 247 return ret; 248 } 249 250 /* Wait for DMIC stable */ 251 msleep(dmic_wakeup_delay); 252 253 return 0; 254} 255 256static int rockchip_sound_startup(struct snd_pcm_substream *substream) 257{ 258 struct snd_pcm_runtime *runtime = substream->runtime; 259 260 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 261 return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 262 8000, 96000); 263} 264 265static const struct snd_soc_ops rockchip_sound_max98357a_ops = { 266 .startup = rockchip_sound_startup, 267 .hw_params = rockchip_sound_max98357a_hw_params, 268}; 269 270static const struct snd_soc_ops rockchip_sound_rt5514_ops = { 271 .startup = rockchip_sound_startup, 272 .hw_params = rockchip_sound_rt5514_hw_params, 273}; 274 275static const struct snd_soc_ops rockchip_sound_da7219_ops = { 276 .startup = rockchip_sound_startup, 277 .hw_params = rockchip_sound_da7219_hw_params, 278}; 279 280static const struct snd_soc_ops rockchip_sound_dmic_ops = { 281 .startup = rockchip_sound_startup, 282 .hw_params = rockchip_sound_dmic_hw_params, 283}; 284 285static 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), 292}; 293 294enum { 295 DAILINK_CDNDP, 296 DAILINK_DA7219, 297 DAILINK_DMIC, 298 DAILINK_MAX98357A, 299 DAILINK_RT5514, 300 DAILINK_RT5514_DSP, 301}; 302 303SND_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())); 307 308SND_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())); 312 313SND_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())); 317 318SND_SOC_DAILINK_DEFS(max98357a, 319 DAILINK_COMP_ARRAY(COMP_EMPTY()), 320 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), 321 DAILINK_COMP_ARRAY(COMP_EMPTY())); 322 323SND_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())); 327 328SND_SOC_DAILINK_DEFS(rt5514_dsp, 329 DAILINK_COMP_ARRAY(COMP_EMPTY()), 330 DAILINK_COMP_ARRAY(COMP_DUMMY()), 331 DAILINK_COMP_ARRAY(COMP_EMPTY())); 332 333static const struct snd_soc_dai_link rockchip_dais[] = { 334 [DAILINK_CDNDP] = { 335 .name = "DP", 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), 341 }, 342 [DAILINK_DA7219] = { 343 .name = "DA7219", 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), 351 }, 352 [DAILINK_DMIC] = { 353 .name = "DMIC", 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), 359 }, 360 [DAILINK_MAX98357A] = { 361 .name = "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), 368 }, 369 [DAILINK_RT5514] = { 370 .name = "RT5514", 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), 377 }, 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), 383 }, 384}; 385 386static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = { 387 /* Output */ 388 {"HDMI", NULL, "TX"}, 389}; 390 391static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = { 392 /* Output */ 393 {"Headphones", NULL, "HPL"}, 394 {"Headphones", NULL, "HPR"}, 395 396 /* Input */ 397 {"MIC", NULL, "Headset Mic"}, 398}; 399 400static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = { 401 /* Input */ 402 {"DMic", NULL, "Int Mic"}, 403}; 404 405static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = { 406 /* Output */ 407 {"Speakers", NULL, "Speaker"}, 408}; 409 410static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = { 411 /* Input */ 412 {"DMIC1L", NULL, "Int Mic"}, 413 {"DMIC1R", NULL, "Int Mic"}, 414}; 415 416struct rockchip_sound_route { 417 const struct snd_soc_dapm_route *routes; 418 int num_routes; 419}; 420 421static const struct rockchip_sound_route rockchip_routes[] = { 422 [DAILINK_CDNDP] = { 423 .routes = rockchip_sound_cdndp_routes, 424 .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes), 425 }, 426 [DAILINK_DA7219] = { 427 .routes = rockchip_sound_da7219_routes, 428 .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes), 429 }, 430 [DAILINK_DMIC] = { 431 .routes = rockchip_sound_dmic_routes, 432 .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes), 433 }, 434 [DAILINK_MAX98357A] = { 435 .routes = rockchip_sound_max98357a_routes, 436 .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes), 437 }, 438 [DAILINK_RT5514] = { 439 .routes = rockchip_sound_rt5514_routes, 440 .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes), 441 }, 442 [DAILINK_RT5514_DSP] = {}, 443}; 444 445struct dailink_match_data { 446 const char *compatible; 447 struct bus_type *bus_type; 448}; 449 450static const struct dailink_match_data dailink_match[] = { 451 [DAILINK_CDNDP] = { 452 .compatible = "rockchip,rk3399-cdn-dp", 453 }, 454 [DAILINK_DA7219] = { 455 .compatible = "dlg,da7219", 456 }, 457 [DAILINK_DMIC] = { 458 .compatible = "dmic-codec", 459 }, 460 [DAILINK_MAX98357A] = { 461 .compatible = "maxim,max98357a", 462 }, 463 [DAILINK_RT5514] = { 464 .compatible = "realtek,rt5514", 465 .bus_type = &i2c_bus_type, 466 }, 467 [DAILINK_RT5514_DSP] = { 468 .compatible = "realtek,rt5514", 469 .bus_type = &spi_bus_type, 470 }, 471}; 472 473static int rockchip_sound_codec_node_match(struct device_node *np_codec) 474{ 475 struct device *dev; 476 int i; 477 478 for (i = 0; i < ARRAY_SIZE(dailink_match); i++) { 479 if (!of_device_is_compatible(np_codec, 480 dailink_match[i].compatible)) 481 continue; 482 483 if (dailink_match[i].bus_type) { 484 dev = bus_find_device_by_of_node(dailink_match[i].bus_type, 485 np_codec); 486 if (!dev) 487 continue; 488 put_device(dev); 489 } 490 491 return i; 492 } 493 return -1; 494} 495 496static int rockchip_sound_of_parse_dais(struct device *dev, 497 struct snd_soc_card *card) 498{ 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; 503 int i, index; 504 int num_routes; 505 506 card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais), 507 GFP_KERNEL); 508 if (!card->dai_link) 509 return -ENOMEM; 510 511 num_routes = 0; 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), 515 GFP_KERNEL); 516 if (!routes) 517 return -ENOMEM; 518 card->dapm_routes = routes; 519 520 np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0); 521 np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1); 522 523 card->num_dapm_routes = 0; 524 card->num_links = 0; 525 for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) { 526 np_codec = of_parse_phandle(dev->of_node, 527 "rockchip,codec", i); 528 if (!np_codec) 529 break; 530 531 if (!of_device_is_available(np_codec)) 532 continue; 533 534 index = rockchip_sound_codec_node_match(np_codec); 535 if (index < 0) 536 continue; 537 538 switch (index) { 539 case DAILINK_CDNDP: 540 np_cpu = np_cpu1; 541 break; 542 case DAILINK_RT5514_DSP: 543 np_cpu = np_codec; 544 break; 545 default: 546 np_cpu = np_cpu0; 547 break; 548 } 549 550 if (!np_cpu) { 551 dev_err(dev, "Missing 'rockchip,cpu' for %s\n", 552 rockchip_dais[index].name); 553 return -EINVAL; 554 } 555 556 dai = &card->dai_link[card->num_links++]; 557 *dai = rockchip_dais[index]; 558 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; 563 564 if (card->num_dapm_routes + rockchip_routes[index].num_routes > 565 num_routes) { 566 dev_err(dev, "Too many routes\n"); 567 return -EINVAL; 568 } 569 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; 574 } 575 576 return 0; 577} 578 579static int rockchip_sound_probe(struct platform_device *pdev) 580{ 581 struct snd_soc_card *card = &rockchip_sound_card; 582 int ret; 583 584 ret = rockchip_sound_of_parse_dais(&pdev->dev, card); 585 if (ret < 0) { 586 dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret); 587 return ret; 588 } 589 590 /* Set DMIC wakeup delay */ 591 ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms", 592 &dmic_wakeup_delay); 593 if (ret) { 594 dmic_wakeup_delay = 0; 595 dev_dbg(&pdev->dev, 596 "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n"); 597 } 598 599 card->dev = &pdev->dev; 600 return devm_snd_soc_register_card(&pdev->dev, card); 601} 602 603static const struct of_device_id rockchip_sound_of_match[] = { 604 { .compatible = "rockchip,rk3399-gru-sound", }, 605 {}, 606}; 607 608static struct platform_driver rockchip_sound_driver = { 609 .probe = rockchip_sound_probe, 610 .driver = { 611 .name = DRV_NAME, 612 .of_match_table = rockchip_sound_of_match, 613#ifdef CONFIG_PM 614 .pm = &snd_soc_pm_ops, 615#endif 616 }, 617}; 618 619module_platform_driver(rockchip_sound_driver); 620 621MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>"); 622MODULE_DESCRIPTION("Rockchip ASoC Machine Driver"); 623MODULE_LICENSE("GPL v2"); 624MODULE_ALIAS("platform:" DRV_NAME); 625MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);