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