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