linux/sound/soc/intel/boards/bxt_rt298.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Intel Broxton-P I2S Machine Driver
   4 *
   5 * Copyright (C) 2014-2016, Intel Corporation. All rights reserved.
   6 *
   7 * Modified from:
   8 *   Intel Skylake I2S Machine driver
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <sound/core.h>
  14#include <sound/pcm.h>
  15#include <sound/soc.h>
  16#include <sound/soc-acpi.h>
  17#include <sound/jack.h>
  18#include <sound/pcm_params.h>
  19#include "../../codecs/hdac_hdmi.h"
  20#include "../../codecs/rt298.h"
  21#include "hda_dsp_common.h"
  22
  23/* Headset jack detection DAPM pins */
  24static struct snd_soc_jack broxton_headset;
  25static struct snd_soc_jack broxton_hdmi[3];
  26
  27struct bxt_hdmi_pcm {
  28        struct list_head head;
  29        struct snd_soc_dai *codec_dai;
  30        int device;
  31};
  32
  33struct bxt_rt286_private {
  34        struct list_head hdmi_pcm_list;
  35        bool common_hdmi_codec_drv;
  36};
  37
  38enum {
  39        BXT_DPCM_AUDIO_PB = 0,
  40        BXT_DPCM_AUDIO_CP,
  41        BXT_DPCM_AUDIO_REF_CP,
  42        BXT_DPCM_AUDIO_DMIC_CP,
  43        BXT_DPCM_AUDIO_HDMI1_PB,
  44        BXT_DPCM_AUDIO_HDMI2_PB,
  45        BXT_DPCM_AUDIO_HDMI3_PB,
  46};
  47
  48static struct snd_soc_jack_pin broxton_headset_pins[] = {
  49        {
  50                .pin = "Mic Jack",
  51                .mask = SND_JACK_MICROPHONE,
  52        },
  53        {
  54                .pin = "Headphone Jack",
  55                .mask = SND_JACK_HEADPHONE,
  56        },
  57};
  58
  59static const struct snd_kcontrol_new broxton_controls[] = {
  60        SOC_DAPM_PIN_SWITCH("Speaker"),
  61        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
  62        SOC_DAPM_PIN_SWITCH("Mic Jack"),
  63};
  64
  65static const struct snd_soc_dapm_widget broxton_widgets[] = {
  66        SND_SOC_DAPM_HP("Headphone Jack", NULL),
  67        SND_SOC_DAPM_SPK("Speaker", NULL),
  68        SND_SOC_DAPM_MIC("Mic Jack", NULL),
  69        SND_SOC_DAPM_MIC("DMIC2", NULL),
  70        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
  71        SND_SOC_DAPM_SPK("HDMI1", NULL),
  72        SND_SOC_DAPM_SPK("HDMI2", NULL),
  73        SND_SOC_DAPM_SPK("HDMI3", NULL),
  74};
  75
  76static const struct snd_soc_dapm_route broxton_rt298_map[] = {
  77        /* speaker */
  78        {"Speaker", NULL, "SPOR"},
  79        {"Speaker", NULL, "SPOL"},
  80
  81        /* HP jack connectors - unknown if we have jack detect */
  82        {"Headphone Jack", NULL, "HPO Pin"},
  83
  84        /* other jacks */
  85        {"MIC1", NULL, "Mic Jack"},
  86
  87        /* digital mics */
  88        {"DMIC1 Pin", NULL, "DMIC2"},
  89        {"DMic", NULL, "SoC DMIC"},
  90
  91        {"HDMI1", NULL, "hif5-0 Output"},
  92        {"HDMI2", NULL, "hif6-0 Output"},
  93        {"HDMI2", NULL, "hif7-0 Output"},
  94
  95        /* CODEC BE connections */
  96        { "AIF1 Playback", NULL, "ssp5 Tx"},
  97        { "ssp5 Tx", NULL, "codec0_out"},
  98        { "ssp5 Tx", NULL, "codec1_out"},
  99
 100        { "codec0_in", NULL, "ssp5 Rx" },
 101        { "ssp5 Rx", NULL, "AIF1 Capture" },
 102
 103        { "dmic01_hifi", NULL, "DMIC01 Rx" },
 104        { "DMIC01 Rx", NULL, "Capture" },
 105
 106        { "hifi3", NULL, "iDisp3 Tx"},
 107        { "iDisp3 Tx", NULL, "iDisp3_out"},
 108        { "hifi2", NULL, "iDisp2 Tx"},
 109        { "iDisp2 Tx", NULL, "iDisp2_out"},
 110        { "hifi1", NULL, "iDisp1 Tx"},
 111        { "iDisp1 Tx", NULL, "iDisp1_out"},
 112};
 113
 114static const struct snd_soc_dapm_route geminilake_rt298_map[] = {
 115        /* speaker */
 116        {"Speaker", NULL, "SPOR"},
 117        {"Speaker", NULL, "SPOL"},
 118
 119        /* HP jack connectors - unknown if we have jack detect */
 120        {"Headphone Jack", NULL, "HPO Pin"},
 121
 122        /* other jacks */
 123        {"MIC1", NULL, "Mic Jack"},
 124
 125        /* digital mics */
 126        {"DMIC1 Pin", NULL, "DMIC2"},
 127        {"DMic", NULL, "SoC DMIC"},
 128
 129        {"HDMI1", NULL, "hif5-0 Output"},
 130        {"HDMI2", NULL, "hif6-0 Output"},
 131        {"HDMI2", NULL, "hif7-0 Output"},
 132
 133        /* CODEC BE connections */
 134        { "AIF1 Playback", NULL, "ssp2 Tx"},
 135        { "ssp2 Tx", NULL, "codec0_out"},
 136        { "ssp2 Tx", NULL, "codec1_out"},
 137
 138        { "codec0_in", NULL, "ssp2 Rx" },
 139        { "ssp2 Rx", NULL, "AIF1 Capture" },
 140
 141        { "dmic01_hifi", NULL, "DMIC01 Rx" },
 142        { "DMIC01 Rx", NULL, "Capture" },
 143
 144        { "dmic_voice", NULL, "DMIC16k Rx" },
 145        { "DMIC16k Rx", NULL, "Capture" },
 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
 155static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
 156{
 157        struct snd_soc_dapm_context *dapm;
 158        struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
 159
 160        dapm = snd_soc_component_get_dapm(component);
 161        snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
 162
 163        return 0;
 164}
 165
 166static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
 167{
 168        struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
 169        int ret = 0;
 170
 171        ret = snd_soc_card_jack_new(rtd->card, "Headset",
 172                SND_JACK_HEADSET | SND_JACK_BTN_0,
 173                &broxton_headset,
 174                broxton_headset_pins, ARRAY_SIZE(broxton_headset_pins));
 175
 176        if (ret)
 177                return ret;
 178
 179        rt298_mic_detect(component, &broxton_headset);
 180
 181        snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
 182
 183        return 0;
 184}
 185
 186static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd)
 187{
 188        struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card);
 189        struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
 190        struct bxt_hdmi_pcm *pcm;
 191
 192        pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
 193        if (!pcm)
 194                return -ENOMEM;
 195
 196        pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id;
 197        pcm->codec_dai = dai;
 198
 199        list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
 200
 201        return 0;
 202}
 203
 204static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd,
 205                        struct snd_pcm_hw_params *params)
 206{
 207        struct snd_interval *rate = hw_param_interval(params,
 208                                        SNDRV_PCM_HW_PARAM_RATE);
 209        struct snd_interval *chan = hw_param_interval(params,
 210                                        SNDRV_PCM_HW_PARAM_CHANNELS);
 211        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 212
 213        /* The ADSP will covert the FE rate to 48k, stereo */
 214        rate->min = rate->max = 48000;
 215        chan->min = chan->max = 2;
 216
 217        /* set SSP5 to 24 bit */
 218        snd_mask_none(fmt);
 219        snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
 220
 221        return 0;
 222}
 223
 224static int broxton_rt298_hw_params(struct snd_pcm_substream *substream,
 225        struct snd_pcm_hw_params *params)
 226{
 227        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 228        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 229        int ret;
 230
 231        ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL,
 232                                        19200000, SND_SOC_CLOCK_IN);
 233        if (ret < 0) {
 234                dev_err(rtd->dev, "can't set codec sysclk configuration\n");
 235                return ret;
 236        }
 237
 238        return ret;
 239}
 240
 241static const struct snd_soc_ops broxton_rt298_ops = {
 242        .hw_params = broxton_rt298_hw_params,
 243};
 244
 245static const unsigned int rates[] = {
 246        48000,
 247};
 248
 249static const struct snd_pcm_hw_constraint_list constraints_rates = {
 250        .count = ARRAY_SIZE(rates),
 251        .list  = rates,
 252        .mask = 0,
 253};
 254
 255static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
 256                                struct snd_pcm_hw_params *params)
 257{
 258        struct snd_interval *chan = hw_param_interval(params,
 259                                                SNDRV_PCM_HW_PARAM_CHANNELS);
 260        chan->min = chan->max = 4;
 261
 262        return 0;
 263}
 264
 265static const unsigned int channels_dmic[] = {
 266        1, 2, 3, 4,
 267};
 268
 269static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
 270        .count = ARRAY_SIZE(channels_dmic),
 271        .list = channels_dmic,
 272        .mask = 0,
 273};
 274
 275static int broxton_dmic_startup(struct snd_pcm_substream *substream)
 276{
 277        struct snd_pcm_runtime *runtime = substream->runtime;
 278
 279        runtime->hw.channels_max = 4;
 280        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 281                                        &constraints_dmic_channels);
 282
 283        return snd_pcm_hw_constraint_list(substream->runtime, 0,
 284                                SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
 285}
 286
 287static const struct snd_soc_ops broxton_dmic_ops = {
 288        .startup = broxton_dmic_startup,
 289};
 290
 291static const unsigned int channels[] = {
 292        2,
 293};
 294
 295static const struct snd_pcm_hw_constraint_list constraints_channels = {
 296        .count = ARRAY_SIZE(channels),
 297        .list = channels,
 298        .mask = 0,
 299};
 300
 301static int bxt_fe_startup(struct snd_pcm_substream *substream)
 302{
 303        struct snd_pcm_runtime *runtime = substream->runtime;
 304
 305        /*
 306         * on this platform for PCM device we support:
 307         *      48Khz
 308         *      stereo
 309         *      16-bit audio
 310         */
 311
 312        runtime->hw.channels_max = 2;
 313        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 314                                &constraints_channels);
 315
 316        runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
 317        snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
 318        snd_pcm_hw_constraint_list(runtime, 0,
 319                                SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
 320
 321        return 0;
 322}
 323
 324static const struct snd_soc_ops broxton_rt286_fe_ops = {
 325        .startup = bxt_fe_startup,
 326};
 327
 328SND_SOC_DAILINK_DEF(dummy,
 329        DAILINK_COMP_ARRAY(COMP_DUMMY()));
 330
 331SND_SOC_DAILINK_DEF(system,
 332        DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
 333
 334SND_SOC_DAILINK_DEF(reference,
 335        DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
 336
 337SND_SOC_DAILINK_DEF(dmic,
 338        DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
 339
 340SND_SOC_DAILINK_DEF(hdmi1,
 341        DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
 342
 343SND_SOC_DAILINK_DEF(hdmi2,
 344        DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
 345
 346SND_SOC_DAILINK_DEF(hdmi3,
 347        DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
 348
 349SND_SOC_DAILINK_DEF(ssp5_pin,
 350        DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin")));
 351SND_SOC_DAILINK_DEF(ssp5_codec,
 352        DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00",
 353                                      "rt298-aif1")));
 354
 355SND_SOC_DAILINK_DEF(dmic_pin,
 356        DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
 357
 358SND_SOC_DAILINK_DEF(dmic_codec,
 359        DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec",
 360                                      "dmic-hifi")));
 361
 362SND_SOC_DAILINK_DEF(dmic16k,
 363        DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
 364
 365SND_SOC_DAILINK_DEF(idisp1_pin,
 366        DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
 367SND_SOC_DAILINK_DEF(idisp1_codec,
 368        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
 369                                      "intel-hdmi-hifi1")));
 370
 371SND_SOC_DAILINK_DEF(idisp2_pin,
 372        DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
 373SND_SOC_DAILINK_DEF(idisp2_codec,
 374        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
 375                                      "intel-hdmi-hifi2")));
 376
 377SND_SOC_DAILINK_DEF(idisp3_pin,
 378        DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
 379SND_SOC_DAILINK_DEF(idisp3_codec,
 380        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
 381                                      "intel-hdmi-hifi3")));
 382
 383SND_SOC_DAILINK_DEF(platform,
 384        DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0")));
 385
 386/* broxton digital audio interface glue - connects codec <--> CPU */
 387static struct snd_soc_dai_link broxton_rt298_dais[] = {
 388        /* Front End DAI links */
 389        [BXT_DPCM_AUDIO_PB] =
 390        {
 391                .name = "Bxt Audio Port",
 392                .stream_name = "Audio",
 393                .nonatomic = 1,
 394                .dynamic = 1,
 395                .init = broxton_rt298_fe_init,
 396                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 397                .dpcm_playback = 1,
 398                .ops = &broxton_rt286_fe_ops,
 399                SND_SOC_DAILINK_REG(system, dummy, platform),
 400        },
 401        [BXT_DPCM_AUDIO_CP] =
 402        {
 403                .name = "Bxt Audio Capture Port",
 404                .stream_name = "Audio Record",
 405                .nonatomic = 1,
 406                .dynamic = 1,
 407                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 408                .dpcm_capture = 1,
 409                .ops = &broxton_rt286_fe_ops,
 410                SND_SOC_DAILINK_REG(system, dummy, platform),
 411        },
 412        [BXT_DPCM_AUDIO_REF_CP] =
 413        {
 414                .name = "Bxt Audio Reference cap",
 415                .stream_name = "refcap",
 416                .init = NULL,
 417                .dpcm_capture = 1,
 418                .nonatomic = 1,
 419                .dynamic = 1,
 420                SND_SOC_DAILINK_REG(reference, dummy, platform),
 421        },
 422        [BXT_DPCM_AUDIO_DMIC_CP] =
 423        {
 424                .name = "Bxt Audio DMIC cap",
 425                .stream_name = "dmiccap",
 426                .init = NULL,
 427                .dpcm_capture = 1,
 428                .nonatomic = 1,
 429                .dynamic = 1,
 430                .ops = &broxton_dmic_ops,
 431                SND_SOC_DAILINK_REG(dmic, dummy, platform),
 432        },
 433        [BXT_DPCM_AUDIO_HDMI1_PB] =
 434        {
 435                .name = "Bxt HDMI Port1",
 436                .stream_name = "Hdmi1",
 437                .dpcm_playback = 1,
 438                .init = NULL,
 439                .nonatomic = 1,
 440                .dynamic = 1,
 441                SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
 442        },
 443        [BXT_DPCM_AUDIO_HDMI2_PB] =
 444        {
 445                .name = "Bxt HDMI Port2",
 446                .stream_name = "Hdmi2",
 447                .dpcm_playback = 1,
 448                .init = NULL,
 449                .nonatomic = 1,
 450                .dynamic = 1,
 451                SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
 452        },
 453        [BXT_DPCM_AUDIO_HDMI3_PB] =
 454        {
 455                .name = "Bxt HDMI Port3",
 456                .stream_name = "Hdmi3",
 457                .dpcm_playback = 1,
 458                .init = NULL,
 459                .nonatomic = 1,
 460                .dynamic = 1,
 461                SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
 462        },
 463        /* Back End DAI links */
 464        {
 465                /* SSP5 - Codec */
 466                .name = "SSP5-Codec",
 467                .id = 0,
 468                .no_pcm = 1,
 469                .init = broxton_rt298_codec_init,
 470                .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF |
 471                                                SND_SOC_DAIFMT_CBS_CFS,
 472                .ignore_pmdown_time = 1,
 473                .be_hw_params_fixup = broxton_ssp5_fixup,
 474                .ops = &broxton_rt298_ops,
 475                .dpcm_playback = 1,
 476                .dpcm_capture = 1,
 477                SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform),
 478        },
 479        {
 480                .name = "dmic01",
 481                .id = 1,
 482                .be_hw_params_fixup = broxton_dmic_fixup,
 483                .ignore_suspend = 1,
 484                .dpcm_capture = 1,
 485                .no_pcm = 1,
 486                SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
 487        },
 488        {
 489                .name = "dmic16k",
 490                .id = 2,
 491                .be_hw_params_fixup = broxton_dmic_fixup,
 492                .ignore_suspend = 1,
 493                .dpcm_capture = 1,
 494                .no_pcm = 1,
 495                SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
 496        },
 497        {
 498                .name = "iDisp1",
 499                .id = 3,
 500                .init = broxton_hdmi_init,
 501                .dpcm_playback = 1,
 502                .no_pcm = 1,
 503                SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
 504        },
 505        {
 506                .name = "iDisp2",
 507                .id = 4,
 508                .init = broxton_hdmi_init,
 509                .dpcm_playback = 1,
 510                .no_pcm = 1,
 511                SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
 512        },
 513        {
 514                .name = "iDisp3",
 515                .id = 5,
 516                .init = broxton_hdmi_init,
 517                .dpcm_playback = 1,
 518                .no_pcm = 1,
 519                SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
 520        },
 521};
 522
 523#define NAME_SIZE       32
 524static int bxt_card_late_probe(struct snd_soc_card *card)
 525{
 526        struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card);
 527        struct bxt_hdmi_pcm *pcm;
 528        struct snd_soc_component *component = NULL;
 529        int err, i = 0;
 530        char jack_name[NAME_SIZE];
 531
 532        if (list_empty(&ctx->hdmi_pcm_list))
 533                return -EINVAL;
 534
 535        if (ctx->common_hdmi_codec_drv) {
 536                pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
 537                                       head);
 538                component = pcm->codec_dai->component;
 539                return hda_dsp_hdmi_build_controls(card, component);
 540        }
 541
 542        list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
 543                component = pcm->codec_dai->component;
 544                snprintf(jack_name, sizeof(jack_name),
 545                        "HDMI/DP, pcm=%d Jack", pcm->device);
 546                err = snd_soc_card_jack_new(card, jack_name,
 547                                        SND_JACK_AVOUT, &broxton_hdmi[i],
 548                                        NULL, 0);
 549
 550                if (err)
 551                        return err;
 552
 553                err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
 554                                                &broxton_hdmi[i]);
 555                if (err < 0)
 556                        return err;
 557
 558                i++;
 559        }
 560
 561        return hdac_hdmi_jack_port_init(component, &card->dapm);
 562}
 563
 564
 565/* broxton audio machine driver for SPT + RT298S */
 566static struct snd_soc_card broxton_rt298 = {
 567        .name = "broxton-rt298",
 568        .owner = THIS_MODULE,
 569        .dai_link = broxton_rt298_dais,
 570        .num_links = ARRAY_SIZE(broxton_rt298_dais),
 571        .controls = broxton_controls,
 572        .num_controls = ARRAY_SIZE(broxton_controls),
 573        .dapm_widgets = broxton_widgets,
 574        .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
 575        .dapm_routes = broxton_rt298_map,
 576        .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map),
 577        .fully_routed = true,
 578        .late_probe = bxt_card_late_probe,
 579
 580};
 581
 582static struct snd_soc_card geminilake_rt298 = {
 583        .name = "geminilake-rt298",
 584        .owner = THIS_MODULE,
 585        .dai_link = broxton_rt298_dais,
 586        .num_links = ARRAY_SIZE(broxton_rt298_dais),
 587        .controls = broxton_controls,
 588        .num_controls = ARRAY_SIZE(broxton_controls),
 589        .dapm_widgets = broxton_widgets,
 590        .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
 591        .dapm_routes = geminilake_rt298_map,
 592        .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map),
 593        .fully_routed = true,
 594        .late_probe = bxt_card_late_probe,
 595};
 596
 597static int broxton_audio_probe(struct platform_device *pdev)
 598{
 599        struct bxt_rt286_private *ctx;
 600        struct snd_soc_card *card =
 601                        (struct snd_soc_card *)pdev->id_entry->driver_data;
 602        struct snd_soc_acpi_mach *mach;
 603        const char *platform_name;
 604        int ret;
 605        int i;
 606
 607        for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) {
 608                if (!strncmp(card->dai_link[i].codecs->name, "i2c-INT343A:00",
 609                             I2C_NAME_SIZE)) {
 610                        if (!strncmp(card->name, "broxton-rt298",
 611                                     PLATFORM_NAME_SIZE)) {
 612                                card->dai_link[i].name = "SSP5-Codec";
 613                                card->dai_link[i].cpus->dai_name = "SSP5 Pin";
 614                        } else if (!strncmp(card->name, "geminilake-rt298",
 615                                            PLATFORM_NAME_SIZE)) {
 616                                card->dai_link[i].name = "SSP2-Codec";
 617                                card->dai_link[i].cpus->dai_name = "SSP2 Pin";
 618                        }
 619                }
 620        }
 621
 622        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 623        if (!ctx)
 624                return -ENOMEM;
 625
 626        INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
 627
 628        card->dev = &pdev->dev;
 629        snd_soc_card_set_drvdata(card, ctx);
 630
 631        /* override plaform name, if required */
 632        mach = pdev->dev.platform_data;
 633        platform_name = mach->mach_params.platform;
 634
 635        ret = snd_soc_fixup_dai_links_platform_name(card,
 636                                                    platform_name);
 637        if (ret)
 638                return ret;
 639
 640        ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
 641
 642        return devm_snd_soc_register_card(&pdev->dev, card);
 643}
 644
 645static const struct platform_device_id bxt_board_ids[] = {
 646        { .name = "bxt_alc298s_i2s", .driver_data =
 647                                (unsigned long)&broxton_rt298 },
 648        { .name = "glk_alc298s_i2s", .driver_data =
 649                                (unsigned long)&geminilake_rt298 },
 650        {}
 651};
 652
 653static struct platform_driver broxton_audio = {
 654        .probe = broxton_audio_probe,
 655        .driver = {
 656                .name = "bxt_alc298s_i2s",
 657                .pm = &snd_soc_pm_ops,
 658        },
 659        .id_table = bxt_board_ids,
 660};
 661module_platform_driver(broxton_audio)
 662
 663/* Module information */
 664MODULE_AUTHOR("Ramesh Babu <Ramesh.Babu@intel.com>");
 665MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>");
 666MODULE_DESCRIPTION("Intel SST Audio for Broxton");
 667MODULE_LICENSE("GPL v2");
 668MODULE_ALIAS("platform:bxt_alc298s_i2s");
 669MODULE_ALIAS("platform:glk_alc298s_i2s");
 670