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