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