linux/sound/soc/intel/boards/bxt_da7219_max98357a.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Intel Broxton-P I2S Machine Driver
   4 *
   5 * Copyright (C) 2016, Intel Corporation. All rights reserved.
   6 *
   7 * Modified from:
   8 *   Intel Skylake I2S Machine driver
   9 */
  10
  11#include <linux/input.h>
  12#include <linux/module.h>
  13#include <linux/platform_device.h>
  14#include <sound/core.h>
  15#include <sound/jack.h>
  16#include <sound/pcm.h>
  17#include <sound/pcm_params.h>
  18#include <sound/soc.h>
  19#include <sound/soc-acpi.h>
  20#include "../../codecs/hdac_hdmi.h"
  21#include "../../codecs/da7219.h"
  22#include "../../codecs/da7219-aad.h"
  23#include "../common/soc-intel-quirks.h"
  24#include "hda_dsp_common.h"
  25
  26#define BXT_DIALOG_CODEC_DAI    "da7219-hifi"
  27#define BXT_MAXIM_CODEC_DAI     "HiFi"
  28#define MAX98390_DEV0_NAME      "i2c-MX98390:00"
  29#define MAX98390_DEV1_NAME      "i2c-MX98390:01"
  30#define DUAL_CHANNEL            2
  31#define QUAD_CHANNEL            4
  32
  33#define SPKAMP_MAX98357A        1
  34#define SPKAMP_MAX98390 2
  35
  36static struct snd_soc_jack broxton_headset;
  37static struct snd_soc_jack broxton_hdmi[3];
  38
  39struct bxt_hdmi_pcm {
  40        struct list_head head;
  41        struct snd_soc_dai *codec_dai;
  42        int device;
  43};
  44
  45struct bxt_card_private {
  46        struct list_head hdmi_pcm_list;
  47        bool common_hdmi_codec_drv;
  48        int spkamp;
  49};
  50
  51enum {
  52        BXT_DPCM_AUDIO_PB = 0,
  53        BXT_DPCM_AUDIO_CP,
  54        BXT_DPCM_AUDIO_HS_PB,
  55        BXT_DPCM_AUDIO_REF_CP,
  56        BXT_DPCM_AUDIO_DMIC_CP,
  57        BXT_DPCM_AUDIO_HDMI1_PB,
  58        BXT_DPCM_AUDIO_HDMI2_PB,
  59        BXT_DPCM_AUDIO_HDMI3_PB,
  60};
  61
  62static int platform_clock_control(struct snd_soc_dapm_widget *w,
  63        struct snd_kcontrol *k, int  event)
  64{
  65        int ret = 0;
  66        struct snd_soc_dapm_context *dapm = w->dapm;
  67        struct snd_soc_card *card = dapm->card;
  68        struct snd_soc_dai *codec_dai;
  69
  70        codec_dai = snd_soc_card_get_codec_dai(card, BXT_DIALOG_CODEC_DAI);
  71        if (!codec_dai) {
  72                dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
  73                return -EIO;
  74        }
  75
  76        if (SND_SOC_DAPM_EVENT_OFF(event)) {
  77                ret = snd_soc_dai_set_pll(codec_dai, 0,
  78                        DA7219_SYSCLK_MCLK, 0, 0);
  79                if (ret)
  80                        dev_err(card->dev, "failed to stop PLL: %d\n", ret);
  81        } else if(SND_SOC_DAPM_EVENT_ON(event)) {
  82                ret = snd_soc_dai_set_pll(codec_dai, 0,
  83                        DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304);
  84                if (ret)
  85                        dev_err(card->dev, "failed to start PLL: %d\n", ret);
  86        }
  87
  88        return ret;
  89}
  90
  91static const struct snd_kcontrol_new broxton_controls[] = {
  92        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
  93        SOC_DAPM_PIN_SWITCH("Headset Mic"),
  94};
  95
  96static const struct snd_kcontrol_new max98357a_controls[] = {
  97        SOC_DAPM_PIN_SWITCH("Spk"),
  98};
  99
 100static const struct snd_kcontrol_new max98390_controls[] = {
 101        SOC_DAPM_PIN_SWITCH("Left Spk"),
 102        SOC_DAPM_PIN_SWITCH("Right Spk"),
 103};
 104
 105static const struct snd_soc_dapm_widget broxton_widgets[] = {
 106        SND_SOC_DAPM_HP("Headphone Jack", NULL),
 107        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 108        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
 109        SND_SOC_DAPM_SPK("HDMI1", NULL),
 110        SND_SOC_DAPM_SPK("HDMI2", NULL),
 111        SND_SOC_DAPM_SPK("HDMI3", NULL),
 112        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 113                        platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU),
 114};
 115
 116static const struct snd_soc_dapm_widget max98357a_widgets[] = {
 117        SND_SOC_DAPM_SPK("Spk", NULL),
 118};
 119
 120static const struct snd_soc_dapm_widget max98390_widgets[] = {
 121        SND_SOC_DAPM_SPK("Left Spk", NULL),
 122        SND_SOC_DAPM_SPK("Right Spk", NULL),
 123};
 124
 125static const struct snd_soc_dapm_route audio_map[] = {
 126        /* HP jack connectors - unknown if we have jack detection */
 127        {"Headphone Jack", NULL, "HPL"},
 128        {"Headphone Jack", NULL, "HPR"},
 129
 130        /* other jacks */
 131        {"MIC", NULL, "Headset Mic"},
 132
 133        /* digital mics */
 134        {"DMic", NULL, "SoC DMIC"},
 135
 136        /* CODEC BE connections */
 137        {"HDMI1", NULL, "hif5-0 Output"},
 138        {"HDMI2", NULL, "hif6-0 Output"},
 139        {"HDMI2", NULL, "hif7-0 Output"},
 140
 141        {"hifi3", NULL, "iDisp3 Tx"},
 142        {"iDisp3 Tx", NULL, "iDisp3_out"},
 143        {"hifi2", NULL, "iDisp2 Tx"},
 144        {"iDisp2 Tx", NULL, "iDisp2_out"},
 145        {"hifi1", NULL, "iDisp1 Tx"},
 146        {"iDisp1 Tx", NULL, "iDisp1_out"},
 147
 148        /* DMIC */
 149        {"dmic01_hifi", NULL, "DMIC01 Rx"},
 150        {"DMIC01 Rx", NULL, "DMIC AIF"},
 151
 152        { "Headphone Jack", NULL, "Platform Clock" },
 153        { "Headset Mic", NULL, "Platform Clock" },
 154};
 155
 156static const struct snd_soc_dapm_route max98357a_routes[] = {
 157        /* speaker */
 158        {"Spk", NULL, "Speaker"},
 159};
 160
 161static const struct snd_soc_dapm_route max98390_routes[] = {
 162        /* Speaker */
 163        {"Left Spk", NULL, "Left BE_OUT"},
 164        {"Right Spk", NULL, "Right BE_OUT"},
 165};
 166
 167static const struct snd_soc_dapm_route broxton_map[] = {
 168        {"HiFi Playback", NULL, "ssp5 Tx"},
 169        {"ssp5 Tx", NULL, "codec0_out"},
 170
 171        {"Playback", NULL, "ssp1 Tx"},
 172        {"ssp1 Tx", NULL, "codec1_out"},
 173
 174        {"codec0_in", NULL, "ssp1 Rx"},
 175        {"ssp1 Rx", NULL, "Capture"},
 176};
 177
 178static const struct snd_soc_dapm_route gemini_map[] = {
 179        {"HiFi Playback", NULL, "ssp1 Tx"},
 180        {"ssp1 Tx", NULL, "codec0_out"},
 181
 182        {"Playback", NULL, "ssp2 Tx"},
 183        {"ssp2 Tx", NULL, "codec1_out"},
 184
 185        {"codec0_in", NULL, "ssp2 Rx"},
 186        {"ssp2 Rx", NULL, "Capture"},
 187};
 188
 189static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
 190                        struct snd_pcm_hw_params *params)
 191{
 192        struct snd_interval *rate = hw_param_interval(params,
 193                        SNDRV_PCM_HW_PARAM_RATE);
 194        struct snd_interval *chan = hw_param_interval(params,
 195                        SNDRV_PCM_HW_PARAM_CHANNELS);
 196        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 197
 198        /* The ADSP will convert the FE rate to 48k, stereo */
 199        rate->min = rate->max = 48000;
 200        chan->min = chan->max = DUAL_CHANNEL;
 201
 202        /* set SSP to 24 bit */
 203        snd_mask_none(fmt);
 204        snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
 205
 206        return 0;
 207}
 208
 209static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
 210{
 211        int ret;
 212        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 213        struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
 214        int clk_freq;
 215
 216        /* Configure sysclk for codec */
 217        if (soc_intel_is_cml())
 218                clk_freq = 24000000;
 219        else
 220                clk_freq = 19200000;
 221
 222        ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq,
 223                                     SND_SOC_CLOCK_IN);
 224
 225        if (ret) {
 226                dev_err(rtd->dev, "can't set codec sysclk configuration\n");
 227                return ret;
 228        }
 229
 230        /*
 231         * Headset buttons map to the google Reference headset.
 232         * These can be configured by userspace.
 233         */
 234        ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
 235                        SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
 236                        SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT,
 237                        &broxton_headset, NULL, 0);
 238        if (ret) {
 239                dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
 240                return ret;
 241        }
 242
 243        snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
 244        snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
 245        snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
 246        snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_3,
 247                         KEY_VOICECOMMAND);
 248
 249        da7219_aad_jack_det(component, &broxton_headset);
 250
 251        snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
 252
 253        return ret;
 254}
 255
 256static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd)
 257{
 258        struct bxt_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
 259        struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
 260        struct bxt_hdmi_pcm *pcm;
 261
 262        pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
 263        if (!pcm)
 264                return -ENOMEM;
 265
 266        pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id;
 267        pcm->codec_dai = dai;
 268
 269        list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
 270
 271        return 0;
 272}
 273
 274static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd)
 275{
 276        struct snd_soc_dapm_context *dapm;
 277        struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
 278
 279        dapm = snd_soc_component_get_dapm(component);
 280        snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
 281
 282        return 0;
 283}
 284
 285static const unsigned int rates[] = {
 286        48000,
 287};
 288
 289static const struct snd_pcm_hw_constraint_list constraints_rates = {
 290        .count = ARRAY_SIZE(rates),
 291        .list  = rates,
 292        .mask = 0,
 293};
 294
 295static const unsigned int channels[] = {
 296        DUAL_CHANNEL,
 297};
 298
 299static const struct snd_pcm_hw_constraint_list constraints_channels = {
 300        .count = ARRAY_SIZE(channels),
 301        .list = channels,
 302        .mask = 0,
 303};
 304
 305static const unsigned int channels_quad[] = {
 306        QUAD_CHANNEL,
 307};
 308
 309static const struct snd_pcm_hw_constraint_list constraints_channels_quad = {
 310        .count = ARRAY_SIZE(channels_quad),
 311        .list = channels_quad,
 312        .mask = 0,
 313};
 314
 315static int bxt_fe_startup(struct snd_pcm_substream *substream)
 316{
 317        struct snd_pcm_runtime *runtime = substream->runtime;
 318
 319        /*
 320         * On this platform for PCM device we support,
 321         * 48Khz
 322         * stereo
 323         * 16 bit audio
 324         */
 325
 326        runtime->hw.channels_max = DUAL_CHANNEL;
 327        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 328                                           &constraints_channels);
 329
 330        runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
 331        snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
 332
 333        snd_pcm_hw_constraint_list(runtime, 0,
 334                                SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
 335
 336        return 0;
 337}
 338
 339static const struct snd_soc_ops broxton_da7219_fe_ops = {
 340        .startup = bxt_fe_startup,
 341};
 342
 343static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
 344                        struct snd_pcm_hw_params *params)
 345{
 346        struct snd_interval *chan = hw_param_interval(params,
 347                                                SNDRV_PCM_HW_PARAM_CHANNELS);
 348        if (params_channels(params) == 2)
 349                chan->min = chan->max = 2;
 350        else
 351                chan->min = chan->max = 4;
 352
 353        return 0;
 354}
 355
 356static int broxton_dmic_startup(struct snd_pcm_substream *substream)
 357{
 358        struct snd_pcm_runtime *runtime = substream->runtime;
 359
 360        runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
 361        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 362                        &constraints_channels_quad);
 363
 364        return snd_pcm_hw_constraint_list(substream->runtime, 0,
 365                        SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
 366}
 367
 368static const struct snd_soc_ops broxton_dmic_ops = {
 369        .startup = broxton_dmic_startup,
 370};
 371
 372static const unsigned int rates_16000[] = {
 373        16000,
 374};
 375
 376static const struct snd_pcm_hw_constraint_list constraints_16000 = {
 377        .count = ARRAY_SIZE(rates_16000),
 378        .list  = rates_16000,
 379};
 380
 381static const unsigned int ch_mono[] = {
 382        1,
 383};
 384
 385static const struct snd_pcm_hw_constraint_list constraints_refcap = {
 386        .count = ARRAY_SIZE(ch_mono),
 387        .list  = ch_mono,
 388};
 389
 390static int broxton_refcap_startup(struct snd_pcm_substream *substream)
 391{
 392        substream->runtime->hw.channels_max = 1;
 393        snd_pcm_hw_constraint_list(substream->runtime, 0,
 394                                   SNDRV_PCM_HW_PARAM_CHANNELS,
 395                                   &constraints_refcap);
 396
 397        return snd_pcm_hw_constraint_list(substream->runtime, 0,
 398                        SNDRV_PCM_HW_PARAM_RATE,
 399                        &constraints_16000);
 400};
 401
 402static const struct snd_soc_ops broxton_refcap_ops = {
 403        .startup = broxton_refcap_startup,
 404};
 405
 406/* broxton digital audio interface glue - connects codec <--> CPU */
 407SND_SOC_DAILINK_DEF(dummy,
 408        DAILINK_COMP_ARRAY(COMP_DUMMY()));
 409
 410SND_SOC_DAILINK_DEF(system,
 411        DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
 412
 413SND_SOC_DAILINK_DEF(system2,
 414        DAILINK_COMP_ARRAY(COMP_CPU("System Pin2")));
 415
 416SND_SOC_DAILINK_DEF(reference,
 417        DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
 418
 419SND_SOC_DAILINK_DEF(dmic,
 420        DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
 421
 422SND_SOC_DAILINK_DEF(hdmi1,
 423        DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
 424
 425SND_SOC_DAILINK_DEF(hdmi2,
 426        DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
 427
 428SND_SOC_DAILINK_DEF(hdmi3,
 429        DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
 430
 431 /* Back End DAI */
 432SND_SOC_DAILINK_DEF(ssp5_pin,
 433        DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin")));
 434SND_SOC_DAILINK_DEF(ssp5_codec,
 435        DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00",
 436                                      BXT_MAXIM_CODEC_DAI)));
 437SND_SOC_DAILINK_DEF(max98390_codec,
 438        DAILINK_COMP_ARRAY(
 439        /* Left */      COMP_CODEC(MAX98390_DEV0_NAME, "max98390-aif1"),
 440        /* Right */     COMP_CODEC(MAX98390_DEV1_NAME, "max98390-aif1")));
 441
 442SND_SOC_DAILINK_DEF(ssp1_pin,
 443        DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
 444SND_SOC_DAILINK_DEF(ssp1_codec,
 445        DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00",
 446                                      BXT_DIALOG_CODEC_DAI)));
 447
 448SND_SOC_DAILINK_DEF(dmic_pin,
 449        DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
 450
 451SND_SOC_DAILINK_DEF(dmic16k_pin,
 452        DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
 453
 454SND_SOC_DAILINK_DEF(dmic_codec,
 455        DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
 456
 457SND_SOC_DAILINK_DEF(idisp1_pin,
 458        DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
 459SND_SOC_DAILINK_DEF(idisp1_codec,
 460        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
 461
 462SND_SOC_DAILINK_DEF(idisp2_pin,
 463        DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
 464SND_SOC_DAILINK_DEF(idisp2_codec,
 465        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
 466                                      "intel-hdmi-hifi2")));
 467
 468SND_SOC_DAILINK_DEF(idisp3_pin,
 469        DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
 470SND_SOC_DAILINK_DEF(idisp3_codec,
 471        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
 472                                      "intel-hdmi-hifi3")));
 473
 474SND_SOC_DAILINK_DEF(platform,
 475        DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0")));
 476
 477static struct snd_soc_dai_link broxton_dais[] = {
 478        /* Front End DAI links */
 479        [BXT_DPCM_AUDIO_PB] =
 480        {
 481                .name = "Bxt Audio Port",
 482                .stream_name = "Audio",
 483                .dynamic = 1,
 484                .nonatomic = 1,
 485                .init = broxton_da7219_fe_init,
 486                .trigger = {
 487                        SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 488                .dpcm_playback = 1,
 489                .ops = &broxton_da7219_fe_ops,
 490                SND_SOC_DAILINK_REG(system, dummy, platform),
 491        },
 492        [BXT_DPCM_AUDIO_CP] =
 493        {
 494                .name = "Bxt Audio Capture Port",
 495                .stream_name = "Audio Record",
 496                .dynamic = 1,
 497                .nonatomic = 1,
 498                .trigger = {
 499                        SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 500                .dpcm_capture = 1,
 501                .ops = &broxton_da7219_fe_ops,
 502                SND_SOC_DAILINK_REG(system, dummy, platform),
 503        },
 504        [BXT_DPCM_AUDIO_HS_PB] = {
 505                .name = "Bxt Audio Headset Playback",
 506                .stream_name = "Headset Playback",
 507                .dynamic = 1,
 508                .nonatomic = 1,
 509                .trigger = {
 510                        SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 511                .dpcm_playback = 1,
 512                .ops = &broxton_da7219_fe_ops,
 513                SND_SOC_DAILINK_REG(system2, dummy, platform),
 514        },
 515        [BXT_DPCM_AUDIO_REF_CP] =
 516        {
 517                .name = "Bxt Audio Reference cap",
 518                .stream_name = "Refcap",
 519                .init = NULL,
 520                .dpcm_capture = 1,
 521                .nonatomic = 1,
 522                .dynamic = 1,
 523                .ops = &broxton_refcap_ops,
 524                SND_SOC_DAILINK_REG(reference, dummy, platform),
 525        },
 526        [BXT_DPCM_AUDIO_DMIC_CP] =
 527        {
 528                .name = "Bxt Audio DMIC cap",
 529                .stream_name = "dmiccap",
 530                .init = NULL,
 531                .dpcm_capture = 1,
 532                .nonatomic = 1,
 533                .dynamic = 1,
 534                .ops = &broxton_dmic_ops,
 535                SND_SOC_DAILINK_REG(dmic, dummy, platform),
 536        },
 537        [BXT_DPCM_AUDIO_HDMI1_PB] =
 538        {
 539                .name = "Bxt HDMI Port1",
 540                .stream_name = "Hdmi1",
 541                .dpcm_playback = 1,
 542                .init = NULL,
 543                .nonatomic = 1,
 544                .dynamic = 1,
 545                SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
 546        },
 547        [BXT_DPCM_AUDIO_HDMI2_PB] =
 548        {
 549                .name = "Bxt HDMI Port2",
 550                .stream_name = "Hdmi2",
 551                .dpcm_playback = 1,
 552                .init = NULL,
 553                .nonatomic = 1,
 554                .dynamic = 1,
 555                SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
 556        },
 557        [BXT_DPCM_AUDIO_HDMI3_PB] =
 558        {
 559                .name = "Bxt HDMI Port3",
 560                .stream_name = "Hdmi3",
 561                .dpcm_playback = 1,
 562                .init = NULL,
 563                .nonatomic = 1,
 564                .dynamic = 1,
 565                SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
 566        },
 567        /* Back End DAI links */
 568        {
 569                /* SSP5 - Codec */
 570                .name = "SSP5-Codec",
 571                .id = 0,
 572                .no_pcm = 1,
 573                .dai_fmt = SND_SOC_DAIFMT_I2S |
 574                        SND_SOC_DAIFMT_NB_NF |
 575                        SND_SOC_DAIFMT_CBS_CFS,
 576                .ignore_pmdown_time = 1,
 577                .be_hw_params_fixup = broxton_ssp_fixup,
 578                .dpcm_playback = 1,
 579                SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform),
 580        },
 581        {
 582                /* SSP1 - Codec */
 583                .name = "SSP1-Codec",
 584                .id = 1,
 585                .no_pcm = 1,
 586                .init = broxton_da7219_codec_init,
 587                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 588                        SND_SOC_DAIFMT_CBS_CFS,
 589                .ignore_pmdown_time = 1,
 590                .be_hw_params_fixup = broxton_ssp_fixup,
 591                .dpcm_playback = 1,
 592                .dpcm_capture = 1,
 593                SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
 594        },
 595        {
 596                .name = "dmic01",
 597                .id = 2,
 598                .ignore_suspend = 1,
 599                .be_hw_params_fixup = broxton_dmic_fixup,
 600                .dpcm_capture = 1,
 601                .no_pcm = 1,
 602                SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
 603        },
 604        {
 605                .name = "iDisp1",
 606                .id = 3,
 607                .init = broxton_hdmi_init,
 608                .dpcm_playback = 1,
 609                .no_pcm = 1,
 610                SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
 611        },
 612        {
 613                .name = "iDisp2",
 614                .id = 4,
 615                .init = broxton_hdmi_init,
 616                .dpcm_playback = 1,
 617                .no_pcm = 1,
 618                SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
 619        },
 620        {
 621                .name = "iDisp3",
 622                .id = 5,
 623                .init = broxton_hdmi_init,
 624                .dpcm_playback = 1,
 625                .no_pcm = 1,
 626                SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
 627        },
 628        {
 629                .name = "dmic16k",
 630                .id = 6,
 631                .be_hw_params_fixup = broxton_dmic_fixup,
 632                .dpcm_capture = 1,
 633                .no_pcm = 1,
 634                SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
 635        },
 636};
 637
 638static struct snd_soc_codec_conf max98390_codec_confs[] = {
 639        {
 640                .dlc = COMP_CODEC_CONF(MAX98390_DEV0_NAME),
 641                .name_prefix = "Left",
 642        },
 643        {
 644                .dlc = COMP_CODEC_CONF(MAX98390_DEV1_NAME),
 645                .name_prefix = "Right",
 646        },
 647};
 648
 649#define NAME_SIZE       32
 650static int bxt_card_late_probe(struct snd_soc_card *card)
 651{
 652        struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card);
 653        struct bxt_hdmi_pcm *pcm;
 654        struct snd_soc_component *component = NULL;
 655        const struct snd_kcontrol_new *controls;
 656        const struct snd_soc_dapm_widget *widgets;
 657        const struct snd_soc_dapm_route *routes;
 658        int num_controls, num_widgets, num_routes, err, i = 0;
 659        char jack_name[NAME_SIZE];
 660
 661        switch (ctx->spkamp) {
 662        case SPKAMP_MAX98357A:
 663                controls = max98357a_controls;
 664                num_controls = ARRAY_SIZE(max98357a_controls);
 665                widgets = max98357a_widgets;
 666                num_widgets = ARRAY_SIZE(max98357a_widgets);
 667                routes = max98357a_routes;
 668                num_routes = ARRAY_SIZE(max98357a_routes);
 669                break;
 670        case SPKAMP_MAX98390:
 671                controls = max98390_controls;
 672                num_controls = ARRAY_SIZE(max98390_controls);
 673                widgets = max98390_widgets;
 674                num_widgets = ARRAY_SIZE(max98390_widgets);
 675                routes = max98390_routes;
 676                num_routes = ARRAY_SIZE(max98390_routes);
 677                break;
 678        default:
 679                dev_err(card->dev, "Invalid speaker amplifier %d\n", ctx->spkamp);
 680                return -EINVAL;
 681        }
 682
 683        err = snd_soc_dapm_new_controls(&card->dapm, widgets, num_widgets);
 684        if (err) {
 685                dev_err(card->dev, "Fail to new widgets\n");
 686                return err;
 687        }
 688
 689        err = snd_soc_add_card_controls(card, controls, num_controls);
 690        if (err) {
 691                dev_err(card->dev, "Fail to add controls\n");
 692                return err;
 693        }
 694
 695        err = snd_soc_dapm_add_routes(&card->dapm, routes, num_routes);
 696        if (err) {
 697                dev_err(card->dev, "Fail to add routes\n");
 698                return err;
 699        }
 700
 701        if (soc_intel_is_glk())
 702                snd_soc_dapm_add_routes(&card->dapm, gemini_map,
 703                                        ARRAY_SIZE(gemini_map));
 704        else
 705                snd_soc_dapm_add_routes(&card->dapm, broxton_map,
 706                                        ARRAY_SIZE(broxton_map));
 707
 708        if (list_empty(&ctx->hdmi_pcm_list))
 709                return -EINVAL;
 710
 711        if (ctx->common_hdmi_codec_drv) {
 712                pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
 713                                       head);
 714                component = pcm->codec_dai->component;
 715                return hda_dsp_hdmi_build_controls(card, component);
 716        }
 717
 718        list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
 719                component = pcm->codec_dai->component;
 720                snprintf(jack_name, sizeof(jack_name),
 721                        "HDMI/DP, pcm=%d Jack", pcm->device);
 722                err = snd_soc_card_jack_new(card, jack_name,
 723                                        SND_JACK_AVOUT, &broxton_hdmi[i],
 724                                        NULL, 0);
 725
 726                if (err)
 727                        return err;
 728
 729                err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
 730                                                &broxton_hdmi[i]);
 731                if (err < 0)
 732                        return err;
 733
 734                i++;
 735        }
 736
 737        return hdac_hdmi_jack_port_init(component, &card->dapm);
 738}
 739
 740/* broxton audio machine driver for SPT + da7219 */
 741static struct snd_soc_card broxton_audio_card = {
 742        .name = "bxtda7219max",
 743        .owner = THIS_MODULE,
 744        .dai_link = broxton_dais,
 745        .num_links = ARRAY_SIZE(broxton_dais),
 746        .controls = broxton_controls,
 747        .num_controls = ARRAY_SIZE(broxton_controls),
 748        .dapm_widgets = broxton_widgets,
 749        .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
 750        .dapm_routes = audio_map,
 751        .num_dapm_routes = ARRAY_SIZE(audio_map),
 752        .fully_routed = true,
 753        .late_probe = bxt_card_late_probe,
 754};
 755
 756static int broxton_audio_probe(struct platform_device *pdev)
 757{
 758        struct bxt_card_private *ctx;
 759        struct snd_soc_acpi_mach *mach;
 760        const char *platform_name;
 761        int ret;
 762
 763        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 764        if (!ctx)
 765                return -ENOMEM;
 766
 767        INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
 768
 769        if (acpi_dev_present("MX98390", NULL, -1))
 770                ctx->spkamp = SPKAMP_MAX98390;
 771        else
 772                ctx->spkamp = SPKAMP_MAX98357A;
 773
 774        broxton_audio_card.dev = &pdev->dev;
 775        snd_soc_card_set_drvdata(&broxton_audio_card, ctx);
 776        if (soc_intel_is_glk()) {
 777                unsigned int i;
 778
 779                broxton_audio_card.name = "glkda7219max";
 780                /* Fixup the SSP entries for geminilake */
 781                for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) {
 782                        /* MAXIM_CODEC is connected to SSP1. */
 783                        if (!strcmp(broxton_dais[i].codecs->dai_name,
 784                                    BXT_MAXIM_CODEC_DAI)) {
 785                                broxton_dais[i].name = "SSP1-Codec";
 786                                broxton_dais[i].cpus->dai_name = "SSP1 Pin";
 787                        }
 788                        /* DIALOG_CODE is connected to SSP2 */
 789                        else if (!strcmp(broxton_dais[i].codecs->dai_name,
 790                                         BXT_DIALOG_CODEC_DAI)) {
 791                                broxton_dais[i].name = "SSP2-Codec";
 792                                broxton_dais[i].cpus->dai_name = "SSP2 Pin";
 793                        }
 794                }
 795        } else if (soc_intel_is_cml()) {
 796                unsigned int i;
 797
 798                if (ctx->spkamp == SPKAMP_MAX98390) {
 799                        broxton_audio_card.name = "cml_max98390_da7219";
 800
 801                        broxton_audio_card.codec_conf = max98390_codec_confs;
 802                        broxton_audio_card.num_configs = ARRAY_SIZE(max98390_codec_confs);
 803                } else
 804                        broxton_audio_card.name = "cmlda7219max";
 805
 806                for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) {
 807                        /* MAXIM_CODEC is connected to SSP1. */
 808                        if (!strcmp(broxton_dais[i].codecs->dai_name,
 809                                        BXT_MAXIM_CODEC_DAI)) {
 810                                broxton_dais[i].name = "SSP1-Codec";
 811                                broxton_dais[i].cpus->dai_name = "SSP1 Pin";
 812
 813                                if (ctx->spkamp == SPKAMP_MAX98390) {
 814                                        broxton_dais[i].codecs = max98390_codec;
 815                                        broxton_dais[i].num_codecs = ARRAY_SIZE(max98390_codec);
 816                                }
 817                        }
 818                        /* DIALOG_CODEC is connected to SSP0 */
 819                        else if (!strcmp(broxton_dais[i].codecs->dai_name,
 820                                        BXT_DIALOG_CODEC_DAI)) {
 821                                broxton_dais[i].name = "SSP0-Codec";
 822                                broxton_dais[i].cpus->dai_name = "SSP0 Pin";
 823                        }
 824                }
 825        }
 826
 827        /* override plaform name, if required */
 828        mach = pdev->dev.platform_data;
 829        platform_name = mach->mach_params.platform;
 830
 831        ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card,
 832                                                    platform_name);
 833        if (ret)
 834                return ret;
 835
 836        ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
 837
 838        return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card);
 839}
 840
 841static const struct platform_device_id bxt_board_ids[] = {
 842        { .name = "bxt_da7219_max98357a" },
 843        { .name = "glk_da7219_max98357a" },
 844        { .name = "cml_da7219_max98357a" },
 845        { }
 846};
 847
 848static struct platform_driver broxton_audio = {
 849        .probe = broxton_audio_probe,
 850        .driver = {
 851                .name = "bxt_da7219_max98357a",
 852                .pm = &snd_soc_pm_ops,
 853        },
 854        .id_table = bxt_board_ids,
 855};
 856module_platform_driver(broxton_audio)
 857
 858/* Module information */
 859MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode");
 860MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>");
 861MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>");
 862MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
 863MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>");
 864MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
 865MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
 866MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
 867MODULE_LICENSE("GPL v2");
 868MODULE_ALIAS("platform:bxt_da7219_max98357a");
 869MODULE_ALIAS("platform:glk_da7219_max98357a");
 870MODULE_ALIAS("platform:cml_da7219_max98357a");
 871