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