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 int clk_freq; 183 184 /* Configure sysclk for codec */ 185 if (soc_intel_is_cml()) 186 clk_freq = 24000000; 187 else 188 clk_freq = 19200000; 189 190 ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq, 191 SND_SOC_CLOCK_IN); 192 193 if (ret) { 194 dev_err(rtd->dev, "can't set codec sysclk configuration\n"); 195 return ret; 196 } 197 198 /* 199 * Headset buttons map to the google Reference headset. 200 * These can be configured by userspace. 201 */ 202 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", 203 SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | 204 SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, 205 &broxton_headset, NULL, 0); 206 if (ret) { 207 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 208 return ret; 209 } 210 211 snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 212 snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); 213 snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); 214 snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_3, 215 KEY_VOICECOMMAND); 216 217 da7219_aad_jack_det(component, &broxton_headset); 218 219 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); 220 221 return ret; 222 } 223 224 static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) 225 { 226 struct bxt_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 227 struct snd_soc_dai *dai = rtd->codec_dai; 228 struct bxt_hdmi_pcm *pcm; 229 230 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 231 if (!pcm) 232 return -ENOMEM; 233 234 pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; 235 pcm->codec_dai = dai; 236 237 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 238 239 return 0; 240 } 241 242 static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) 243 { 244 struct snd_soc_dapm_context *dapm; 245 struct snd_soc_component *component = rtd->cpu_dai->component; 246 247 dapm = snd_soc_component_get_dapm(component); 248 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); 249 250 return 0; 251 } 252 253 static const unsigned int rates[] = { 254 48000, 255 }; 256 257 static const struct snd_pcm_hw_constraint_list constraints_rates = { 258 .count = ARRAY_SIZE(rates), 259 .list = rates, 260 .mask = 0, 261 }; 262 263 static const unsigned int channels[] = { 264 DUAL_CHANNEL, 265 }; 266 267 static const struct snd_pcm_hw_constraint_list constraints_channels = { 268 .count = ARRAY_SIZE(channels), 269 .list = channels, 270 .mask = 0, 271 }; 272 273 static const unsigned int channels_quad[] = { 274 QUAD_CHANNEL, 275 }; 276 277 static const struct snd_pcm_hw_constraint_list constraints_channels_quad = { 278 .count = ARRAY_SIZE(channels_quad), 279 .list = channels_quad, 280 .mask = 0, 281 }; 282 283 static int bxt_fe_startup(struct snd_pcm_substream *substream) 284 { 285 struct snd_pcm_runtime *runtime = substream->runtime; 286 287 /* 288 * On this platform for PCM device we support, 289 * 48Khz 290 * stereo 291 * 16 bit audio 292 */ 293 294 runtime->hw.channels_max = DUAL_CHANNEL; 295 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 296 &constraints_channels); 297 298 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 299 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 300 301 snd_pcm_hw_constraint_list(runtime, 0, 302 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 303 304 return 0; 305 } 306 307 static const struct snd_soc_ops broxton_da7219_fe_ops = { 308 .startup = bxt_fe_startup, 309 }; 310 311 static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, 312 struct snd_pcm_hw_params *params) 313 { 314 struct snd_interval *channels = hw_param_interval(params, 315 SNDRV_PCM_HW_PARAM_CHANNELS); 316 if (params_channels(params) == 2) 317 channels->min = channels->max = 2; 318 else 319 channels->min = channels->max = 4; 320 321 return 0; 322 } 323 324 static int broxton_dmic_startup(struct snd_pcm_substream *substream) 325 { 326 struct snd_pcm_runtime *runtime = substream->runtime; 327 328 runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; 329 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 330 &constraints_channels_quad); 331 332 return snd_pcm_hw_constraint_list(substream->runtime, 0, 333 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 334 } 335 336 static const struct snd_soc_ops broxton_dmic_ops = { 337 .startup = broxton_dmic_startup, 338 }; 339 340 static const unsigned int rates_16000[] = { 341 16000, 342 }; 343 344 static const struct snd_pcm_hw_constraint_list constraints_16000 = { 345 .count = ARRAY_SIZE(rates_16000), 346 .list = rates_16000, 347 }; 348 349 static const unsigned int ch_mono[] = { 350 1, 351 }; 352 353 static const struct snd_pcm_hw_constraint_list constraints_refcap = { 354 .count = ARRAY_SIZE(ch_mono), 355 .list = ch_mono, 356 }; 357 358 static int broxton_refcap_startup(struct snd_pcm_substream *substream) 359 { 360 substream->runtime->hw.channels_max = 1; 361 snd_pcm_hw_constraint_list(substream->runtime, 0, 362 SNDRV_PCM_HW_PARAM_CHANNELS, 363 &constraints_refcap); 364 365 return snd_pcm_hw_constraint_list(substream->runtime, 0, 366 SNDRV_PCM_HW_PARAM_RATE, 367 &constraints_16000); 368 }; 369 370 static const struct snd_soc_ops broxton_refcap_ops = { 371 .startup = broxton_refcap_startup, 372 }; 373 374 /* broxton digital audio interface glue - connects codec <--> CPU */ 375 SND_SOC_DAILINK_DEF(dummy, 376 DAILINK_COMP_ARRAY(COMP_DUMMY())); 377 378 SND_SOC_DAILINK_DEF(system, 379 DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); 380 381 SND_SOC_DAILINK_DEF(system2, 382 DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); 383 384 SND_SOC_DAILINK_DEF(reference, 385 DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); 386 387 SND_SOC_DAILINK_DEF(dmic, 388 DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); 389 390 SND_SOC_DAILINK_DEF(hdmi1, 391 DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); 392 393 SND_SOC_DAILINK_DEF(hdmi2, 394 DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); 395 396 SND_SOC_DAILINK_DEF(hdmi3, 397 DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); 398 399 /* Back End DAI */ 400 SND_SOC_DAILINK_DEF(ssp5_pin, 401 DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin"))); 402 SND_SOC_DAILINK_DEF(ssp5_codec, 403 DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", 404 BXT_MAXIM_CODEC_DAI))); 405 406 SND_SOC_DAILINK_DEF(ssp1_pin, 407 DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); 408 SND_SOC_DAILINK_DEF(ssp1_codec, 409 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", 410 BXT_DIALOG_CODEC_DAI))); 411 412 SND_SOC_DAILINK_DEF(dmic_pin, 413 DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); 414 415 SND_SOC_DAILINK_DEF(dmic16k_pin, 416 DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); 417 418 SND_SOC_DAILINK_DEF(dmic_codec, 419 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 420 421 SND_SOC_DAILINK_DEF(idisp1_pin, 422 DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); 423 SND_SOC_DAILINK_DEF(idisp1_codec, 424 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); 425 426 SND_SOC_DAILINK_DEF(idisp2_pin, 427 DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); 428 SND_SOC_DAILINK_DEF(idisp2_codec, 429 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", 430 "intel-hdmi-hifi2"))); 431 432 SND_SOC_DAILINK_DEF(idisp3_pin, 433 DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); 434 SND_SOC_DAILINK_DEF(idisp3_codec, 435 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", 436 "intel-hdmi-hifi3"))); 437 438 SND_SOC_DAILINK_DEF(platform, 439 DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); 440 441 static struct snd_soc_dai_link broxton_dais[] = { 442 /* Front End DAI links */ 443 [BXT_DPCM_AUDIO_PB] = 444 { 445 .name = "Bxt Audio Port", 446 .stream_name = "Audio", 447 .dynamic = 1, 448 .nonatomic = 1, 449 .init = broxton_da7219_fe_init, 450 .trigger = { 451 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 452 .dpcm_playback = 1, 453 .ops = &broxton_da7219_fe_ops, 454 SND_SOC_DAILINK_REG(system, dummy, platform), 455 }, 456 [BXT_DPCM_AUDIO_CP] = 457 { 458 .name = "Bxt Audio Capture Port", 459 .stream_name = "Audio Record", 460 .dynamic = 1, 461 .nonatomic = 1, 462 .trigger = { 463 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 464 .dpcm_capture = 1, 465 .ops = &broxton_da7219_fe_ops, 466 SND_SOC_DAILINK_REG(system, dummy, platform), 467 }, 468 [BXT_DPCM_AUDIO_HS_PB] = { 469 .name = "Bxt Audio Headset Playback", 470 .stream_name = "Headset Playback", 471 .dynamic = 1, 472 .nonatomic = 1, 473 .trigger = { 474 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 475 .dpcm_playback = 1, 476 .ops = &broxton_da7219_fe_ops, 477 SND_SOC_DAILINK_REG(system2, dummy, platform), 478 }, 479 [BXT_DPCM_AUDIO_REF_CP] = 480 { 481 .name = "Bxt Audio Reference cap", 482 .stream_name = "Refcap", 483 .init = NULL, 484 .dpcm_capture = 1, 485 .nonatomic = 1, 486 .dynamic = 1, 487 .ops = &broxton_refcap_ops, 488 SND_SOC_DAILINK_REG(reference, dummy, platform), 489 }, 490 [BXT_DPCM_AUDIO_DMIC_CP] = 491 { 492 .name = "Bxt Audio DMIC cap", 493 .stream_name = "dmiccap", 494 .init = NULL, 495 .dpcm_capture = 1, 496 .nonatomic = 1, 497 .dynamic = 1, 498 .ops = &broxton_dmic_ops, 499 SND_SOC_DAILINK_REG(dmic, dummy, platform), 500 }, 501 [BXT_DPCM_AUDIO_HDMI1_PB] = 502 { 503 .name = "Bxt HDMI Port1", 504 .stream_name = "Hdmi1", 505 .dpcm_playback = 1, 506 .init = NULL, 507 .nonatomic = 1, 508 .dynamic = 1, 509 SND_SOC_DAILINK_REG(hdmi1, dummy, platform), 510 }, 511 [BXT_DPCM_AUDIO_HDMI2_PB] = 512 { 513 .name = "Bxt HDMI Port2", 514 .stream_name = "Hdmi2", 515 .dpcm_playback = 1, 516 .init = NULL, 517 .nonatomic = 1, 518 .dynamic = 1, 519 SND_SOC_DAILINK_REG(hdmi2, dummy, platform), 520 }, 521 [BXT_DPCM_AUDIO_HDMI3_PB] = 522 { 523 .name = "Bxt HDMI Port3", 524 .stream_name = "Hdmi3", 525 .dpcm_playback = 1, 526 .init = NULL, 527 .nonatomic = 1, 528 .dynamic = 1, 529 SND_SOC_DAILINK_REG(hdmi3, dummy, platform), 530 }, 531 /* Back End DAI links */ 532 { 533 /* SSP5 - Codec */ 534 .name = "SSP5-Codec", 535 .id = 0, 536 .no_pcm = 1, 537 .dai_fmt = SND_SOC_DAIFMT_I2S | 538 SND_SOC_DAIFMT_NB_NF | 539 SND_SOC_DAIFMT_CBS_CFS, 540 .ignore_pmdown_time = 1, 541 .be_hw_params_fixup = broxton_ssp_fixup, 542 .dpcm_playback = 1, 543 SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), 544 }, 545 { 546 /* SSP1 - Codec */ 547 .name = "SSP1-Codec", 548 .id = 1, 549 .no_pcm = 1, 550 .init = broxton_da7219_codec_init, 551 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 552 SND_SOC_DAIFMT_CBS_CFS, 553 .ignore_pmdown_time = 1, 554 .be_hw_params_fixup = broxton_ssp_fixup, 555 .dpcm_playback = 1, 556 .dpcm_capture = 1, 557 SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), 558 }, 559 { 560 .name = "dmic01", 561 .id = 2, 562 .ignore_suspend = 1, 563 .be_hw_params_fixup = broxton_dmic_fixup, 564 .dpcm_capture = 1, 565 .no_pcm = 1, 566 SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), 567 }, 568 { 569 .name = "iDisp1", 570 .id = 3, 571 .init = broxton_hdmi_init, 572 .dpcm_playback = 1, 573 .no_pcm = 1, 574 SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), 575 }, 576 { 577 .name = "iDisp2", 578 .id = 4, 579 .init = broxton_hdmi_init, 580 .dpcm_playback = 1, 581 .no_pcm = 1, 582 SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), 583 }, 584 { 585 .name = "iDisp3", 586 .id = 5, 587 .init = broxton_hdmi_init, 588 .dpcm_playback = 1, 589 .no_pcm = 1, 590 SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), 591 }, 592 { 593 .name = "dmic16k", 594 .id = 6, 595 .be_hw_params_fixup = broxton_dmic_fixup, 596 .dpcm_capture = 1, 597 .no_pcm = 1, 598 SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), 599 }, 600 }; 601 602 #define NAME_SIZE 32 603 static int bxt_card_late_probe(struct snd_soc_card *card) 604 { 605 struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); 606 struct bxt_hdmi_pcm *pcm; 607 struct snd_soc_component *component = NULL; 608 int err, i = 0; 609 char jack_name[NAME_SIZE]; 610 611 if (soc_intel_is_glk()) 612 snd_soc_dapm_add_routes(&card->dapm, gemini_map, 613 ARRAY_SIZE(gemini_map)); 614 else 615 snd_soc_dapm_add_routes(&card->dapm, broxton_map, 616 ARRAY_SIZE(broxton_map)); 617 618 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 619 component = pcm->codec_dai->component; 620 snprintf(jack_name, sizeof(jack_name), 621 "HDMI/DP, pcm=%d Jack", pcm->device); 622 err = snd_soc_card_jack_new(card, jack_name, 623 SND_JACK_AVOUT, &broxton_hdmi[i], 624 NULL, 0); 625 626 if (err) 627 return err; 628 629 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, 630 &broxton_hdmi[i]); 631 if (err < 0) 632 return err; 633 634 i++; 635 } 636 637 if (!component) 638 return -EINVAL; 639 640 return hdac_hdmi_jack_port_init(component, &card->dapm); 641 } 642 643 /* broxton audio machine driver for SPT + da7219 */ 644 static struct snd_soc_card broxton_audio_card = { 645 .name = "bxtda7219max", 646 .owner = THIS_MODULE, 647 .dai_link = broxton_dais, 648 .num_links = ARRAY_SIZE(broxton_dais), 649 .controls = broxton_controls, 650 .num_controls = ARRAY_SIZE(broxton_controls), 651 .dapm_widgets = broxton_widgets, 652 .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), 653 .dapm_routes = audio_map, 654 .num_dapm_routes = ARRAY_SIZE(audio_map), 655 .fully_routed = true, 656 .late_probe = bxt_card_late_probe, 657 }; 658 659 static int broxton_audio_probe(struct platform_device *pdev) 660 { 661 struct bxt_card_private *ctx; 662 struct snd_soc_acpi_mach *mach; 663 const char *platform_name; 664 int ret; 665 666 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 667 if (!ctx) 668 return -ENOMEM; 669 670 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 671 672 broxton_audio_card.dev = &pdev->dev; 673 snd_soc_card_set_drvdata(&broxton_audio_card, ctx); 674 if (soc_intel_is_glk()) { 675 unsigned int i; 676 677 broxton_audio_card.name = "glkda7219max"; 678 /* Fixup the SSP entries for geminilake */ 679 for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { 680 /* MAXIM_CODEC is connected to SSP1. */ 681 if (!strcmp(broxton_dais[i].codecs->dai_name, 682 BXT_MAXIM_CODEC_DAI)) { 683 broxton_dais[i].name = "SSP1-Codec"; 684 broxton_dais[i].cpus->dai_name = "SSP1 Pin"; 685 } 686 /* DIALOG_CODE is connected to SSP2 */ 687 else if (!strcmp(broxton_dais[i].codecs->dai_name, 688 BXT_DIALOG_CODEC_DAI)) { 689 broxton_dais[i].name = "SSP2-Codec"; 690 broxton_dais[i].cpus->dai_name = "SSP2 Pin"; 691 } 692 } 693 } else if (soc_intel_is_cml()) { 694 unsigned int i; 695 696 broxton_audio_card.name = "cmlda7219max"; 697 698 for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { 699 /* MAXIM_CODEC is connected to SSP1. */ 700 if (!strcmp(broxton_dais[i].codecs->dai_name, 701 BXT_MAXIM_CODEC_DAI)) { 702 broxton_dais[i].name = "SSP1-Codec"; 703 broxton_dais[i].cpus->dai_name = "SSP1 Pin"; 704 } 705 /* DIALOG_CODEC is connected to SSP0 */ 706 else if (!strcmp(broxton_dais[i].codecs->dai_name, 707 BXT_DIALOG_CODEC_DAI)) { 708 broxton_dais[i].name = "SSP0-Codec"; 709 broxton_dais[i].cpus->dai_name = "SSP0 Pin"; 710 } 711 } 712 } 713 714 /* override plaform name, if required */ 715 mach = (&pdev->dev)->platform_data; 716 platform_name = mach->mach_params.platform; 717 718 ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card, 719 platform_name); 720 if (ret) 721 return ret; 722 723 return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card); 724 } 725 726 static const struct platform_device_id bxt_board_ids[] = { 727 { .name = "bxt_da7219_max98357a" }, 728 { .name = "glk_da7219_max98357a" }, 729 { .name = "cml_da7219_max98357a" }, 730 { } 731 }; 732 733 static struct platform_driver broxton_audio = { 734 .probe = broxton_audio_probe, 735 .driver = { 736 .name = "bxt_da7219_max98357a", 737 .pm = &snd_soc_pm_ops, 738 }, 739 .id_table = bxt_board_ids, 740 }; 741 module_platform_driver(broxton_audio) 742 743 /* Module information */ 744 MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); 745 MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>"); 746 MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>"); 747 MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); 748 MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); 749 MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); 750 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); 751 MODULE_LICENSE("GPL v2"); 752 MODULE_ALIAS("platform:bxt_da7219_max98357a"); 753 MODULE_ALIAS("platform:glk_da7219_max98357a"); 754 MODULE_ALIAS("platform:cml_da7219_max98357a"); 755