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