1 /* 2 * Intel Skylake I2S Machine Driver for NAU88L25+SSM4567 3 * 4 * Copyright (C) 2015, Intel Corporation. All rights reserved. 5 * 6 * Modified from: 7 * Intel Skylake I2S Machine Driver for NAU88L25 and SSM4567 8 * 9 * Copyright (C) 2015, Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License version 13 * 2 as published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 #include <sound/core.h> 24 #include <sound/pcm.h> 25 #include <sound/soc.h> 26 #include <sound/jack.h> 27 #include <sound/pcm_params.h> 28 #include "../../codecs/nau8825.h" 29 #include "../../codecs/hdac_hdmi.h" 30 #include "../skylake/skl.h" 31 32 #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" 33 #define SKL_SSM_CODEC_DAI "ssm4567-hifi" 34 #define DMIC_CH(p) p->list[p->count-1] 35 36 static struct snd_soc_jack skylake_headset; 37 static struct snd_soc_card skylake_audio_card; 38 static const struct snd_pcm_hw_constraint_list *dmic_constraints; 39 40 struct skl_hdmi_pcm { 41 struct list_head head; 42 struct snd_soc_dai *codec_dai; 43 int device; 44 }; 45 46 struct skl_nau88125_private { 47 struct list_head hdmi_pcm_list; 48 }; 49 enum { 50 SKL_DPCM_AUDIO_PB = 0, 51 SKL_DPCM_AUDIO_CP, 52 SKL_DPCM_AUDIO_REF_CP, 53 SKL_DPCM_AUDIO_DMIC_CP, 54 SKL_DPCM_AUDIO_HDMI1_PB, 55 SKL_DPCM_AUDIO_HDMI2_PB, 56 SKL_DPCM_AUDIO_HDMI3_PB, 57 }; 58 59 static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card) 60 { 61 struct snd_soc_pcm_runtime *rtd; 62 63 list_for_each_entry(rtd, &card->rtd_list, list) { 64 65 if (!strncmp(rtd->codec_dai->name, SKL_NUVOTON_CODEC_DAI, 66 strlen(SKL_NUVOTON_CODEC_DAI))) 67 return rtd->codec_dai; 68 } 69 70 return NULL; 71 } 72 73 static const struct snd_kcontrol_new skylake_controls[] = { 74 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 75 SOC_DAPM_PIN_SWITCH("Headset Mic"), 76 SOC_DAPM_PIN_SWITCH("Left Speaker"), 77 SOC_DAPM_PIN_SWITCH("Right Speaker"), 78 }; 79 80 static int platform_clock_control(struct snd_soc_dapm_widget *w, 81 struct snd_kcontrol *k, int event) 82 { 83 struct snd_soc_dapm_context *dapm = w->dapm; 84 struct snd_soc_card *card = dapm->card; 85 struct snd_soc_dai *codec_dai; 86 int ret; 87 88 codec_dai = skl_get_codec_dai(card); 89 if (!codec_dai) { 90 dev_err(card->dev, "Codec dai not found\n"); 91 return -EIO; 92 } 93 94 if (SND_SOC_DAPM_EVENT_ON(event)) { 95 ret = snd_soc_dai_set_sysclk(codec_dai, 96 NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); 97 if (ret < 0) { 98 dev_err(card->dev, "set sysclk err = %d\n", ret); 99 return -EIO; 100 } 101 } else { 102 ret = snd_soc_dai_set_sysclk(codec_dai, 103 NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); 104 if (ret < 0) { 105 dev_err(card->dev, "set sysclk err = %d\n", ret); 106 return -EIO; 107 } 108 } 109 return ret; 110 } 111 112 static const struct snd_soc_dapm_widget skylake_widgets[] = { 113 SND_SOC_DAPM_HP("Headphone Jack", NULL), 114 SND_SOC_DAPM_MIC("Headset Mic", NULL), 115 SND_SOC_DAPM_SPK("Left Speaker", NULL), 116 SND_SOC_DAPM_SPK("Right Speaker", NULL), 117 SND_SOC_DAPM_MIC("SoC DMIC", NULL), 118 SND_SOC_DAPM_SPK("DP", NULL), 119 SND_SOC_DAPM_SPK("HDMI", NULL), 120 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 121 platform_clock_control, SND_SOC_DAPM_PRE_PMU | 122 SND_SOC_DAPM_POST_PMD), 123 }; 124 125 static const struct snd_soc_dapm_route skylake_map[] = { 126 /* HP jack connectors - unknown if we have jack detection */ 127 {"Headphone Jack", NULL, "HPOL"}, 128 {"Headphone Jack", NULL, "HPOR"}, 129 130 /* speaker */ 131 {"Left Speaker", NULL, "Left OUT"}, 132 {"Right Speaker", NULL, "Right OUT"}, 133 134 /* other jacks */ 135 {"MIC", NULL, "Headset Mic"}, 136 {"DMic", NULL, "SoC DMIC"}, 137 138 {"HDMI", NULL, "hif5 Output"}, 139 {"DP", NULL, "hif6 Output"}, 140 /* CODEC BE connections */ 141 { "Left Playback", NULL, "ssp0 Tx"}, 142 { "Right Playback", NULL, "ssp0 Tx"}, 143 { "ssp0 Tx", NULL, "codec0_out"}, 144 145 /* IV feedback path */ 146 { "codec0_lp_in", NULL, "ssp0 Rx"}, 147 { "ssp0 Rx", NULL, "Left Capture Sense" }, 148 { "ssp0 Rx", NULL, "Right Capture Sense" }, 149 150 { "Playback", NULL, "ssp1 Tx"}, 151 { "ssp1 Tx", NULL, "codec1_out"}, 152 153 { "codec0_in", NULL, "ssp1 Rx" }, 154 { "ssp1 Rx", NULL, "Capture" }, 155 156 /* DMIC */ 157 { "dmic01_hifi", NULL, "DMIC01 Rx" }, 158 { "DMIC01 Rx", NULL, "DMIC AIF" }, 159 160 { "hifi3", NULL, "iDisp3 Tx"}, 161 { "iDisp3 Tx", NULL, "iDisp3_out"}, 162 { "hifi2", NULL, "iDisp2 Tx"}, 163 { "iDisp2 Tx", NULL, "iDisp2_out"}, 164 { "hifi1", NULL, "iDisp1 Tx"}, 165 { "iDisp1 Tx", NULL, "iDisp1_out"}, 166 167 { "Headphone Jack", NULL, "Platform Clock" }, 168 { "Headset Mic", NULL, "Platform Clock" }, 169 }; 170 171 static struct snd_soc_codec_conf ssm4567_codec_conf[] = { 172 { 173 .dev_name = "i2c-INT343B:00", 174 .name_prefix = "Left", 175 }, 176 { 177 .dev_name = "i2c-INT343B:01", 178 .name_prefix = "Right", 179 }, 180 }; 181 182 static struct snd_soc_dai_link_component ssm4567_codec_components[] = { 183 { /* Left */ 184 .name = "i2c-INT343B:00", 185 .dai_name = SKL_SSM_CODEC_DAI, 186 }, 187 { /* Right */ 188 .name = "i2c-INT343B:01", 189 .dai_name = SKL_SSM_CODEC_DAI, 190 }, 191 }; 192 193 static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) 194 { 195 int ret; 196 197 /* Slot 1 for left */ 198 ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x01, 0x01, 2, 48); 199 if (ret < 0) 200 return ret; 201 202 /* Slot 2 for right */ 203 ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x02, 0x02, 2, 48); 204 if (ret < 0) 205 return ret; 206 207 return ret; 208 } 209 210 static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 211 { 212 int ret; 213 struct snd_soc_codec *codec = rtd->codec; 214 215 /* 216 * 4 buttons here map to the google Reference headset 217 * The use of these buttons can be decided by the user space. 218 */ 219 ret = snd_soc_card_jack_new(&skylake_audio_card, "Headset Jack", 220 SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | 221 SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset, 222 NULL, 0); 223 if (ret) { 224 dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); 225 return ret; 226 } 227 228 nau8825_enable_jack_detect(codec, &skylake_headset); 229 230 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); 231 232 return ret; 233 } 234 235 static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) 236 { 237 struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 238 struct snd_soc_dai *dai = rtd->codec_dai; 239 struct skl_hdmi_pcm *pcm; 240 241 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 242 if (!pcm) 243 return -ENOMEM; 244 245 pcm->device = SKL_DPCM_AUDIO_HDMI1_PB; 246 pcm->codec_dai = dai; 247 248 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 249 250 return 0; 251 } 252 253 static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) 254 { 255 struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 256 struct snd_soc_dai *dai = rtd->codec_dai; 257 struct skl_hdmi_pcm *pcm; 258 259 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 260 if (!pcm) 261 return -ENOMEM; 262 263 pcm->device = SKL_DPCM_AUDIO_HDMI2_PB; 264 pcm->codec_dai = dai; 265 266 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 267 268 return 0; 269 } 270 271 272 static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) 273 { 274 struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 275 struct snd_soc_dai *dai = rtd->codec_dai; 276 struct skl_hdmi_pcm *pcm; 277 278 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 279 if (!pcm) 280 return -ENOMEM; 281 282 pcm->device = SKL_DPCM_AUDIO_HDMI3_PB; 283 pcm->codec_dai = dai; 284 285 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 286 287 return 0; 288 } 289 290 static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) 291 { 292 struct snd_soc_dapm_context *dapm; 293 struct snd_soc_component *component = rtd->cpu_dai->component; 294 295 dapm = snd_soc_component_get_dapm(component); 296 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); 297 298 return 0; 299 } 300 301 static unsigned int rates[] = { 302 48000, 303 }; 304 305 static struct snd_pcm_hw_constraint_list constraints_rates = { 306 .count = ARRAY_SIZE(rates), 307 .list = rates, 308 .mask = 0, 309 }; 310 311 static unsigned int channels[] = { 312 2, 313 }; 314 315 static struct snd_pcm_hw_constraint_list constraints_channels = { 316 .count = ARRAY_SIZE(channels), 317 .list = channels, 318 .mask = 0, 319 }; 320 321 static int skl_fe_startup(struct snd_pcm_substream *substream) 322 { 323 struct snd_pcm_runtime *runtime = substream->runtime; 324 325 /* 326 * on this platform for PCM device we support, 327 * 48Khz 328 * stereo 329 * 16 bit audio 330 */ 331 332 runtime->hw.channels_max = 2; 333 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 334 &constraints_channels); 335 336 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 337 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 338 339 snd_pcm_hw_constraint_list(runtime, 0, 340 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 341 342 return 0; 343 } 344 345 static const struct snd_soc_ops skylake_nau8825_fe_ops = { 346 .startup = skl_fe_startup, 347 }; 348 349 static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, 350 struct snd_pcm_hw_params *params) 351 { 352 struct snd_interval *rate = hw_param_interval(params, 353 SNDRV_PCM_HW_PARAM_RATE); 354 struct snd_interval *channels = hw_param_interval(params, 355 SNDRV_PCM_HW_PARAM_CHANNELS); 356 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 357 358 /* The ADSP will covert the FE rate to 48k, stereo */ 359 rate->min = rate->max = 48000; 360 channels->min = channels->max = 2; 361 362 /* set SSP0 to 24 bit */ 363 snd_mask_none(fmt); 364 snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); 365 return 0; 366 } 367 368 static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, 369 struct snd_pcm_hw_params *params) 370 { 371 struct snd_interval *channels = hw_param_interval(params, 372 SNDRV_PCM_HW_PARAM_CHANNELS); 373 if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) 374 channels->min = channels->max = 2; 375 else 376 channels->min = channels->max = 4; 377 378 return 0; 379 } 380 381 static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, 382 struct snd_pcm_hw_params *params) 383 { 384 struct snd_soc_pcm_runtime *rtd = substream->private_data; 385 struct snd_soc_dai *codec_dai = rtd->codec_dai; 386 int ret; 387 388 ret = snd_soc_dai_set_sysclk(codec_dai, 389 NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); 390 391 if (ret < 0) 392 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); 393 394 return ret; 395 } 396 397 static const struct snd_soc_ops skylake_nau8825_ops = { 398 .hw_params = skylake_nau8825_hw_params, 399 }; 400 401 static unsigned int channels_dmic[] = { 402 2, 4, 403 }; 404 405 static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { 406 .count = ARRAY_SIZE(channels_dmic), 407 .list = channels_dmic, 408 .mask = 0, 409 }; 410 411 static const unsigned int dmic_2ch[] = { 412 2, 413 }; 414 415 static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { 416 .count = ARRAY_SIZE(dmic_2ch), 417 .list = dmic_2ch, 418 .mask = 0, 419 }; 420 421 static int skylake_dmic_startup(struct snd_pcm_substream *substream) 422 { 423 struct snd_pcm_runtime *runtime = substream->runtime; 424 425 runtime->hw.channels_max = DMIC_CH(dmic_constraints); 426 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 427 dmic_constraints); 428 429 return snd_pcm_hw_constraint_list(substream->runtime, 0, 430 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 431 } 432 433 static const struct snd_soc_ops skylake_dmic_ops = { 434 .startup = skylake_dmic_startup, 435 }; 436 437 static unsigned int rates_16000[] = { 438 16000, 439 }; 440 441 static struct snd_pcm_hw_constraint_list constraints_16000 = { 442 .count = ARRAY_SIZE(rates_16000), 443 .list = rates_16000, 444 }; 445 446 static const unsigned int ch_mono[] = { 447 1, 448 }; 449 450 static const struct snd_pcm_hw_constraint_list constraints_refcap = { 451 .count = ARRAY_SIZE(ch_mono), 452 .list = ch_mono, 453 }; 454 455 static int skylake_refcap_startup(struct snd_pcm_substream *substream) 456 { 457 substream->runtime->hw.channels_max = 1; 458 snd_pcm_hw_constraint_list(substream->runtime, 0, 459 SNDRV_PCM_HW_PARAM_CHANNELS, 460 &constraints_refcap); 461 462 return snd_pcm_hw_constraint_list(substream->runtime, 0, 463 SNDRV_PCM_HW_PARAM_RATE, 464 &constraints_16000); 465 } 466 467 static const struct snd_soc_ops skylaye_refcap_ops = { 468 .startup = skylake_refcap_startup, 469 }; 470 471 /* skylake digital audio interface glue - connects codec <--> CPU */ 472 static struct snd_soc_dai_link skylake_dais[] = { 473 /* Front End DAI links */ 474 [SKL_DPCM_AUDIO_PB] = { 475 .name = "Skl Audio Port", 476 .stream_name = "Audio", 477 .cpu_dai_name = "System Pin", 478 .platform_name = "0000:00:1f.3", 479 .dynamic = 1, 480 .codec_name = "snd-soc-dummy", 481 .codec_dai_name = "snd-soc-dummy-dai", 482 .nonatomic = 1, 483 .init = skylake_nau8825_fe_init, 484 .trigger = { 485 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 486 .dpcm_playback = 1, 487 .ops = &skylake_nau8825_fe_ops, 488 }, 489 [SKL_DPCM_AUDIO_CP] = { 490 .name = "Skl Audio Capture Port", 491 .stream_name = "Audio Record", 492 .cpu_dai_name = "System Pin", 493 .platform_name = "0000:00:1f.3", 494 .dynamic = 1, 495 .codec_name = "snd-soc-dummy", 496 .codec_dai_name = "snd-soc-dummy-dai", 497 .nonatomic = 1, 498 .trigger = { 499 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 500 .dpcm_capture = 1, 501 .ops = &skylake_nau8825_fe_ops, 502 }, 503 [SKL_DPCM_AUDIO_REF_CP] = { 504 .name = "Skl Audio Reference cap", 505 .stream_name = "Wake on Voice", 506 .cpu_dai_name = "Reference Pin", 507 .codec_name = "snd-soc-dummy", 508 .codec_dai_name = "snd-soc-dummy-dai", 509 .platform_name = "0000:00:1f.3", 510 .init = NULL, 511 .dpcm_capture = 1, 512 .nonatomic = 1, 513 .dynamic = 1, 514 .ops = &skylaye_refcap_ops, 515 }, 516 [SKL_DPCM_AUDIO_DMIC_CP] = { 517 .name = "Skl Audio DMIC cap", 518 .stream_name = "dmiccap", 519 .cpu_dai_name = "DMIC Pin", 520 .codec_name = "snd-soc-dummy", 521 .codec_dai_name = "snd-soc-dummy-dai", 522 .platform_name = "0000:00:1f.3", 523 .init = NULL, 524 .dpcm_capture = 1, 525 .nonatomic = 1, 526 .dynamic = 1, 527 .ops = &skylake_dmic_ops, 528 }, 529 [SKL_DPCM_AUDIO_HDMI1_PB] = { 530 .name = "Skl HDMI Port1", 531 .stream_name = "Hdmi1", 532 .cpu_dai_name = "HDMI1 Pin", 533 .codec_name = "snd-soc-dummy", 534 .codec_dai_name = "snd-soc-dummy-dai", 535 .platform_name = "0000:00:1f.3", 536 .dpcm_playback = 1, 537 .init = NULL, 538 .trigger = { 539 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 540 .nonatomic = 1, 541 .dynamic = 1, 542 }, 543 [SKL_DPCM_AUDIO_HDMI2_PB] = { 544 .name = "Skl HDMI Port2", 545 .stream_name = "Hdmi2", 546 .cpu_dai_name = "HDMI2 Pin", 547 .codec_name = "snd-soc-dummy", 548 .codec_dai_name = "snd-soc-dummy-dai", 549 .platform_name = "0000:00:1f.3", 550 .dpcm_playback = 1, 551 .init = NULL, 552 .trigger = { 553 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 554 .nonatomic = 1, 555 .dynamic = 1, 556 }, 557 [SKL_DPCM_AUDIO_HDMI3_PB] = { 558 .name = "Skl HDMI Port3", 559 .stream_name = "Hdmi3", 560 .cpu_dai_name = "HDMI3 Pin", 561 .codec_name = "snd-soc-dummy", 562 .codec_dai_name = "snd-soc-dummy-dai", 563 .platform_name = "0000:00:1f.3", 564 .trigger = { 565 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 566 .dpcm_playback = 1, 567 .init = NULL, 568 .nonatomic = 1, 569 .dynamic = 1, 570 }, 571 572 /* Back End DAI links */ 573 { 574 /* SSP0 - Codec */ 575 .name = "SSP0-Codec", 576 .id = 0, 577 .cpu_dai_name = "SSP0 Pin", 578 .platform_name = "0000:00:1f.3", 579 .no_pcm = 1, 580 .codecs = ssm4567_codec_components, 581 .num_codecs = ARRAY_SIZE(ssm4567_codec_components), 582 .dai_fmt = SND_SOC_DAIFMT_DSP_A | 583 SND_SOC_DAIFMT_IB_NF | 584 SND_SOC_DAIFMT_CBS_CFS, 585 .init = skylake_ssm4567_codec_init, 586 .ignore_pmdown_time = 1, 587 .be_hw_params_fixup = skylake_ssp_fixup, 588 .dpcm_playback = 1, 589 .dpcm_capture = 1, 590 }, 591 { 592 /* SSP1 - Codec */ 593 .name = "SSP1-Codec", 594 .id = 1, 595 .cpu_dai_name = "SSP1 Pin", 596 .platform_name = "0000:00:1f.3", 597 .no_pcm = 1, 598 .codec_name = "i2c-10508825:00", 599 .codec_dai_name = SKL_NUVOTON_CODEC_DAI, 600 .init = skylake_nau8825_codec_init, 601 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 602 SND_SOC_DAIFMT_CBS_CFS, 603 .ignore_pmdown_time = 1, 604 .be_hw_params_fixup = skylake_ssp_fixup, 605 .ops = &skylake_nau8825_ops, 606 .dpcm_playback = 1, 607 .dpcm_capture = 1, 608 }, 609 { 610 .name = "dmic01", 611 .id = 2, 612 .cpu_dai_name = "DMIC01 Pin", 613 .codec_name = "dmic-codec", 614 .codec_dai_name = "dmic-hifi", 615 .platform_name = "0000:00:1f.3", 616 .ignore_suspend = 1, 617 .be_hw_params_fixup = skylake_dmic_fixup, 618 .dpcm_capture = 1, 619 .no_pcm = 1, 620 }, 621 { 622 .name = "iDisp1", 623 .id = 3, 624 .cpu_dai_name = "iDisp1 Pin", 625 .codec_name = "ehdaudio0D2", 626 .codec_dai_name = "intel-hdmi-hifi1", 627 .platform_name = "0000:00:1f.3", 628 .dpcm_playback = 1, 629 .init = skylake_hdmi1_init, 630 .no_pcm = 1, 631 }, 632 { 633 .name = "iDisp2", 634 .id = 4, 635 .cpu_dai_name = "iDisp2 Pin", 636 .codec_name = "ehdaudio0D2", 637 .codec_dai_name = "intel-hdmi-hifi2", 638 .platform_name = "0000:00:1f.3", 639 .init = skylake_hdmi2_init, 640 .dpcm_playback = 1, 641 .no_pcm = 1, 642 }, 643 { 644 .name = "iDisp3", 645 .id = 5, 646 .cpu_dai_name = "iDisp3 Pin", 647 .codec_name = "ehdaudio0D2", 648 .codec_dai_name = "intel-hdmi-hifi3", 649 .platform_name = "0000:00:1f.3", 650 .init = skylake_hdmi3_init, 651 .dpcm_playback = 1, 652 .no_pcm = 1, 653 }, 654 }; 655 656 static int skylake_card_late_probe(struct snd_soc_card *card) 657 { 658 struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); 659 struct skl_hdmi_pcm *pcm; 660 int err; 661 662 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 663 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); 664 if (err < 0) 665 return err; 666 } 667 668 return 0; 669 } 670 671 /* skylake audio machine driver for SPT + NAU88L25 */ 672 static struct snd_soc_card skylake_audio_card = { 673 .name = "sklnau8825adi", 674 .owner = THIS_MODULE, 675 .dai_link = skylake_dais, 676 .num_links = ARRAY_SIZE(skylake_dais), 677 .controls = skylake_controls, 678 .num_controls = ARRAY_SIZE(skylake_controls), 679 .dapm_widgets = skylake_widgets, 680 .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), 681 .dapm_routes = skylake_map, 682 .num_dapm_routes = ARRAY_SIZE(skylake_map), 683 .codec_conf = ssm4567_codec_conf, 684 .num_configs = ARRAY_SIZE(ssm4567_codec_conf), 685 .fully_routed = true, 686 .late_probe = skylake_card_late_probe, 687 }; 688 689 static int skylake_audio_probe(struct platform_device *pdev) 690 { 691 struct skl_nau88125_private *ctx; 692 struct skl_machine_pdata *pdata; 693 694 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); 695 if (!ctx) 696 return -ENOMEM; 697 698 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 699 700 skylake_audio_card.dev = &pdev->dev; 701 snd_soc_card_set_drvdata(&skylake_audio_card, ctx); 702 703 pdata = dev_get_drvdata(&pdev->dev); 704 if (pdata) 705 dmic_constraints = pdata->dmic_num == 2 ? 706 &constraints_dmic_2ch : &constraints_dmic_channels; 707 708 return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); 709 } 710 711 static const struct platform_device_id skl_board_ids[] = { 712 { .name = "skl_n88l25_s4567" }, 713 { .name = "kbl_n88l25_s4567" }, 714 { } 715 }; 716 717 static struct platform_driver skylake_audio = { 718 .probe = skylake_audio_probe, 719 .driver = { 720 .name = "skl_n88l25_s4567", 721 .pm = &snd_soc_pm_ops, 722 }, 723 .id_table = skl_board_ids, 724 }; 725 726 module_platform_driver(skylake_audio) 727 728 /* Module information */ 729 MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); 730 MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); 731 MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); 732 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); 733 MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); 734 MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); 735 MODULE_LICENSE("GPL v2"); 736 MODULE_ALIAS("platform:skl_n88l25_s4567"); 737 MODULE_ALIAS("platform:kbl_n88l25_s4567"); 738