1 /* 2 * Intel Broxton-P I2S Machine Driver 3 * 4 * Copyright (C) 2014-2016, Intel Corporation. All rights reserved. 5 * 6 * Modified from: 7 * Intel Skylake I2S Machine driver 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License version 11 * 2 as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <sound/core.h> 22 #include <sound/pcm.h> 23 #include <sound/soc.h> 24 #include <sound/jack.h> 25 #include <sound/pcm_params.h> 26 #include "../../codecs/hdac_hdmi.h" 27 #include "../../codecs/rt298.h" 28 29 /* Headset jack detection DAPM pins */ 30 static struct snd_soc_jack broxton_headset; 31 static struct snd_soc_jack broxton_hdmi[3]; 32 33 struct bxt_hdmi_pcm { 34 struct list_head head; 35 struct snd_soc_dai *codec_dai; 36 int device; 37 }; 38 39 struct bxt_rt286_private { 40 struct list_head hdmi_pcm_list; 41 }; 42 43 enum { 44 BXT_DPCM_AUDIO_PB = 0, 45 BXT_DPCM_AUDIO_CP, 46 BXT_DPCM_AUDIO_REF_CP, 47 BXT_DPCM_AUDIO_DMIC_CP, 48 BXT_DPCM_AUDIO_HDMI1_PB, 49 BXT_DPCM_AUDIO_HDMI2_PB, 50 BXT_DPCM_AUDIO_HDMI3_PB, 51 }; 52 53 static struct snd_soc_jack_pin broxton_headset_pins[] = { 54 { 55 .pin = "Mic Jack", 56 .mask = SND_JACK_MICROPHONE, 57 }, 58 { 59 .pin = "Headphone Jack", 60 .mask = SND_JACK_HEADPHONE, 61 }, 62 }; 63 64 static const struct snd_kcontrol_new broxton_controls[] = { 65 SOC_DAPM_PIN_SWITCH("Speaker"), 66 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 67 SOC_DAPM_PIN_SWITCH("Mic Jack"), 68 }; 69 70 static const struct snd_soc_dapm_widget broxton_widgets[] = { 71 SND_SOC_DAPM_HP("Headphone Jack", NULL), 72 SND_SOC_DAPM_SPK("Speaker", NULL), 73 SND_SOC_DAPM_MIC("Mic Jack", NULL), 74 SND_SOC_DAPM_MIC("DMIC2", NULL), 75 SND_SOC_DAPM_MIC("SoC DMIC", NULL), 76 SND_SOC_DAPM_SPK("HDMI1", NULL), 77 SND_SOC_DAPM_SPK("HDMI2", NULL), 78 SND_SOC_DAPM_SPK("HDMI3", NULL), 79 }; 80 81 static const struct snd_soc_dapm_route broxton_rt298_map[] = { 82 /* speaker */ 83 {"Speaker", NULL, "SPOR"}, 84 {"Speaker", NULL, "SPOL"}, 85 86 /* HP jack connectors - unknown if we have jack detect */ 87 {"Headphone Jack", NULL, "HPO Pin"}, 88 89 /* other jacks */ 90 {"MIC1", NULL, "Mic Jack"}, 91 92 /* digital mics */ 93 {"DMIC1 Pin", NULL, "DMIC2"}, 94 {"DMic", NULL, "SoC DMIC"}, 95 96 {"HDMI1", NULL, "hif5-0 Output"}, 97 {"HDMI2", NULL, "hif6-0 Output"}, 98 {"HDMI2", NULL, "hif7-0 Output"}, 99 100 /* CODEC BE connections */ 101 { "AIF1 Playback", NULL, "ssp5 Tx"}, 102 { "ssp5 Tx", NULL, "codec0_out"}, 103 { "ssp5 Tx", NULL, "codec1_out"}, 104 105 { "codec0_in", NULL, "ssp5 Rx" }, 106 { "ssp5 Rx", NULL, "AIF1 Capture" }, 107 108 { "dmic01_hifi", NULL, "DMIC01 Rx" }, 109 { "DMIC01 Rx", NULL, "Capture" }, 110 111 { "hifi3", NULL, "iDisp3 Tx"}, 112 { "iDisp3 Tx", NULL, "iDisp3_out"}, 113 { "hifi2", NULL, "iDisp2 Tx"}, 114 { "iDisp2 Tx", NULL, "iDisp2_out"}, 115 { "hifi1", NULL, "iDisp1 Tx"}, 116 { "iDisp1 Tx", NULL, "iDisp1_out"}, 117 }; 118 119 static const struct snd_soc_dapm_route geminilake_rt298_map[] = { 120 /* speaker */ 121 {"Speaker", NULL, "SPOR"}, 122 {"Speaker", NULL, "SPOL"}, 123 124 /* HP jack connectors - unknown if we have jack detect */ 125 {"Headphone Jack", NULL, "HPO Pin"}, 126 127 /* other jacks */ 128 {"MIC1", NULL, "Mic Jack"}, 129 130 /* digital mics */ 131 {"DMIC1 Pin", NULL, "DMIC2"}, 132 {"DMic", NULL, "SoC DMIC"}, 133 134 {"HDMI1", NULL, "hif5-0 Output"}, 135 {"HDMI2", NULL, "hif6-0 Output"}, 136 {"HDMI2", NULL, "hif7-0 Output"}, 137 138 /* CODEC BE connections */ 139 { "AIF1 Playback", NULL, "ssp2 Tx"}, 140 { "ssp2 Tx", NULL, "codec0_out"}, 141 { "ssp2 Tx", NULL, "codec1_out"}, 142 143 { "codec0_in", NULL, "ssp2 Rx" }, 144 { "ssp2 Rx", NULL, "AIF1 Capture" }, 145 146 { "dmic01_hifi", NULL, "DMIC01 Rx" }, 147 { "DMIC01 Rx", NULL, "Capture" }, 148 149 { "hifi3", NULL, "iDisp3 Tx"}, 150 { "iDisp3 Tx", NULL, "iDisp3_out"}, 151 { "hifi2", NULL, "iDisp2 Tx"}, 152 { "iDisp2 Tx", NULL, "iDisp2_out"}, 153 { "hifi1", NULL, "iDisp1 Tx"}, 154 { "iDisp1 Tx", NULL, "iDisp1_out"}, 155 }; 156 157 static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) 158 { 159 struct snd_soc_dapm_context *dapm; 160 struct snd_soc_component *component = rtd->cpu_dai->component; 161 162 dapm = snd_soc_component_get_dapm(component); 163 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); 164 165 return 0; 166 } 167 168 static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) 169 { 170 struct snd_soc_codec *codec = rtd->codec; 171 int ret = 0; 172 173 ret = snd_soc_card_jack_new(rtd->card, "Headset", 174 SND_JACK_HEADSET | SND_JACK_BTN_0, 175 &broxton_headset, 176 broxton_headset_pins, ARRAY_SIZE(broxton_headset_pins)); 177 178 if (ret) 179 return ret; 180 181 rt298_mic_detect(codec, &broxton_headset); 182 183 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); 184 185 return 0; 186 } 187 188 static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) 189 { 190 struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); 191 struct snd_soc_dai *dai = rtd->codec_dai; 192 struct bxt_hdmi_pcm *pcm; 193 194 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 195 if (!pcm) 196 return -ENOMEM; 197 198 pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; 199 pcm->codec_dai = dai; 200 201 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 202 203 return 0; 204 } 205 206 static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, 207 struct snd_pcm_hw_params *params) 208 { 209 struct snd_interval *rate = hw_param_interval(params, 210 SNDRV_PCM_HW_PARAM_RATE); 211 struct snd_interval *channels = hw_param_interval(params, 212 SNDRV_PCM_HW_PARAM_CHANNELS); 213 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 214 215 /* The ADSP will covert the FE rate to 48k, stereo */ 216 rate->min = rate->max = 48000; 217 channels->min = channels->max = 2; 218 219 /* set SSP5 to 24 bit */ 220 snd_mask_none(fmt); 221 snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); 222 223 return 0; 224 } 225 226 static int broxton_rt298_hw_params(struct snd_pcm_substream *substream, 227 struct snd_pcm_hw_params *params) 228 { 229 struct snd_soc_pcm_runtime *rtd = substream->private_data; 230 struct snd_soc_dai *codec_dai = rtd->codec_dai; 231 int ret; 232 233 ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, 234 19200000, SND_SOC_CLOCK_IN); 235 if (ret < 0) { 236 dev_err(rtd->dev, "can't set codec sysclk configuration\n"); 237 return ret; 238 } 239 240 return ret; 241 } 242 243 static const struct snd_soc_ops broxton_rt298_ops = { 244 .hw_params = broxton_rt298_hw_params, 245 }; 246 247 static const unsigned int rates[] = { 248 48000, 249 }; 250 251 static const struct snd_pcm_hw_constraint_list constraints_rates = { 252 .count = ARRAY_SIZE(rates), 253 .list = rates, 254 .mask = 0, 255 }; 256 257 static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, 258 struct snd_pcm_hw_params *params) 259 { 260 struct snd_interval *channels = hw_param_interval(params, 261 SNDRV_PCM_HW_PARAM_CHANNELS); 262 channels->min = channels->max = 4; 263 264 return 0; 265 } 266 267 static const unsigned int channels_dmic[] = { 268 1, 2, 3, 4, 269 }; 270 271 static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { 272 .count = ARRAY_SIZE(channels_dmic), 273 .list = channels_dmic, 274 .mask = 0, 275 }; 276 277 static int broxton_dmic_startup(struct snd_pcm_substream *substream) 278 { 279 struct snd_pcm_runtime *runtime = substream->runtime; 280 281 runtime->hw.channels_max = 4; 282 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 283 &constraints_dmic_channels); 284 285 return snd_pcm_hw_constraint_list(substream->runtime, 0, 286 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 287 } 288 289 static const struct snd_soc_ops broxton_dmic_ops = { 290 .startup = broxton_dmic_startup, 291 }; 292 293 static const unsigned int channels[] = { 294 2, 295 }; 296 297 static const struct snd_pcm_hw_constraint_list constraints_channels = { 298 .count = ARRAY_SIZE(channels), 299 .list = channels, 300 .mask = 0, 301 }; 302 303 static int bxt_fe_startup(struct snd_pcm_substream *substream) 304 { 305 struct snd_pcm_runtime *runtime = substream->runtime; 306 307 /* 308 * on this platform for PCM device we support: 309 * 48Khz 310 * stereo 311 * 16-bit audio 312 */ 313 314 runtime->hw.channels_max = 2; 315 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 316 &constraints_channels); 317 318 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 319 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 320 snd_pcm_hw_constraint_list(runtime, 0, 321 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 322 323 return 0; 324 } 325 326 static const struct snd_soc_ops broxton_rt286_fe_ops = { 327 .startup = bxt_fe_startup, 328 }; 329 330 /* broxton digital audio interface glue - connects codec <--> CPU */ 331 static struct snd_soc_dai_link broxton_rt298_dais[] = { 332 /* Front End DAI links */ 333 [BXT_DPCM_AUDIO_PB] = 334 { 335 .name = "Bxt Audio Port", 336 .stream_name = "Audio", 337 .cpu_dai_name = "System Pin", 338 .platform_name = "0000:00:0e.0", 339 .nonatomic = 1, 340 .dynamic = 1, 341 .codec_name = "snd-soc-dummy", 342 .codec_dai_name = "snd-soc-dummy-dai", 343 .init = broxton_rt298_fe_init, 344 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 345 .dpcm_playback = 1, 346 .ops = &broxton_rt286_fe_ops, 347 }, 348 [BXT_DPCM_AUDIO_CP] = 349 { 350 .name = "Bxt Audio Capture Port", 351 .stream_name = "Audio Record", 352 .cpu_dai_name = "System Pin", 353 .platform_name = "0000:00:0e.0", 354 .nonatomic = 1, 355 .dynamic = 1, 356 .codec_name = "snd-soc-dummy", 357 .codec_dai_name = "snd-soc-dummy-dai", 358 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 359 .dpcm_capture = 1, 360 .ops = &broxton_rt286_fe_ops, 361 }, 362 [BXT_DPCM_AUDIO_REF_CP] = 363 { 364 .name = "Bxt Audio Reference cap", 365 .stream_name = "refcap", 366 .cpu_dai_name = "Reference Pin", 367 .codec_name = "snd-soc-dummy", 368 .codec_dai_name = "snd-soc-dummy-dai", 369 .platform_name = "0000:00:0e.0", 370 .init = NULL, 371 .dpcm_capture = 1, 372 .nonatomic = 1, 373 .dynamic = 1, 374 }, 375 [BXT_DPCM_AUDIO_DMIC_CP] = 376 { 377 .name = "Bxt Audio DMIC cap", 378 .stream_name = "dmiccap", 379 .cpu_dai_name = "DMIC Pin", 380 .codec_name = "snd-soc-dummy", 381 .codec_dai_name = "snd-soc-dummy-dai", 382 .platform_name = "0000:00:0e.0", 383 .init = NULL, 384 .dpcm_capture = 1, 385 .nonatomic = 1, 386 .dynamic = 1, 387 .ops = &broxton_dmic_ops, 388 }, 389 [BXT_DPCM_AUDIO_HDMI1_PB] = 390 { 391 .name = "Bxt HDMI Port1", 392 .stream_name = "Hdmi1", 393 .cpu_dai_name = "HDMI1 Pin", 394 .codec_name = "snd-soc-dummy", 395 .codec_dai_name = "snd-soc-dummy-dai", 396 .platform_name = "0000:00:0e.0", 397 .dpcm_playback = 1, 398 .init = NULL, 399 .nonatomic = 1, 400 .dynamic = 1, 401 }, 402 [BXT_DPCM_AUDIO_HDMI2_PB] = 403 { 404 .name = "Bxt HDMI Port2", 405 .stream_name = "Hdmi2", 406 .cpu_dai_name = "HDMI2 Pin", 407 .codec_name = "snd-soc-dummy", 408 .codec_dai_name = "snd-soc-dummy-dai", 409 .platform_name = "0000:00:0e.0", 410 .dpcm_playback = 1, 411 .init = NULL, 412 .nonatomic = 1, 413 .dynamic = 1, 414 }, 415 [BXT_DPCM_AUDIO_HDMI3_PB] = 416 { 417 .name = "Bxt HDMI Port3", 418 .stream_name = "Hdmi3", 419 .cpu_dai_name = "HDMI3 Pin", 420 .codec_name = "snd-soc-dummy", 421 .codec_dai_name = "snd-soc-dummy-dai", 422 .platform_name = "0000:00:0e.0", 423 .dpcm_playback = 1, 424 .init = NULL, 425 .nonatomic = 1, 426 .dynamic = 1, 427 }, 428 /* Back End DAI links */ 429 { 430 /* SSP5 - Codec */ 431 .name = "SSP5-Codec", 432 .id = 0, 433 .cpu_dai_name = "SSP5 Pin", 434 .platform_name = "0000:00:0e.0", 435 .no_pcm = 1, 436 .codec_name = "i2c-INT343A:00", 437 .codec_dai_name = "rt298-aif1", 438 .init = broxton_rt298_codec_init, 439 .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | 440 SND_SOC_DAIFMT_CBS_CFS, 441 .ignore_pmdown_time = 1, 442 .be_hw_params_fixup = broxton_ssp5_fixup, 443 .ops = &broxton_rt298_ops, 444 .dpcm_playback = 1, 445 .dpcm_capture = 1, 446 }, 447 { 448 .name = "dmic01", 449 .id = 1, 450 .cpu_dai_name = "DMIC01 Pin", 451 .codec_name = "dmic-codec", 452 .codec_dai_name = "dmic-hifi", 453 .platform_name = "0000:00:0e.0", 454 .be_hw_params_fixup = broxton_dmic_fixup, 455 .ignore_suspend = 1, 456 .dpcm_capture = 1, 457 .no_pcm = 1, 458 }, 459 { 460 .name = "iDisp1", 461 .id = 3, 462 .cpu_dai_name = "iDisp1 Pin", 463 .codec_name = "ehdaudio0D2", 464 .codec_dai_name = "intel-hdmi-hifi1", 465 .platform_name = "0000:00:0e.0", 466 .init = broxton_hdmi_init, 467 .dpcm_playback = 1, 468 .no_pcm = 1, 469 }, 470 { 471 .name = "iDisp2", 472 .id = 4, 473 .cpu_dai_name = "iDisp2 Pin", 474 .codec_name = "ehdaudio0D2", 475 .codec_dai_name = "intel-hdmi-hifi2", 476 .platform_name = "0000:00:0e.0", 477 .init = broxton_hdmi_init, 478 .dpcm_playback = 1, 479 .no_pcm = 1, 480 }, 481 { 482 .name = "iDisp3", 483 .id = 5, 484 .cpu_dai_name = "iDisp3 Pin", 485 .codec_name = "ehdaudio0D2", 486 .codec_dai_name = "intel-hdmi-hifi3", 487 .platform_name = "0000:00:0e.0", 488 .init = broxton_hdmi_init, 489 .dpcm_playback = 1, 490 .no_pcm = 1, 491 }, 492 }; 493 494 #define NAME_SIZE 32 495 static int bxt_card_late_probe(struct snd_soc_card *card) 496 { 497 struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card); 498 struct bxt_hdmi_pcm *pcm; 499 struct snd_soc_codec *codec = NULL; 500 int err, i = 0; 501 char jack_name[NAME_SIZE]; 502 503 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 504 codec = pcm->codec_dai->codec; 505 snprintf(jack_name, sizeof(jack_name), 506 "HDMI/DP, pcm=%d Jack", pcm->device); 507 err = snd_soc_card_jack_new(card, jack_name, 508 SND_JACK_AVOUT, &broxton_hdmi[i], 509 NULL, 0); 510 511 if (err) 512 return err; 513 514 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, 515 &broxton_hdmi[i]); 516 if (err < 0) 517 return err; 518 519 i++; 520 } 521 522 if (!codec) 523 return -EINVAL; 524 525 return hdac_hdmi_jack_port_init(codec, &card->dapm); 526 } 527 528 529 /* broxton audio machine driver for SPT + RT298S */ 530 static struct snd_soc_card broxton_rt298 = { 531 .name = "broxton-rt298", 532 .dai_link = broxton_rt298_dais, 533 .num_links = ARRAY_SIZE(broxton_rt298_dais), 534 .controls = broxton_controls, 535 .num_controls = ARRAY_SIZE(broxton_controls), 536 .dapm_widgets = broxton_widgets, 537 .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), 538 .dapm_routes = broxton_rt298_map, 539 .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), 540 .fully_routed = true, 541 .late_probe = bxt_card_late_probe, 542 543 }; 544 545 static struct snd_soc_card geminilake_rt298 = { 546 .name = "geminilake-rt298", 547 .dai_link = broxton_rt298_dais, 548 .num_links = ARRAY_SIZE(broxton_rt298_dais), 549 .controls = broxton_controls, 550 .num_controls = ARRAY_SIZE(broxton_controls), 551 .dapm_widgets = broxton_widgets, 552 .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), 553 .dapm_routes = geminilake_rt298_map, 554 .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map), 555 .fully_routed = true, 556 .late_probe = bxt_card_late_probe, 557 }; 558 559 static int broxton_audio_probe(struct platform_device *pdev) 560 { 561 struct bxt_rt286_private *ctx; 562 struct snd_soc_card *card = 563 (struct snd_soc_card *)pdev->id_entry->driver_data; 564 int i; 565 566 for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) { 567 if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00", 568 I2C_NAME_SIZE)) { 569 if (!strncmp(card->name, "broxton-rt298", 570 PLATFORM_NAME_SIZE)) { 571 card->dai_link[i].name = "SSP5-Codec"; 572 card->dai_link[i].cpu_dai_name = "SSP5 Pin"; 573 } else if (!strncmp(card->name, "geminilake-rt298", 574 PLATFORM_NAME_SIZE)) { 575 card->dai_link[i].name = "SSP2-Codec"; 576 card->dai_link[i].cpu_dai_name = "SSP2 Pin"; 577 } 578 } 579 } 580 581 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); 582 if (!ctx) 583 return -ENOMEM; 584 585 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 586 587 card->dev = &pdev->dev; 588 snd_soc_card_set_drvdata(card, ctx); 589 590 return devm_snd_soc_register_card(&pdev->dev, card); 591 } 592 593 static const struct platform_device_id bxt_board_ids[] = { 594 { .name = "bxt_alc298s_i2s", .driver_data = 595 (unsigned long)&broxton_rt298 }, 596 { .name = "glk_alc298s_i2s", .driver_data = 597 (unsigned long)&geminilake_rt298 }, 598 {} 599 }; 600 601 static struct platform_driver broxton_audio = { 602 .probe = broxton_audio_probe, 603 .driver = { 604 .name = "bxt_alc298s_i2s", 605 .pm = &snd_soc_pm_ops, 606 }, 607 .id_table = bxt_board_ids, 608 }; 609 module_platform_driver(broxton_audio) 610 611 /* Module information */ 612 MODULE_AUTHOR("Ramesh Babu <Ramesh.Babu@intel.com>"); 613 MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>"); 614 MODULE_DESCRIPTION("Intel SST Audio for Broxton"); 615 MODULE_LICENSE("GPL v2"); 616 MODULE_ALIAS("platform:bxt_alc298s_i2s"); 617 MODULE_ALIAS("platform:glk_alc298s_i2s"); 618