1 /* 2 * byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform 3 * 4 * Copyright (C) 2014 Intel Corp 5 * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 */ 19 20 #include <linux/init.h> 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 #include <linux/acpi.h> 24 #include <linux/device.h> 25 #include <linux/dmi.h> 26 #include <linux/slab.h> 27 #include <asm/cpu_device_id.h> 28 #include <asm/platform_sst_audio.h> 29 #include <linux/clk.h> 30 #include <sound/pcm.h> 31 #include <sound/pcm_params.h> 32 #include <sound/soc.h> 33 #include <sound/jack.h> 34 #include "../../codecs/rt5640.h" 35 #include "../atom/sst-atom-controls.h" 36 #include "../common/sst-acpi.h" 37 #include "../common/sst-dsp.h" 38 39 enum { 40 BYT_RT5640_DMIC1_MAP, 41 BYT_RT5640_DMIC2_MAP, 42 BYT_RT5640_IN1_MAP, 43 BYT_RT5640_IN3_MAP, 44 }; 45 46 #define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) 47 #define BYT_RT5640_DMIC_EN BIT(16) 48 #define BYT_RT5640_MONO_SPEAKER BIT(17) 49 #define BYT_RT5640_DIFF_MIC BIT(18) /* defaut is single-ended */ 50 #define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ 51 #define BYT_RT5640_SSP0_AIF1 BIT(20) 52 #define BYT_RT5640_SSP0_AIF2 BIT(21) 53 #define BYT_RT5640_MCLK_EN BIT(22) 54 #define BYT_RT5640_MCLK_25MHZ BIT(23) 55 56 struct byt_rt5640_private { 57 struct clk *mclk; 58 }; 59 60 static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | 61 BYT_RT5640_DMIC_EN | 62 BYT_RT5640_MCLK_EN; 63 64 static void log_quirks(struct device *dev) 65 { 66 if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC1_MAP) 67 dev_info(dev, "quirk DMIC1_MAP enabled"); 68 if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC2_MAP) 69 dev_info(dev, "quirk DMIC2_MAP enabled"); 70 if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN1_MAP) 71 dev_info(dev, "quirk IN1_MAP enabled"); 72 if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN3_MAP) 73 dev_info(dev, "quirk IN3_MAP enabled"); 74 if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) 75 dev_info(dev, "quirk DMIC enabled"); 76 if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) 77 dev_info(dev, "quirk MONO_SPEAKER enabled"); 78 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 79 dev_info(dev, "quirk DIFF_MIC enabled"); 80 if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) 81 dev_info(dev, "quirk SSP2_AIF2 enabled"); 82 if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) 83 dev_info(dev, "quirk SSP0_AIF1 enabled"); 84 if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) 85 dev_info(dev, "quirk SSP0_AIF2 enabled"); 86 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) 87 dev_info(dev, "quirk MCLK_EN enabled"); 88 if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) 89 dev_info(dev, "quirk MCLK_25MHZ enabled"); 90 } 91 92 93 #define BYT_CODEC_DAI1 "rt5640-aif1" 94 #define BYT_CODEC_DAI2 "rt5640-aif2" 95 96 static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card) 97 { 98 struct snd_soc_pcm_runtime *rtd; 99 100 list_for_each_entry(rtd, &card->rtd_list, list) { 101 if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1, 102 strlen(BYT_CODEC_DAI1))) 103 return rtd->codec_dai; 104 if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI2, 105 strlen(BYT_CODEC_DAI2))) 106 return rtd->codec_dai; 107 108 } 109 return NULL; 110 } 111 112 static int platform_clock_control(struct snd_soc_dapm_widget *w, 113 struct snd_kcontrol *k, int event) 114 { 115 struct snd_soc_dapm_context *dapm = w->dapm; 116 struct snd_soc_card *card = dapm->card; 117 struct snd_soc_dai *codec_dai; 118 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 119 int ret; 120 121 codec_dai = byt_get_codec_dai(card); 122 if (!codec_dai) { 123 dev_err(card->dev, 124 "Codec dai not found; Unable to set platform clock\n"); 125 return -EIO; 126 } 127 128 if (SND_SOC_DAPM_EVENT_ON(event)) { 129 if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) { 130 ret = clk_prepare_enable(priv->mclk); 131 if (ret < 0) { 132 dev_err(card->dev, 133 "could not configure MCLK state"); 134 return ret; 135 } 136 } 137 ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, 138 48000 * 512, 139 SND_SOC_CLOCK_IN); 140 } else { 141 /* 142 * Set codec clock source to internal clock before 143 * turning off the platform clock. Codec needs clock 144 * for Jack detection and button press 145 */ 146 ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, 147 0, 148 SND_SOC_CLOCK_IN); 149 if (!ret) { 150 if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) 151 clk_disable_unprepare(priv->mclk); 152 } 153 } 154 155 if (ret < 0) { 156 dev_err(card->dev, "can't set codec sysclk: %d\n", ret); 157 return ret; 158 } 159 160 return 0; 161 } 162 163 static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { 164 SND_SOC_DAPM_HP("Headphone", NULL), 165 SND_SOC_DAPM_MIC("Headset Mic", NULL), 166 SND_SOC_DAPM_MIC("Internal Mic", NULL), 167 SND_SOC_DAPM_SPK("Speaker", NULL), 168 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 169 platform_clock_control, SND_SOC_DAPM_PRE_PMU | 170 SND_SOC_DAPM_POST_PMD), 171 172 }; 173 174 static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { 175 {"Headphone", NULL, "Platform Clock"}, 176 {"Headset Mic", NULL, "Platform Clock"}, 177 {"Internal Mic", NULL, "Platform Clock"}, 178 {"Speaker", NULL, "Platform Clock"}, 179 180 {"Headset Mic", NULL, "MICBIAS1"}, 181 {"IN2P", NULL, "Headset Mic"}, 182 {"Headphone", NULL, "HPOL"}, 183 {"Headphone", NULL, "HPOR"}, 184 }; 185 186 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { 187 {"DMIC1", NULL, "Internal Mic"}, 188 }; 189 190 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { 191 {"DMIC2", NULL, "Internal Mic"}, 192 }; 193 194 static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { 195 {"Internal Mic", NULL, "MICBIAS1"}, 196 {"IN1P", NULL, "Internal Mic"}, 197 }; 198 199 static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { 200 {"Internal Mic", NULL, "MICBIAS1"}, 201 {"IN3P", NULL, "Internal Mic"}, 202 }; 203 204 static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { 205 {"ssp2 Tx", NULL, "codec_out0"}, 206 {"ssp2 Tx", NULL, "codec_out1"}, 207 {"codec_in0", NULL, "ssp2 Rx"}, 208 {"codec_in1", NULL, "ssp2 Rx"}, 209 210 {"AIF1 Playback", NULL, "ssp2 Tx"}, 211 {"ssp2 Rx", NULL, "AIF1 Capture"}, 212 }; 213 214 static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { 215 {"ssp2 Tx", NULL, "codec_out0"}, 216 {"ssp2 Tx", NULL, "codec_out1"}, 217 {"codec_in0", NULL, "ssp2 Rx"}, 218 {"codec_in1", NULL, "ssp2 Rx"}, 219 220 {"AIF2 Playback", NULL, "ssp2 Tx"}, 221 {"ssp2 Rx", NULL, "AIF2 Capture"}, 222 }; 223 224 static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = { 225 {"ssp0 Tx", NULL, "modem_out"}, 226 {"modem_in", NULL, "ssp0 Rx"}, 227 228 {"AIF1 Playback", NULL, "ssp0 Tx"}, 229 {"ssp0 Rx", NULL, "AIF1 Capture"}, 230 }; 231 232 static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { 233 {"ssp0 Tx", NULL, "modem_out"}, 234 {"modem_in", NULL, "ssp0 Rx"}, 235 236 {"AIF2 Playback", NULL, "ssp0 Tx"}, 237 {"ssp0 Rx", NULL, "AIF2 Capture"}, 238 }; 239 240 static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { 241 {"Speaker", NULL, "SPOLP"}, 242 {"Speaker", NULL, "SPOLN"}, 243 {"Speaker", NULL, "SPORP"}, 244 {"Speaker", NULL, "SPORN"}, 245 }; 246 247 static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { 248 {"Speaker", NULL, "SPOLP"}, 249 {"Speaker", NULL, "SPOLN"}, 250 }; 251 252 static const struct snd_kcontrol_new byt_rt5640_controls[] = { 253 SOC_DAPM_PIN_SWITCH("Headphone"), 254 SOC_DAPM_PIN_SWITCH("Headset Mic"), 255 SOC_DAPM_PIN_SWITCH("Internal Mic"), 256 SOC_DAPM_PIN_SWITCH("Speaker"), 257 }; 258 259 static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, 260 struct snd_pcm_hw_params *params) 261 { 262 struct snd_soc_pcm_runtime *rtd = substream->private_data; 263 struct snd_soc_dai *codec_dai = rtd->codec_dai; 264 int ret; 265 266 ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, 267 params_rate(params) * 512, 268 SND_SOC_CLOCK_IN); 269 270 if (ret < 0) { 271 dev_err(rtd->dev, "can't set codec clock %d\n", ret); 272 return ret; 273 } 274 275 if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) { 276 /* use bitclock as PLL input */ 277 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 278 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 279 280 /* 2x16 bit slots on SSP0 */ 281 ret = snd_soc_dai_set_pll(codec_dai, 0, 282 RT5640_PLL1_S_BCLK1, 283 params_rate(params) * 32, 284 params_rate(params) * 512); 285 } else { 286 /* 2x15 bit slots on SSP2 */ 287 ret = snd_soc_dai_set_pll(codec_dai, 0, 288 RT5640_PLL1_S_BCLK1, 289 params_rate(params) * 50, 290 params_rate(params) * 512); 291 } 292 } else { 293 if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { 294 ret = snd_soc_dai_set_pll(codec_dai, 0, 295 RT5640_PLL1_S_MCLK, 296 25000000, 297 params_rate(params) * 512); 298 } else { 299 ret = snd_soc_dai_set_pll(codec_dai, 0, 300 RT5640_PLL1_S_MCLK, 301 19200000, 302 params_rate(params) * 512); 303 } 304 } 305 306 if (ret < 0) { 307 dev_err(rtd->dev, "can't set codec pll: %d\n", ret); 308 return ret; 309 } 310 311 return 0; 312 } 313 314 static int byt_rt5640_quirk_cb(const struct dmi_system_id *id) 315 { 316 byt_rt5640_quirk = (unsigned long)id->driver_data; 317 return 1; 318 } 319 320 static const struct dmi_system_id byt_rt5640_quirk_table[] = { 321 { 322 .callback = byt_rt5640_quirk_cb, 323 .matches = { 324 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 325 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), 326 }, 327 .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | 328 BYT_RT5640_MCLK_EN), 329 }, 330 { 331 .callback = byt_rt5640_quirk_cb, 332 .matches = { 333 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 334 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), 335 }, 336 .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | 337 BYT_RT5640_MONO_SPEAKER | 338 BYT_RT5640_DIFF_MIC | 339 BYT_RT5640_SSP0_AIF2 | 340 BYT_RT5640_MCLK_EN 341 ), 342 }, 343 { 344 .callback = byt_rt5640_quirk_cb, 345 .matches = { 346 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "DellInc."), 347 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), 348 }, 349 .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP | 350 BYT_RT5640_DMIC_EN | 351 BYT_RT5640_MCLK_EN), 352 }, 353 { 354 .callback = byt_rt5640_quirk_cb, 355 .matches = { 356 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 357 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), 358 }, 359 .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | 360 BYT_RT5640_MCLK_EN), 361 }, 362 { 363 .callback = byt_rt5640_quirk_cb, 364 .matches = { 365 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), 366 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), 367 }, 368 .driver_data = (unsigned long *)(BYT_RT5640_DMIC1_MAP | 369 BYT_RT5640_DMIC_EN), 370 }, 371 { 372 .callback = byt_rt5640_quirk_cb, 373 .matches = { 374 DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), 375 DMI_MATCH(DMI_BOARD_NAME, "tPAD"), 376 }, 377 .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP | 378 BYT_RT5640_MCLK_EN | 379 BYT_RT5640_SSP0_AIF1), 380 }, 381 { 382 .callback = byt_rt5640_quirk_cb, 383 .matches = { 384 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 385 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), 386 }, 387 .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | 388 BYT_RT5640_MCLK_EN | 389 BYT_RT5640_SSP0_AIF1), 390 391 }, 392 {} 393 }; 394 395 static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) 396 { 397 int ret; 398 struct snd_soc_codec *codec = runtime->codec; 399 struct snd_soc_card *card = runtime->card; 400 const struct snd_soc_dapm_route *custom_map; 401 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 402 int num_routes; 403 404 card->dapm.idle_bias_off = true; 405 406 rt5640_sel_asrc_clk_src(codec, 407 RT5640_DA_STEREO_FILTER | 408 RT5640_DA_MONO_L_FILTER | 409 RT5640_DA_MONO_R_FILTER | 410 RT5640_AD_STEREO_FILTER | 411 RT5640_AD_MONO_L_FILTER | 412 RT5640_AD_MONO_R_FILTER, 413 RT5640_CLK_SEL_ASRC); 414 415 ret = snd_soc_add_card_controls(card, byt_rt5640_controls, 416 ARRAY_SIZE(byt_rt5640_controls)); 417 if (ret) { 418 dev_err(card->dev, "unable to add card controls\n"); 419 return ret; 420 } 421 422 switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { 423 case BYT_RT5640_IN1_MAP: 424 custom_map = byt_rt5640_intmic_in1_map; 425 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); 426 break; 427 case BYT_RT5640_IN3_MAP: 428 custom_map = byt_rt5640_intmic_in3_map; 429 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); 430 break; 431 case BYT_RT5640_DMIC2_MAP: 432 custom_map = byt_rt5640_intmic_dmic2_map; 433 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); 434 break; 435 default: 436 custom_map = byt_rt5640_intmic_dmic1_map; 437 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); 438 } 439 440 ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); 441 if (ret) 442 return ret; 443 444 if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { 445 ret = snd_soc_dapm_add_routes(&card->dapm, 446 byt_rt5640_ssp2_aif2_map, 447 ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); 448 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { 449 ret = snd_soc_dapm_add_routes(&card->dapm, 450 byt_rt5640_ssp0_aif1_map, 451 ARRAY_SIZE(byt_rt5640_ssp0_aif1_map)); 452 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { 453 ret = snd_soc_dapm_add_routes(&card->dapm, 454 byt_rt5640_ssp0_aif2_map, 455 ARRAY_SIZE(byt_rt5640_ssp0_aif2_map)); 456 } else { 457 ret = snd_soc_dapm_add_routes(&card->dapm, 458 byt_rt5640_ssp2_aif1_map, 459 ARRAY_SIZE(byt_rt5640_ssp2_aif1_map)); 460 } 461 if (ret) 462 return ret; 463 464 if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { 465 ret = snd_soc_dapm_add_routes(&card->dapm, 466 byt_rt5640_mono_spk_map, 467 ARRAY_SIZE(byt_rt5640_mono_spk_map)); 468 } else { 469 ret = snd_soc_dapm_add_routes(&card->dapm, 470 byt_rt5640_stereo_spk_map, 471 ARRAY_SIZE(byt_rt5640_stereo_spk_map)); 472 } 473 if (ret) 474 return ret; 475 476 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) { 477 snd_soc_update_bits(codec, RT5640_IN1_IN2, RT5640_IN_DF1, 478 RT5640_IN_DF1); 479 } 480 481 if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) { 482 ret = rt5640_dmic_enable(codec, 0, 0); 483 if (ret) 484 return ret; 485 } 486 487 snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); 488 snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); 489 490 if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) { 491 /* 492 * The firmware might enable the clock at 493 * boot (this information may or may not 494 * be reflected in the enable clock register). 495 * To change the rate we must disable the clock 496 * first to cover these cases. Due to common 497 * clock framework restrictions that do not allow 498 * to disable a clock that has not been enabled, 499 * we need to enable the clock first. 500 */ 501 ret = clk_prepare_enable(priv->mclk); 502 if (!ret) 503 clk_disable_unprepare(priv->mclk); 504 505 if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) 506 ret = clk_set_rate(priv->mclk, 25000000); 507 else 508 ret = clk_set_rate(priv->mclk, 19200000); 509 510 if (ret) 511 dev_err(card->dev, "unable to set MCLK rate\n"); 512 } 513 514 return ret; 515 } 516 517 static const struct snd_soc_pcm_stream byt_rt5640_dai_params = { 518 .formats = SNDRV_PCM_FMTBIT_S24_LE, 519 .rate_min = 48000, 520 .rate_max = 48000, 521 .channels_min = 2, 522 .channels_max = 2, 523 }; 524 525 static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, 526 struct snd_pcm_hw_params *params) 527 { 528 struct snd_interval *rate = hw_param_interval(params, 529 SNDRV_PCM_HW_PARAM_RATE); 530 struct snd_interval *channels = hw_param_interval(params, 531 SNDRV_PCM_HW_PARAM_CHANNELS); 532 int ret; 533 534 /* The DSP will covert the FE rate to 48k, stereo */ 535 rate->min = rate->max = 48000; 536 channels->min = channels->max = 2; 537 538 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 539 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 540 541 /* set SSP0 to 16-bit */ 542 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); 543 544 /* 545 * Default mode for SSP configuration is TDM 4 slot, override config 546 * with explicit setting to I2S 2ch 16-bit. The word length is set with 547 * dai_set_tdm_slot() since there is no other API exposed 548 */ 549 ret = snd_soc_dai_set_fmt(rtd->cpu_dai, 550 SND_SOC_DAIFMT_I2S | 551 SND_SOC_DAIFMT_NB_IF | 552 SND_SOC_DAIFMT_CBS_CFS 553 ); 554 if (ret < 0) { 555 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); 556 return ret; 557 } 558 559 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); 560 if (ret < 0) { 561 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); 562 return ret; 563 } 564 565 } else { 566 567 /* set SSP2 to 24-bit */ 568 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); 569 570 /* 571 * Default mode for SSP configuration is TDM 4 slot, override config 572 * with explicit setting to I2S 2ch 24-bit. The word length is set with 573 * dai_set_tdm_slot() since there is no other API exposed 574 */ 575 ret = snd_soc_dai_set_fmt(rtd->cpu_dai, 576 SND_SOC_DAIFMT_I2S | 577 SND_SOC_DAIFMT_NB_IF | 578 SND_SOC_DAIFMT_CBS_CFS 579 ); 580 if (ret < 0) { 581 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); 582 return ret; 583 } 584 585 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); 586 if (ret < 0) { 587 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); 588 return ret; 589 } 590 } 591 return 0; 592 } 593 594 static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream) 595 { 596 return snd_pcm_hw_constraint_single(substream->runtime, 597 SNDRV_PCM_HW_PARAM_RATE, 48000); 598 } 599 600 static struct snd_soc_ops byt_rt5640_aif1_ops = { 601 .startup = byt_rt5640_aif1_startup, 602 }; 603 604 static struct snd_soc_ops byt_rt5640_be_ssp2_ops = { 605 .hw_params = byt_rt5640_aif1_hw_params, 606 }; 607 608 static struct snd_soc_dai_link byt_rt5640_dais[] = { 609 [MERR_DPCM_AUDIO] = { 610 .name = "Baytrail Audio Port", 611 .stream_name = "Baytrail Audio", 612 .cpu_dai_name = "media-cpu-dai", 613 .codec_dai_name = "snd-soc-dummy-dai", 614 .codec_name = "snd-soc-dummy", 615 .platform_name = "sst-mfld-platform", 616 .ignore_suspend = 1, 617 .dynamic = 1, 618 .dpcm_playback = 1, 619 .dpcm_capture = 1, 620 .ops = &byt_rt5640_aif1_ops, 621 }, 622 [MERR_DPCM_DEEP_BUFFER] = { 623 .name = "Deep-Buffer Audio Port", 624 .stream_name = "Deep-Buffer Audio", 625 .cpu_dai_name = "deepbuffer-cpu-dai", 626 .codec_dai_name = "snd-soc-dummy-dai", 627 .codec_name = "snd-soc-dummy", 628 .platform_name = "sst-mfld-platform", 629 .ignore_suspend = 1, 630 .nonatomic = true, 631 .dynamic = 1, 632 .dpcm_playback = 1, 633 .ops = &byt_rt5640_aif1_ops, 634 }, 635 [MERR_DPCM_COMPR] = { 636 .name = "Baytrail Compressed Port", 637 .stream_name = "Baytrail Compress", 638 .cpu_dai_name = "compress-cpu-dai", 639 .codec_dai_name = "snd-soc-dummy-dai", 640 .codec_name = "snd-soc-dummy", 641 .platform_name = "sst-mfld-platform", 642 }, 643 /* back ends */ 644 { 645 .name = "SSP2-Codec", 646 .id = 1, 647 .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ 648 .platform_name = "sst-mfld-platform", 649 .no_pcm = 1, 650 .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ 651 .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ 652 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 653 | SND_SOC_DAIFMT_CBS_CFS, 654 .be_hw_params_fixup = byt_rt5640_codec_fixup, 655 .ignore_suspend = 1, 656 .dpcm_playback = 1, 657 .dpcm_capture = 1, 658 .init = byt_rt5640_init, 659 .ops = &byt_rt5640_be_ssp2_ops, 660 }, 661 }; 662 663 /* SoC card */ 664 static struct snd_soc_card byt_rt5640_card = { 665 .name = "bytcr-rt5640", 666 .owner = THIS_MODULE, 667 .dai_link = byt_rt5640_dais, 668 .num_links = ARRAY_SIZE(byt_rt5640_dais), 669 .dapm_widgets = byt_rt5640_widgets, 670 .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), 671 .dapm_routes = byt_rt5640_audio_map, 672 .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), 673 .fully_routed = true, 674 }; 675 676 static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ 677 static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ 678 static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ 679 680 static bool is_valleyview(void) 681 { 682 static const struct x86_cpu_id cpu_ids[] = { 683 { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ 684 {} 685 }; 686 687 if (!x86_match_cpu(cpu_ids)) 688 return false; 689 return true; 690 } 691 692 693 static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) 694 { 695 int ret_val = 0; 696 struct sst_acpi_mach *mach; 697 const char *i2c_name = NULL; 698 int i; 699 int dai_index; 700 struct byt_rt5640_private *priv; 701 702 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); 703 if (!priv) 704 return -ENOMEM; 705 706 /* register the soc card */ 707 byt_rt5640_card.dev = &pdev->dev; 708 mach = byt_rt5640_card.dev->platform_data; 709 snd_soc_card_set_drvdata(&byt_rt5640_card, priv); 710 711 /* fix index of codec dai */ 712 dai_index = MERR_DPCM_COMPR + 1; 713 for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { 714 if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) { 715 dai_index = i; 716 break; 717 } 718 } 719 720 /* fixup codec name based on HID */ 721 i2c_name = sst_acpi_find_name_from_hid(mach->id); 722 if (i2c_name != NULL) { 723 snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), 724 "%s%s", "i2c-", i2c_name); 725 726 byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name; 727 } 728 729 /* 730 * swap SSP0 if bytcr is detected 731 * (will be overridden if DMI quirk is detected) 732 */ 733 if (is_valleyview()) { 734 struct sst_platform_info *p_info = mach->pdata; 735 const struct sst_res_info *res_info = p_info->res_info; 736 737 /* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */ 738 if (res_info->acpi_ipc_irq_index == 0) { 739 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; 740 } 741 } 742 743 /* check quirks before creating card */ 744 dmi_check_system(byt_rt5640_quirk_table); 745 log_quirks(&pdev->dev); 746 747 if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || 748 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 749 750 /* fixup codec aif name */ 751 snprintf(byt_rt5640_codec_aif_name, 752 sizeof(byt_rt5640_codec_aif_name), 753 "%s", "rt5640-aif2"); 754 755 byt_rt5640_dais[dai_index].codec_dai_name = 756 byt_rt5640_codec_aif_name; 757 } 758 759 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 760 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 761 762 /* fixup cpu dai name name */ 763 snprintf(byt_rt5640_cpu_dai_name, 764 sizeof(byt_rt5640_cpu_dai_name), 765 "%s", "ssp0-port"); 766 767 byt_rt5640_dais[dai_index].cpu_dai_name = 768 byt_rt5640_cpu_dai_name; 769 } 770 771 if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && (is_valleyview())) { 772 priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); 773 if (IS_ERR(priv->mclk)) { 774 dev_err(&pdev->dev, 775 "Failed to get MCLK from pmc_plt_clk_3: %ld\n", 776 PTR_ERR(priv->mclk)); 777 return PTR_ERR(priv->mclk); 778 } 779 } 780 781 ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); 782 783 if (ret_val) { 784 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", 785 ret_val); 786 return ret_val; 787 } 788 platform_set_drvdata(pdev, &byt_rt5640_card); 789 return ret_val; 790 } 791 792 static struct platform_driver snd_byt_rt5640_mc_driver = { 793 .driver = { 794 .name = "bytcr_rt5640", 795 .pm = &snd_soc_pm_ops, 796 }, 797 .probe = snd_byt_rt5640_mc_probe, 798 }; 799 800 module_platform_driver(snd_byt_rt5640_mc_driver); 801 802 MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); 803 MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); 804 MODULE_LICENSE("GPL v2"); 805 MODULE_ALIAS("platform:bytcr_rt5640"); 806