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 <asm/cpu_device_id.h> 12 #include <linux/input.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <sound/core.h> 16 #include <sound/jack.h> 17 #include <sound/pcm.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 #include <sound/soc-acpi.h> 21 #include "../../codecs/hdac_hdmi.h" 22 #include "../../codecs/da7219.h" 23 #include "../../codecs/da7219-aad.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 static struct snd_soc_dai_link broxton_dais[] = { 369 /* Front End DAI links */ 370 [BXT_DPCM_AUDIO_PB] = 371 { 372 .name = "Bxt Audio Port", 373 .stream_name = "Audio", 374 .cpu_dai_name = "System Pin", 375 .platform_name = "0000:00:0e.0", 376 .dynamic = 1, 377 .codec_name = "snd-soc-dummy", 378 .codec_dai_name = "snd-soc-dummy-dai", 379 .nonatomic = 1, 380 .init = broxton_da7219_fe_init, 381 .trigger = { 382 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 383 .dpcm_playback = 1, 384 .ops = &broxton_da7219_fe_ops, 385 }, 386 [BXT_DPCM_AUDIO_CP] = 387 { 388 .name = "Bxt Audio Capture Port", 389 .stream_name = "Audio Record", 390 .cpu_dai_name = "System Pin", 391 .platform_name = "0000:00:0e.0", 392 .dynamic = 1, 393 .codec_name = "snd-soc-dummy", 394 .codec_dai_name = "snd-soc-dummy-dai", 395 .nonatomic = 1, 396 .trigger = { 397 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 398 .dpcm_capture = 1, 399 .ops = &broxton_da7219_fe_ops, 400 }, 401 [BXT_DPCM_AUDIO_HS_PB] = { 402 .name = "Bxt Audio Headset Playback", 403 .stream_name = "Headset Playback", 404 .cpu_dai_name = "System Pin2", 405 .platform_name = "0000:00:0e.0", 406 .dynamic = 1, 407 .codec_name = "snd-soc-dummy", 408 .codec_dai_name = "snd-soc-dummy-dai", 409 .nonatomic = 1, 410 .trigger = { 411 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 412 .dpcm_playback = 1, 413 .ops = &broxton_da7219_fe_ops, 414 }, 415 [BXT_DPCM_AUDIO_REF_CP] = 416 { 417 .name = "Bxt Audio Reference cap", 418 .stream_name = "Refcap", 419 .cpu_dai_name = "Reference Pin", 420 .codec_name = "snd-soc-dummy", 421 .codec_dai_name = "snd-soc-dummy-dai", 422 .platform_name = "0000:00:0e.0", 423 .init = NULL, 424 .dpcm_capture = 1, 425 .nonatomic = 1, 426 .dynamic = 1, 427 .ops = &broxton_refcap_ops, 428 }, 429 [BXT_DPCM_AUDIO_DMIC_CP] = 430 { 431 .name = "Bxt Audio DMIC cap", 432 .stream_name = "dmiccap", 433 .cpu_dai_name = "DMIC Pin", 434 .codec_name = "snd-soc-dummy", 435 .codec_dai_name = "snd-soc-dummy-dai", 436 .platform_name = "0000:00:0e.0", 437 .init = NULL, 438 .dpcm_capture = 1, 439 .nonatomic = 1, 440 .dynamic = 1, 441 .ops = &broxton_dmic_ops, 442 }, 443 [BXT_DPCM_AUDIO_HDMI1_PB] = 444 { 445 .name = "Bxt HDMI Port1", 446 .stream_name = "Hdmi1", 447 .cpu_dai_name = "HDMI1 Pin", 448 .codec_name = "snd-soc-dummy", 449 .codec_dai_name = "snd-soc-dummy-dai", 450 .platform_name = "0000:00:0e.0", 451 .dpcm_playback = 1, 452 .init = NULL, 453 .nonatomic = 1, 454 .dynamic = 1, 455 }, 456 [BXT_DPCM_AUDIO_HDMI2_PB] = 457 { 458 .name = "Bxt HDMI Port2", 459 .stream_name = "Hdmi2", 460 .cpu_dai_name = "HDMI2 Pin", 461 .codec_name = "snd-soc-dummy", 462 .codec_dai_name = "snd-soc-dummy-dai", 463 .platform_name = "0000:00:0e.0", 464 .dpcm_playback = 1, 465 .init = NULL, 466 .nonatomic = 1, 467 .dynamic = 1, 468 }, 469 [BXT_DPCM_AUDIO_HDMI3_PB] = 470 { 471 .name = "Bxt HDMI Port3", 472 .stream_name = "Hdmi3", 473 .cpu_dai_name = "HDMI3 Pin", 474 .codec_name = "snd-soc-dummy", 475 .codec_dai_name = "snd-soc-dummy-dai", 476 .platform_name = "0000:00:0e.0", 477 .dpcm_playback = 1, 478 .init = NULL, 479 .nonatomic = 1, 480 .dynamic = 1, 481 }, 482 /* Back End DAI links */ 483 { 484 /* SSP5 - Codec */ 485 .name = "SSP5-Codec", 486 .id = 0, 487 .cpu_dai_name = "SSP5 Pin", 488 .platform_name = "0000:00:0e.0", 489 .no_pcm = 1, 490 .codec_name = "MX98357A:00", 491 .codec_dai_name = BXT_MAXIM_CODEC_DAI, 492 .dai_fmt = SND_SOC_DAIFMT_I2S | 493 SND_SOC_DAIFMT_NB_NF | 494 SND_SOC_DAIFMT_CBS_CFS, 495 .ignore_pmdown_time = 1, 496 .be_hw_params_fixup = broxton_ssp_fixup, 497 .dpcm_playback = 1, 498 }, 499 { 500 /* SSP1 - Codec */ 501 .name = "SSP1-Codec", 502 .id = 1, 503 .cpu_dai_name = "SSP1 Pin", 504 .platform_name = "0000:00:0e.0", 505 .no_pcm = 1, 506 .codec_name = "i2c-DLGS7219:00", 507 .codec_dai_name = BXT_DIALOG_CODEC_DAI, 508 .init = broxton_da7219_codec_init, 509 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 510 SND_SOC_DAIFMT_CBS_CFS, 511 .ignore_pmdown_time = 1, 512 .be_hw_params_fixup = broxton_ssp_fixup, 513 .dpcm_playback = 1, 514 .dpcm_capture = 1, 515 }, 516 { 517 .name = "dmic01", 518 .id = 2, 519 .cpu_dai_name = "DMIC01 Pin", 520 .codec_name = "dmic-codec", 521 .codec_dai_name = "dmic-hifi", 522 .platform_name = "0000:00:0e.0", 523 .ignore_suspend = 1, 524 .be_hw_params_fixup = broxton_dmic_fixup, 525 .dpcm_capture = 1, 526 .no_pcm = 1, 527 }, 528 { 529 .name = "iDisp1", 530 .id = 3, 531 .cpu_dai_name = "iDisp1 Pin", 532 .codec_name = "ehdaudio0D2", 533 .codec_dai_name = "intel-hdmi-hifi1", 534 .platform_name = "0000:00:0e.0", 535 .init = broxton_hdmi_init, 536 .dpcm_playback = 1, 537 .no_pcm = 1, 538 }, 539 { 540 .name = "iDisp2", 541 .id = 4, 542 .cpu_dai_name = "iDisp2 Pin", 543 .codec_name = "ehdaudio0D2", 544 .codec_dai_name = "intel-hdmi-hifi2", 545 .platform_name = "0000:00:0e.0", 546 .init = broxton_hdmi_init, 547 .dpcm_playback = 1, 548 .no_pcm = 1, 549 }, 550 { 551 .name = "iDisp3", 552 .id = 5, 553 .cpu_dai_name = "iDisp3 Pin", 554 .codec_name = "ehdaudio0D2", 555 .codec_dai_name = "intel-hdmi-hifi3", 556 .platform_name = "0000:00:0e.0", 557 .init = broxton_hdmi_init, 558 .dpcm_playback = 1, 559 .no_pcm = 1, 560 }, 561 }; 562 563 static const struct x86_cpu_id glk_ids[] = { 564 { X86_VENDOR_INTEL, 6, 0x7A }, /* Geminilake CPU_ID */ 565 {} 566 }; 567 568 #define NAME_SIZE 32 569 static int bxt_card_late_probe(struct snd_soc_card *card) 570 { 571 struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); 572 struct bxt_hdmi_pcm *pcm; 573 struct snd_soc_component *component = NULL; 574 int err, i = 0; 575 char jack_name[NAME_SIZE]; 576 577 if (x86_match_cpu(glk_ids)) 578 snd_soc_dapm_add_routes(&card->dapm, gemini_map, 579 ARRAY_SIZE(gemini_map)); 580 else 581 snd_soc_dapm_add_routes(&card->dapm, broxton_map, 582 ARRAY_SIZE(broxton_map)); 583 584 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 585 component = pcm->codec_dai->component; 586 snprintf(jack_name, sizeof(jack_name), 587 "HDMI/DP, pcm=%d Jack", pcm->device); 588 err = snd_soc_card_jack_new(card, jack_name, 589 SND_JACK_AVOUT, &broxton_hdmi[i], 590 NULL, 0); 591 592 if (err) 593 return err; 594 595 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, 596 &broxton_hdmi[i]); 597 if (err < 0) 598 return err; 599 600 i++; 601 } 602 603 if (!component) 604 return -EINVAL; 605 606 return hdac_hdmi_jack_port_init(component, &card->dapm); 607 } 608 609 /* broxton audio machine driver for SPT + da7219 */ 610 static struct snd_soc_card broxton_audio_card = { 611 .name = "bxtda7219max", 612 .owner = THIS_MODULE, 613 .dai_link = broxton_dais, 614 .num_links = ARRAY_SIZE(broxton_dais), 615 .controls = broxton_controls, 616 .num_controls = ARRAY_SIZE(broxton_controls), 617 .dapm_widgets = broxton_widgets, 618 .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), 619 .dapm_routes = audio_map, 620 .num_dapm_routes = ARRAY_SIZE(audio_map), 621 .fully_routed = true, 622 .late_probe = bxt_card_late_probe, 623 }; 624 625 static int broxton_audio_probe(struct platform_device *pdev) 626 { 627 struct bxt_card_private *ctx; 628 struct snd_soc_acpi_mach *mach; 629 const char *platform_name; 630 int ret; 631 632 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 633 if (!ctx) 634 return -ENOMEM; 635 636 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 637 638 broxton_audio_card.dev = &pdev->dev; 639 snd_soc_card_set_drvdata(&broxton_audio_card, ctx); 640 if (x86_match_cpu(glk_ids)) { 641 unsigned int i; 642 643 broxton_audio_card.name = "glkda7219max"; 644 /* Fixup the SSP entries for geminilake */ 645 for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { 646 /* MAXIM_CODEC is connected to SSP1. */ 647 if (!strcmp(broxton_dais[i].codec_dai_name, 648 BXT_MAXIM_CODEC_DAI)) { 649 broxton_dais[i].name = "SSP1-Codec"; 650 broxton_dais[i].cpu_dai_name = "SSP1 Pin"; 651 } 652 /* DIALOG_CODE is connected to SSP2 */ 653 else if (!strcmp(broxton_dais[i].codec_dai_name, 654 BXT_DIALOG_CODEC_DAI)) { 655 broxton_dais[i].name = "SSP2-Codec"; 656 broxton_dais[i].cpu_dai_name = "SSP2 Pin"; 657 } 658 } 659 } 660 661 /* override plaform name, if required */ 662 mach = (&pdev->dev)->platform_data; 663 platform_name = mach->mach_params.platform; 664 665 ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card, 666 platform_name); 667 if (ret) 668 return ret; 669 670 return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card); 671 } 672 673 static const struct platform_device_id bxt_board_ids[] = { 674 { .name = "bxt_da7219_max98357a" }, 675 { .name = "glk_da7219_max98357a" }, 676 { } 677 }; 678 679 static struct platform_driver broxton_audio = { 680 .probe = broxton_audio_probe, 681 .driver = { 682 .name = "bxt_da7219_max98357a", 683 .pm = &snd_soc_pm_ops, 684 }, 685 .id_table = bxt_board_ids, 686 }; 687 module_platform_driver(broxton_audio) 688 689 /* Module information */ 690 MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); 691 MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>"); 692 MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>"); 693 MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); 694 MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); 695 MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); 696 MODULE_LICENSE("GPL v2"); 697 MODULE_ALIAS("platform:bxt_da7219_max98357a"); 698 MODULE_ALIAS("platform:glk_da7219_max98357a"); 699