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