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 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 .codec_dai_name = "wm5110-aif1", 387 .ops = &tm2_aif1_ops, 388 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 389 SND_SOC_DAIFMT_CBM_CFM, 390 }, { 391 .name = "WM5110 Voice", 392 .stream_name = "Voice call", 393 .codec_dai_name = "wm5110-aif2", 394 .ops = &tm2_aif2_ops, 395 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 396 SND_SOC_DAIFMT_CBM_CFM, 397 .ignore_suspend = 1, 398 }, { 399 .name = "WM5110 BT", 400 .stream_name = "Bluetooth", 401 .codec_dai_name = "wm5110-aif3", 402 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 403 SND_SOC_DAIFMT_CBM_CFM, 404 .ignore_suspend = 1, 405 } 406 }; 407 408 static struct snd_soc_card tm2_card = { 409 .owner = THIS_MODULE, 410 411 .dai_link = tm2_dai_links, 412 .num_links = ARRAY_SIZE(tm2_dai_links), 413 .controls = tm2_controls, 414 .num_controls = ARRAY_SIZE(tm2_controls), 415 .dapm_widgets = tm2_dapm_widgets, 416 .num_dapm_widgets = ARRAY_SIZE(tm2_dapm_widgets), 417 .aux_dev = &tm2_speaker_amp_dev, 418 .num_aux_devs = 1, 419 420 .late_probe = tm2_late_probe, 421 .set_bias_level = tm2_set_bias_level, 422 }; 423 424 static int tm2_probe(struct platform_device *pdev) 425 { 426 struct device *dev = &pdev->dev; 427 struct snd_soc_card *card = &tm2_card; 428 struct tm2_machine_priv *priv; 429 struct device_node *cpu_dai_node, *codec_dai_node; 430 int ret, i; 431 432 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 433 if (!priv) 434 return -ENOMEM; 435 436 snd_soc_card_set_drvdata(card, priv); 437 card->dev = dev; 438 439 priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", 440 GPIOF_OUT_INIT_LOW); 441 if (IS_ERR(priv->gpio_mic_bias)) { 442 dev_err(dev, "Failed to get mic bias gpio\n"); 443 return PTR_ERR(priv->gpio_mic_bias); 444 } 445 446 ret = snd_soc_of_parse_card_name(card, "model"); 447 if (ret < 0) { 448 dev_err(dev, "Card name is not specified\n"); 449 return ret; 450 } 451 452 ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); 453 if (ret < 0) { 454 dev_err(dev, "Audio routing is not specified or invalid\n"); 455 return ret; 456 } 457 458 card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, 459 "audio-amplifier", 0); 460 if (!card->aux_dev[0].codec_of_node) { 461 dev_err(dev, "audio-amplifier property invalid or missing\n"); 462 return -EINVAL; 463 } 464 465 cpu_dai_node = of_parse_phandle(dev->of_node, "i2s-controller", 0); 466 if (!cpu_dai_node) { 467 dev_err(dev, "i2s-controllers property invalid or missing\n"); 468 ret = -EINVAL; 469 goto amp_node_put; 470 } 471 472 codec_dai_node = of_parse_phandle(dev->of_node, "audio-codec", 0); 473 if (!codec_dai_node) { 474 dev_err(dev, "audio-codec property invalid or missing\n"); 475 ret = -EINVAL; 476 goto cpu_dai_node_put; 477 } 478 479 for (i = 0; i < card->num_links; i++) { 480 card->dai_link[i].cpu_dai_name = NULL; 481 card->dai_link[i].cpu_name = NULL; 482 card->dai_link[i].platform_name = NULL; 483 card->dai_link[i].codec_of_node = codec_dai_node; 484 card->dai_link[i].cpu_of_node = cpu_dai_node; 485 card->dai_link[i].platform_of_node = cpu_dai_node; 486 } 487 488 ret = devm_snd_soc_register_component(dev, &tm2_component, 489 tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai)); 490 if (ret < 0) { 491 dev_err(dev, "Failed to register component: %d\n", ret); 492 goto codec_dai_node_put; 493 } 494 495 ret = devm_snd_soc_register_card(dev, card); 496 if (ret < 0) { 497 dev_err(dev, "Failed to register card: %d\n", ret); 498 goto codec_dai_node_put; 499 } 500 501 codec_dai_node_put: 502 of_node_put(codec_dai_node); 503 cpu_dai_node_put: 504 of_node_put(cpu_dai_node); 505 amp_node_put: 506 of_node_put(card->aux_dev[0].codec_of_node); 507 return ret; 508 } 509 510 static int tm2_pm_prepare(struct device *dev) 511 { 512 struct snd_soc_card *card = dev_get_drvdata(dev); 513 514 return tm2_stop_sysclk(card); 515 } 516 517 static void tm2_pm_complete(struct device *dev) 518 { 519 struct snd_soc_card *card = dev_get_drvdata(dev); 520 521 tm2_start_sysclk(card); 522 } 523 524 const struct dev_pm_ops tm2_pm_ops = { 525 .prepare = tm2_pm_prepare, 526 .suspend = snd_soc_suspend, 527 .resume = snd_soc_resume, 528 .complete = tm2_pm_complete, 529 .freeze = snd_soc_suspend, 530 .thaw = snd_soc_resume, 531 .poweroff = snd_soc_poweroff, 532 .restore = snd_soc_resume, 533 }; 534 535 static const struct of_device_id tm2_of_match[] = { 536 { .compatible = "samsung,tm2-audio" }, 537 { }, 538 }; 539 MODULE_DEVICE_TABLE(of, tm2_of_match); 540 541 static struct platform_driver tm2_driver = { 542 .driver = { 543 .name = "tm2-audio", 544 .pm = &tm2_pm_ops, 545 .of_match_table = tm2_of_match, 546 }, 547 .probe = tm2_probe, 548 }; 549 module_platform_driver(tm2_driver); 550 551 MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>"); 552 MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support"); 553 MODULE_LICENSE("GPL v2"); 554