1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (c) 2020 Intel Corporation 3 4 /* 5 * sof_sdw - ASOC Machine driver for Intel SoundWire platforms 6 */ 7 8 #include <linux/device.h> 9 #include <linux/dmi.h> 10 #include <linux/module.h> 11 #include <linux/soundwire/sdw.h> 12 #include <linux/soundwire/sdw_type.h> 13 #include <sound/soc.h> 14 #include <sound/soc-acpi.h> 15 #include "sof_sdw_common.h" 16 #include "../../codecs/rt711.h" 17 18 unsigned long sof_sdw_quirk = RT711_JD1; 19 static int quirk_override = -1; 20 module_param_named(quirk, quirk_override, int, 0444); 21 MODULE_PARM_DESC(quirk, "Board-specific quirk override"); 22 23 #define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0) 24 25 static void log_quirks(struct device *dev) 26 { 27 if (SOF_RT711_JDSRC(sof_sdw_quirk)) 28 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", 29 SOF_RT711_JDSRC(sof_sdw_quirk)); 30 if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 31 dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); 32 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 33 dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); 34 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) 35 dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); 36 if (SOF_SSP_GET_PORT(sof_sdw_quirk)) 37 dev_dbg(dev, "SSP port %ld\n", 38 SOF_SSP_GET_PORT(sof_sdw_quirk)); 39 if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) 40 dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); 41 } 42 43 static int sof_sdw_quirk_cb(const struct dmi_system_id *id) 44 { 45 sof_sdw_quirk = (unsigned long)id->driver_data; 46 return 1; 47 } 48 49 static const struct dmi_system_id sof_sdw_quirk_table[] = { 50 /* CometLake devices */ 51 { 52 .callback = sof_sdw_quirk_cb, 53 .matches = { 54 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 55 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), 56 }, 57 .driver_data = (void *)SOF_SDW_PCH_DMIC, 58 }, 59 { 60 .callback = sof_sdw_quirk_cb, 61 .matches = { 62 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 63 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 64 }, 65 .driver_data = (void *)RT711_JD2, 66 }, 67 { 68 /* early version of SKU 09C6 */ 69 .callback = sof_sdw_quirk_cb, 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 72 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 73 }, 74 .driver_data = (void *)RT711_JD2, 75 }, 76 { 77 .callback = sof_sdw_quirk_cb, 78 .matches = { 79 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 80 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 81 }, 82 .driver_data = (void *)(RT711_JD2 | 83 SOF_SDW_FOUR_SPK), 84 }, 85 { 86 .callback = sof_sdw_quirk_cb, 87 .matches = { 88 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 89 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 90 }, 91 .driver_data = (void *)(RT711_JD2 | 92 SOF_SDW_FOUR_SPK), 93 }, 94 /* IceLake devices */ 95 { 96 .callback = sof_sdw_quirk_cb, 97 .matches = { 98 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 99 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), 100 }, 101 .driver_data = (void *)SOF_SDW_PCH_DMIC, 102 }, 103 /* TigerLake devices */ 104 { 105 .callback = sof_sdw_quirk_cb, 106 .matches = { 107 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 108 DMI_MATCH(DMI_PRODUCT_NAME, 109 "Tiger Lake Client Platform"), 110 }, 111 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 112 RT711_JD1 | 113 SOF_SDW_PCH_DMIC | 114 SOF_SSP_PORT(SOF_I2S_SSP2)), 115 }, 116 { 117 .callback = sof_sdw_quirk_cb, 118 .matches = { 119 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 120 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") 121 }, 122 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 123 RT711_JD2), 124 }, 125 { 126 /* another SKU of Dell Latitude 9520 */ 127 .callback = sof_sdw_quirk_cb, 128 .matches = { 129 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 130 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F") 131 }, 132 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 133 RT711_JD2), 134 }, 135 { 136 /* Dell XPS 9710 */ 137 .callback = sof_sdw_quirk_cb, 138 .matches = { 139 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 140 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") 141 }, 142 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 143 RT711_JD2 | 144 SOF_SDW_FOUR_SPK), 145 }, 146 { 147 .callback = sof_sdw_quirk_cb, 148 .matches = { 149 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 150 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") 151 }, 152 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 153 RT711_JD2 | 154 SOF_SDW_FOUR_SPK), 155 }, 156 { 157 .callback = sof_sdw_quirk_cb, 158 .matches = { 159 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 160 DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), 161 }, 162 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 163 SOF_SDW_PCH_DMIC | 164 SOF_SDW_FOUR_SPK | 165 SOF_BT_OFFLOAD_SSP(2) | 166 SOF_SSP_BT_OFFLOAD_PRESENT), 167 }, 168 { 169 .callback = sof_sdw_quirk_cb, 170 .matches = { 171 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 172 DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), 173 }, 174 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 175 SOF_SDW_PCH_DMIC | 176 SOF_SDW_FOUR_SPK), 177 }, 178 { 179 /* 180 * this entry covers multiple HP SKUs. The family name 181 * does not seem robust enough, so we use a partial 182 * match that ignores the product name suffix 183 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) 184 */ 185 .callback = sof_sdw_quirk_cb, 186 .matches = { 187 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 188 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"), 189 }, 190 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 191 SOF_SDW_PCH_DMIC | 192 RT711_JD1), 193 }, 194 { 195 /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */ 196 .callback = sof_sdw_quirk_cb, 197 .matches = { 198 DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 199 DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"), 200 }, 201 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 202 SOF_SDW_PCH_DMIC | 203 RT711_JD1), 204 }, 205 { 206 /* NUC15 LAPBC710 skews */ 207 .callback = sof_sdw_quirk_cb, 208 .matches = { 209 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 210 DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"), 211 }, 212 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 213 SOF_SDW_PCH_DMIC | 214 RT711_JD1), 215 }, 216 /* TigerLake-SDCA devices */ 217 { 218 .callback = sof_sdw_quirk_cb, 219 .matches = { 220 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 221 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") 222 }, 223 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 224 RT711_JD2 | 225 SOF_SDW_FOUR_SPK), 226 }, 227 { 228 .callback = sof_sdw_quirk_cb, 229 .matches = { 230 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 231 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45") 232 }, 233 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 234 RT711_JD2), 235 }, 236 /* AlderLake devices */ 237 { 238 .callback = sof_sdw_quirk_cb, 239 .matches = { 240 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 241 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), 242 }, 243 .driver_data = (void *)(RT711_JD2_100K | 244 SOF_SDW_TGL_HDMI | 245 SOF_BT_OFFLOAD_SSP(2) | 246 SOF_SSP_BT_OFFLOAD_PRESENT), 247 }, 248 { 249 .callback = sof_sdw_quirk_cb, 250 .matches = { 251 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 252 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), 253 }, 254 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 255 SOF_SDW_PCH_DMIC | 256 SOF_SDW_FOUR_SPK | 257 SOF_BT_OFFLOAD_SSP(2) | 258 SOF_SSP_BT_OFFLOAD_PRESENT), 259 }, 260 { 261 .callback = sof_sdw_quirk_cb, 262 .matches = { 263 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 264 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0") 265 }, 266 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 267 RT711_JD2 | 268 SOF_SDW_FOUR_SPK), 269 }, 270 { 271 .callback = sof_sdw_quirk_cb, 272 .matches = { 273 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 274 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"), 275 }, 276 /* No Jack */ 277 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 278 SOF_SDW_FOUR_SPK), 279 }, 280 { 281 .callback = sof_sdw_quirk_cb, 282 .matches = { 283 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 284 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") 285 }, 286 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 287 RT711_JD2 | 288 SOF_SDW_FOUR_SPK), 289 }, 290 { 291 .callback = sof_sdw_quirk_cb, 292 .matches = { 293 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 294 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") 295 }, 296 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 297 RT711_JD2 | 298 SOF_SDW_FOUR_SPK), 299 }, 300 { 301 .callback = sof_sdw_quirk_cb, 302 .matches = { 303 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 304 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") 305 }, 306 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 307 RT711_JD2 | 308 SOF_SDW_FOUR_SPK), 309 }, 310 { 311 .callback = sof_sdw_quirk_cb, 312 .matches = { 313 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 314 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11") 315 }, 316 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 317 RT711_JD2 | 318 SOF_SDW_FOUR_SPK), 319 }, 320 { 321 .callback = sof_sdw_quirk_cb, 322 .matches = { 323 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 324 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12") 325 }, 326 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 327 RT711_JD2 | 328 SOF_SDW_FOUR_SPK), 329 }, 330 { 331 .callback = sof_sdw_quirk_cb, 332 .matches = { 333 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 334 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"), 335 }, 336 /* No Jack */ 337 .driver_data = (void *)SOF_SDW_TGL_HDMI, 338 }, 339 { 340 .callback = sof_sdw_quirk_cb, 341 .matches = { 342 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 343 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"), 344 }, 345 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 346 RT711_JD2 | 347 SOF_SDW_FOUR_SPK), 348 }, 349 { 350 .callback = sof_sdw_quirk_cb, 351 .matches = { 352 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 353 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"), 354 }, 355 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 356 RT711_JD2), 357 }, 358 /* RaptorLake devices */ 359 { 360 .callback = sof_sdw_quirk_cb, 361 .matches = { 362 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 363 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"), 364 }, 365 /* No Jack */ 366 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 367 SOF_SDW_FOUR_SPK), 368 }, 369 { 370 .callback = sof_sdw_quirk_cb, 371 .matches = { 372 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 373 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11") 374 }, 375 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 376 RT711_JD2 | 377 SOF_SDW_FOUR_SPK), 378 }, 379 { 380 .callback = sof_sdw_quirk_cb, 381 .matches = { 382 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 383 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40") 384 }, 385 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 386 RT711_JD2 | 387 SOF_SDW_FOUR_SPK), 388 }, 389 { 390 .callback = sof_sdw_quirk_cb, 391 .matches = { 392 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 393 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F") 394 }, 395 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 396 RT711_JD2 | 397 SOF_SDW_FOUR_SPK), 398 }, 399 /* MeteorLake devices */ 400 { 401 .callback = sof_sdw_quirk_cb, 402 .matches = { 403 DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"), 404 }, 405 .driver_data = (void *)(RT711_JD1 | SOF_SDW_TGL_HDMI), 406 }, 407 {} 408 }; 409 410 static struct snd_soc_dai_link_component dmic_component[] = { 411 { 412 .name = "dmic-codec", 413 .dai_name = "dmic-hifi", 414 } 415 }; 416 417 static struct snd_soc_dai_link_component platform_component[] = { 418 { 419 /* name might be overridden during probe */ 420 .name = "0000:00:1f.3" 421 } 422 }; 423 424 /* these wrappers are only needed to avoid typecast compilation errors */ 425 int sdw_startup(struct snd_pcm_substream *substream) 426 { 427 return sdw_startup_stream(substream); 428 } 429 430 int sdw_prepare(struct snd_pcm_substream *substream) 431 { 432 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 433 struct sdw_stream_runtime *sdw_stream; 434 struct snd_soc_dai *dai; 435 436 /* Find stream from first CPU DAI */ 437 dai = asoc_rtd_to_cpu(rtd, 0); 438 439 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 440 441 if (IS_ERR(sdw_stream)) { 442 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 443 return PTR_ERR(sdw_stream); 444 } 445 446 return sdw_prepare_stream(sdw_stream); 447 } 448 449 int sdw_trigger(struct snd_pcm_substream *substream, int cmd) 450 { 451 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 452 struct sdw_stream_runtime *sdw_stream; 453 struct snd_soc_dai *dai; 454 int ret; 455 456 /* Find stream from first CPU DAI */ 457 dai = asoc_rtd_to_cpu(rtd, 0); 458 459 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 460 461 if (IS_ERR(sdw_stream)) { 462 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 463 return PTR_ERR(sdw_stream); 464 } 465 466 switch (cmd) { 467 case SNDRV_PCM_TRIGGER_START: 468 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 469 case SNDRV_PCM_TRIGGER_RESUME: 470 ret = sdw_enable_stream(sdw_stream); 471 break; 472 473 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 474 case SNDRV_PCM_TRIGGER_SUSPEND: 475 case SNDRV_PCM_TRIGGER_STOP: 476 ret = sdw_disable_stream(sdw_stream); 477 break; 478 default: 479 ret = -EINVAL; 480 break; 481 } 482 483 if (ret) 484 dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret); 485 486 return ret; 487 } 488 489 int sdw_hw_free(struct snd_pcm_substream *substream) 490 { 491 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 492 struct sdw_stream_runtime *sdw_stream; 493 struct snd_soc_dai *dai; 494 495 /* Find stream from first CPU DAI */ 496 dai = asoc_rtd_to_cpu(rtd, 0); 497 498 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 499 500 if (IS_ERR(sdw_stream)) { 501 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 502 return PTR_ERR(sdw_stream); 503 } 504 505 return sdw_deprepare_stream(sdw_stream); 506 } 507 508 void sdw_shutdown(struct snd_pcm_substream *substream) 509 { 510 sdw_shutdown_stream(substream); 511 } 512 513 static const struct snd_soc_ops sdw_ops = { 514 .startup = sdw_startup, 515 .prepare = sdw_prepare, 516 .trigger = sdw_trigger, 517 .hw_free = sdw_hw_free, 518 .shutdown = sdw_shutdown, 519 }; 520 521 static struct sof_sdw_codec_info codec_info_list[] = { 522 { 523 .part_id = 0x700, 524 .direction = {true, true}, 525 .dai_name = "rt700-aif1", 526 .init = sof_sdw_rt700_init, 527 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 528 }, 529 { 530 .part_id = 0x711, 531 .version_id = 3, 532 .direction = {true, true}, 533 .dai_name = "rt711-sdca-aif1", 534 .init = sof_sdw_rt711_sdca_init, 535 .exit = sof_sdw_rt711_sdca_exit, 536 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 537 }, 538 { 539 .part_id = 0x711, 540 .version_id = 2, 541 .direction = {true, true}, 542 .dai_name = "rt711-aif1", 543 .init = sof_sdw_rt711_init, 544 .exit = sof_sdw_rt711_exit, 545 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 546 }, 547 { 548 .part_id = 0x1308, 549 .acpi_id = "10EC1308", 550 .direction = {true, false}, 551 .dai_name = "rt1308-aif", 552 .ops = &sof_sdw_rt1308_i2s_ops, 553 .init = sof_sdw_rt_amp_init, 554 .exit = sof_sdw_rt_amp_exit, 555 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 556 }, 557 { 558 .part_id = 0x1316, 559 .direction = {true, true}, 560 .dai_name = "rt1316-aif", 561 .init = sof_sdw_rt_amp_init, 562 .exit = sof_sdw_rt_amp_exit, 563 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 564 }, 565 { 566 .part_id = 0x1318, 567 .direction = {true, true}, 568 .dai_name = "rt1318-aif", 569 .init = sof_sdw_rt_amp_init, 570 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 571 }, 572 { 573 .part_id = 0x714, 574 .version_id = 3, 575 .direction = {false, true}, 576 .ignore_pch_dmic = true, 577 .dai_name = "rt715-aif2", 578 .init = sof_sdw_rt715_sdca_init, 579 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 580 }, 581 { 582 .part_id = 0x715, 583 .version_id = 3, 584 .direction = {false, true}, 585 .ignore_pch_dmic = true, 586 .dai_name = "rt715-aif2", 587 .init = sof_sdw_rt715_sdca_init, 588 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 589 }, 590 { 591 .part_id = 0x714, 592 .version_id = 2, 593 .direction = {false, true}, 594 .ignore_pch_dmic = true, 595 .dai_name = "rt715-aif2", 596 .init = sof_sdw_rt715_init, 597 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 598 }, 599 { 600 .part_id = 0x715, 601 .version_id = 2, 602 .direction = {false, true}, 603 .ignore_pch_dmic = true, 604 .dai_name = "rt715-aif2", 605 .init = sof_sdw_rt715_init, 606 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 607 }, 608 { 609 .part_id = 0x8373, 610 .direction = {true, true}, 611 .dai_name = "max98373-aif1", 612 .init = sof_sdw_mx8373_init, 613 .codec_card_late_probe = sof_sdw_mx8373_late_probe, 614 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 615 }, 616 { 617 .part_id = 0x5682, 618 .direction = {true, true}, 619 .dai_name = "rt5682-sdw", 620 .init = sof_sdw_rt5682_init, 621 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 622 }, 623 { 624 .part_id = 0xaaaa, /* generic codec mockup */ 625 .version_id = 0, 626 .direction = {true, true}, 627 .dai_name = "sdw-mockup-aif1", 628 .init = NULL, 629 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 630 }, 631 { 632 .part_id = 0xaa55, /* headset codec mockup */ 633 .version_id = 0, 634 .direction = {true, true}, 635 .dai_name = "sdw-mockup-aif1", 636 .init = NULL, 637 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 638 }, 639 { 640 .part_id = 0x55aa, /* amplifier mockup */ 641 .version_id = 0, 642 .direction = {true, false}, 643 .dai_name = "sdw-mockup-aif1", 644 .init = NULL, 645 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 646 }, 647 { 648 .part_id = 0x5555, 649 .version_id = 0, 650 .direction = {false, true}, 651 .dai_name = "sdw-mockup-aif1", 652 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 653 }, 654 }; 655 656 static inline int find_codec_info_part(u64 adr) 657 { 658 unsigned int part_id, sdw_version; 659 int i; 660 661 part_id = SDW_PART_ID(adr); 662 sdw_version = SDW_VERSION(adr); 663 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 664 /* 665 * A codec info is for all sdw version with the part id if 666 * version_id is not specified in the codec info. 667 */ 668 if (part_id == codec_info_list[i].part_id && 669 (!codec_info_list[i].version_id || 670 sdw_version == codec_info_list[i].version_id)) 671 return i; 672 673 return -EINVAL; 674 675 } 676 677 static inline int find_codec_info_acpi(const u8 *acpi_id) 678 { 679 int i; 680 681 if (!acpi_id[0]) 682 return -EINVAL; 683 684 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 685 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, 686 ACPI_ID_LEN)) 687 break; 688 689 if (i == ARRAY_SIZE(codec_info_list)) 690 return -EINVAL; 691 692 return i; 693 } 694 695 /* 696 * get BE dailink number and CPU DAI number based on sdw link adr. 697 * Since some sdw slaves may be aggregated, the CPU DAI number 698 * may be larger than the number of BE dailinks. 699 */ 700 static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_link_adr *links, 701 int *sdw_be_num, int *sdw_cpu_dai_num) 702 { 703 const struct snd_soc_acpi_link_adr *link; 704 int _codec_type = SOF_SDW_CODEC_TYPE_JACK; 705 bool group_visited[SDW_MAX_GROUPS]; 706 bool no_aggregation; 707 int i; 708 709 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 710 *sdw_cpu_dai_num = 0; 711 *sdw_be_num = 0; 712 713 if (!links) 714 return -EINVAL; 715 716 for (i = 0; i < SDW_MAX_GROUPS; i++) 717 group_visited[i] = false; 718 719 for (link = links; link->num_adr; link++) { 720 const struct snd_soc_acpi_endpoint *endpoint; 721 int codec_index; 722 int stream; 723 u64 adr; 724 725 adr = link->adr_d->adr; 726 codec_index = find_codec_info_part(adr); 727 if (codec_index < 0) 728 return codec_index; 729 730 if (codec_info_list[codec_index].codec_type < _codec_type) 731 dev_warn(dev, 732 "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); 733 734 _codec_type = codec_info_list[codec_index].codec_type; 735 736 endpoint = link->adr_d->endpoints; 737 738 /* count DAI number for playback and capture */ 739 for_each_pcm_streams(stream) { 740 if (!codec_info_list[codec_index].direction[stream]) 741 continue; 742 743 (*sdw_cpu_dai_num)++; 744 745 /* count BE for each non-aggregated slave or group */ 746 if (!endpoint->aggregated || no_aggregation || 747 !group_visited[endpoint->group_id]) 748 (*sdw_be_num)++; 749 } 750 751 if (endpoint->aggregated) 752 group_visited[endpoint->group_id] = true; 753 } 754 755 return 0; 756 } 757 758 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 759 int be_id, char *name, int playback, int capture, 760 struct snd_soc_dai_link_component *cpus, int cpus_num, 761 struct snd_soc_dai_link_component *codecs, int codecs_num, 762 int (*init)(struct snd_soc_pcm_runtime *rtd), 763 const struct snd_soc_ops *ops) 764 { 765 dev_dbg(dev, "create dai link %s, id %d\n", name, be_id); 766 dai_links->id = be_id; 767 dai_links->name = name; 768 dai_links->platforms = platform_component; 769 dai_links->num_platforms = ARRAY_SIZE(platform_component); 770 dai_links->no_pcm = 1; 771 dai_links->cpus = cpus; 772 dai_links->num_cpus = cpus_num; 773 dai_links->codecs = codecs; 774 dai_links->num_codecs = codecs_num; 775 dai_links->dpcm_playback = playback; 776 dai_links->dpcm_capture = capture; 777 dai_links->init = init; 778 dai_links->ops = ops; 779 } 780 781 static bool is_unique_device(const struct snd_soc_acpi_link_adr *link, 782 unsigned int sdw_version, 783 unsigned int mfg_id, 784 unsigned int part_id, 785 unsigned int class_id, 786 int index_in_link 787 ) 788 { 789 int i; 790 791 for (i = 0; i < link->num_adr; i++) { 792 unsigned int sdw1_version, mfg1_id, part1_id, class1_id; 793 u64 adr; 794 795 /* skip itself */ 796 if (i == index_in_link) 797 continue; 798 799 adr = link->adr_d[i].adr; 800 801 sdw1_version = SDW_VERSION(adr); 802 mfg1_id = SDW_MFG_ID(adr); 803 part1_id = SDW_PART_ID(adr); 804 class1_id = SDW_CLASS_ID(adr); 805 806 if (sdw_version == sdw1_version && 807 mfg_id == mfg1_id && 808 part_id == part1_id && 809 class_id == class1_id) 810 return false; 811 } 812 813 return true; 814 } 815 816 static int create_codec_dai_name(struct device *dev, 817 const struct snd_soc_acpi_link_adr *link, 818 struct snd_soc_dai_link_component *codec, 819 int offset, 820 struct snd_soc_codec_conf *codec_conf, 821 int codec_count, 822 int *codec_conf_index) 823 { 824 int i; 825 826 /* sanity check */ 827 if (*codec_conf_index + link->num_adr > codec_count) { 828 dev_err(dev, "codec_conf: out-of-bounds access requested\n"); 829 return -EINVAL; 830 } 831 832 for (i = 0; i < link->num_adr; i++) { 833 unsigned int sdw_version, unique_id, mfg_id; 834 unsigned int link_id, part_id, class_id; 835 int codec_index, comp_index; 836 char *codec_str; 837 u64 adr; 838 839 adr = link->adr_d[i].adr; 840 841 sdw_version = SDW_VERSION(adr); 842 link_id = SDW_DISCO_LINK_ID(adr); 843 unique_id = SDW_UNIQUE_ID(adr); 844 mfg_id = SDW_MFG_ID(adr); 845 part_id = SDW_PART_ID(adr); 846 class_id = SDW_CLASS_ID(adr); 847 848 comp_index = i + offset; 849 if (is_unique_device(link, sdw_version, mfg_id, part_id, 850 class_id, i)) { 851 codec_str = "sdw:%01x:%04x:%04x:%02x"; 852 codec[comp_index].name = 853 devm_kasprintf(dev, GFP_KERNEL, codec_str, 854 link_id, mfg_id, part_id, 855 class_id); 856 } else { 857 codec_str = "sdw:%01x:%04x:%04x:%02x:%01x"; 858 codec[comp_index].name = 859 devm_kasprintf(dev, GFP_KERNEL, codec_str, 860 link_id, mfg_id, part_id, 861 class_id, unique_id); 862 } 863 864 if (!codec[comp_index].name) 865 return -ENOMEM; 866 867 codec_index = find_codec_info_part(adr); 868 if (codec_index < 0) 869 return codec_index; 870 871 codec[comp_index].dai_name = 872 codec_info_list[codec_index].dai_name; 873 874 codec_conf[*codec_conf_index].dlc = codec[comp_index]; 875 codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix; 876 877 ++*codec_conf_index; 878 } 879 880 return 0; 881 } 882 883 static int set_codec_init_func(struct snd_soc_card *card, 884 const struct snd_soc_acpi_link_adr *link, 885 struct snd_soc_dai_link *dai_links, 886 bool playback, int group_id) 887 { 888 int i; 889 890 do { 891 /* 892 * Initialize the codec. If codec is part of an aggregated 893 * group (group_id>0), initialize all codecs belonging to 894 * same group. 895 */ 896 for (i = 0; i < link->num_adr; i++) { 897 int codec_index; 898 899 codec_index = find_codec_info_part(link->adr_d[i].adr); 900 901 if (codec_index < 0) 902 return codec_index; 903 /* The group_id is > 0 iff the codec is aggregated */ 904 if (link->adr_d[i].endpoints->group_id != group_id) 905 continue; 906 if (codec_info_list[codec_index].init) 907 codec_info_list[codec_index].init(card, 908 link, 909 dai_links, 910 &codec_info_list[codec_index], 911 playback); 912 } 913 link++; 914 } while (link->mask && group_id); 915 916 return 0; 917 } 918 919 /* 920 * check endpoint status in slaves and gather link ID for all slaves in 921 * the same group to generate different CPU DAI. Now only support 922 * one sdw link with all slaves set with only single group id. 923 * 924 * one slave on one sdw link with aggregated = 0 925 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 926 * 927 * two or more slaves on one sdw link with aggregated = 0 928 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 929 * 930 * multiple links with multiple slaves with aggregated = 1 931 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 932 */ 933 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 934 struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 935 int *codec_num, unsigned int *group_id, 936 bool *group_generated) 937 { 938 const struct snd_soc_acpi_adr_device *adr_d; 939 const struct snd_soc_acpi_link_adr *adr_next; 940 bool no_aggregation; 941 int index = 0; 942 943 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 944 *codec_num = adr_link->num_adr; 945 adr_d = adr_link->adr_d; 946 947 /* make sure the link mask has a single bit set */ 948 if (!is_power_of_2(adr_link->mask)) 949 return -EINVAL; 950 951 cpu_dai_id[index++] = ffs(adr_link->mask) - 1; 952 if (!adr_d->endpoints->aggregated || no_aggregation) { 953 *cpu_dai_num = 1; 954 *group_id = 0; 955 return 0; 956 } 957 958 *group_id = adr_d->endpoints->group_id; 959 960 /* gather other link ID of slaves in the same group */ 961 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; 962 adr_next++) { 963 const struct snd_soc_acpi_endpoint *endpoint; 964 965 endpoint = adr_next->adr_d->endpoints; 966 if (!endpoint->aggregated || 967 endpoint->group_id != *group_id) 968 continue; 969 970 /* make sure the link mask has a single bit set */ 971 if (!is_power_of_2(adr_next->mask)) 972 return -EINVAL; 973 974 if (index >= SDW_MAX_CPU_DAIS) { 975 dev_err(dev, " cpu_dai_id array overflows"); 976 return -EINVAL; 977 } 978 979 cpu_dai_id[index++] = ffs(adr_next->mask) - 1; 980 *codec_num += adr_next->num_adr; 981 } 982 983 /* 984 * indicate CPU DAIs for this group have been generated 985 * to avoid generating CPU DAIs for this group again. 986 */ 987 group_generated[*group_id] = true; 988 *cpu_dai_num = index; 989 990 return 0; 991 } 992 993 static int create_sdw_dailink(struct snd_soc_card *card, 994 struct device *dev, int *link_index, 995 struct snd_soc_dai_link *dai_links, 996 int sdw_be_num, int sdw_cpu_dai_num, 997 struct snd_soc_dai_link_component *cpus, 998 const struct snd_soc_acpi_link_adr *link, 999 int *cpu_id, bool *group_generated, 1000 struct snd_soc_codec_conf *codec_conf, 1001 int codec_count, int *link_id, 1002 int *codec_conf_index, 1003 bool *ignore_pch_dmic) 1004 { 1005 const struct snd_soc_acpi_link_adr *link_next; 1006 struct snd_soc_dai_link_component *codecs; 1007 int cpu_dai_id[SDW_MAX_CPU_DAIS]; 1008 int cpu_dai_num, cpu_dai_index; 1009 unsigned int group_id; 1010 int codec_idx = 0; 1011 int i = 0, j = 0; 1012 int codec_index; 1013 int codec_num; 1014 int stream; 1015 int ret; 1016 int k; 1017 1018 ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 1019 &group_id, group_generated); 1020 if (ret) 1021 return ret; 1022 1023 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 1024 if (!codecs) 1025 return -ENOMEM; 1026 1027 /* generate codec name on different links in the same group */ 1028 for (link_next = link; link_next && link_next->num_adr && 1029 i < cpu_dai_num; link_next++) { 1030 const struct snd_soc_acpi_endpoint *endpoints; 1031 1032 endpoints = link_next->adr_d->endpoints; 1033 if (group_id && (!endpoints->aggregated || 1034 endpoints->group_id != group_id)) 1035 continue; 1036 1037 /* skip the link excluded by this processed group */ 1038 if (cpu_dai_id[i] != ffs(link_next->mask) - 1) 1039 continue; 1040 1041 ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, 1042 codec_conf, codec_count, codec_conf_index); 1043 if (ret < 0) 1044 return ret; 1045 1046 /* check next link to create codec dai in the processed group */ 1047 i++; 1048 codec_idx += link_next->num_adr; 1049 } 1050 1051 /* find codec info to create BE DAI */ 1052 codec_index = find_codec_info_part(link->adr_d[0].adr); 1053 if (codec_index < 0) 1054 return codec_index; 1055 1056 if (codec_info_list[codec_index].ignore_pch_dmic) 1057 *ignore_pch_dmic = true; 1058 1059 /* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */ 1060 if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP && 1061 *link_id < SDW_AMP_DAI_ID) 1062 *link_id = SDW_AMP_DAI_ID; 1063 1064 /* 1065 * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to 1066 * keep sdw DMIC and HDMI setting static in UCM 1067 */ 1068 if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC && 1069 *link_id < SDW_DMIC_DAI_ID) 1070 *link_id = SDW_DMIC_DAI_ID; 1071 1072 cpu_dai_index = *cpu_id; 1073 for_each_pcm_streams(stream) { 1074 char *name, *cpu_name; 1075 int playback, capture; 1076 static const char * const sdw_stream_name[] = { 1077 "SDW%d-Playback", 1078 "SDW%d-Capture", 1079 }; 1080 1081 if (!codec_info_list[codec_index].direction[stream]) 1082 continue; 1083 1084 /* create stream name according to first link id */ 1085 name = devm_kasprintf(dev, GFP_KERNEL, 1086 sdw_stream_name[stream], cpu_dai_id[0]); 1087 if (!name) 1088 return -ENOMEM; 1089 1090 /* 1091 * generate CPU DAI name base on the sdw link ID and 1092 * PIN ID with offset of 2 according to sdw dai driver. 1093 */ 1094 for (k = 0; k < cpu_dai_num; k++) { 1095 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1096 "SDW%d Pin%d", cpu_dai_id[k], 1097 j + SDW_INTEL_BIDIR_PDI_BASE); 1098 if (!cpu_name) 1099 return -ENOMEM; 1100 1101 if (cpu_dai_index >= sdw_cpu_dai_num) { 1102 dev_err(dev, "invalid cpu dai index %d", 1103 cpu_dai_index); 1104 return -EINVAL; 1105 } 1106 1107 cpus[cpu_dai_index++].dai_name = cpu_name; 1108 } 1109 1110 /* 1111 * We create sdw dai links at first stage, so link index should 1112 * not be larger than sdw_be_num 1113 */ 1114 if (*link_index >= sdw_be_num) { 1115 dev_err(dev, "invalid dai link index %d", *link_index); 1116 return -EINVAL; 1117 } 1118 1119 if (*cpu_id >= sdw_cpu_dai_num) { 1120 dev_err(dev, " invalid cpu dai index %d", *cpu_id); 1121 return -EINVAL; 1122 } 1123 1124 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 1125 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 1126 init_dai_link(dev, dai_links + *link_index, (*link_id)++, name, 1127 playback, capture, 1128 cpus + *cpu_id, cpu_dai_num, 1129 codecs, codec_num, 1130 NULL, &sdw_ops); 1131 1132 /* 1133 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 1134 * based on wait_for_completion(), tag them as 'nonatomic'. 1135 */ 1136 dai_links[*link_index].nonatomic = true; 1137 1138 ret = set_codec_init_func(card, link, dai_links + (*link_index)++, 1139 playback, group_id); 1140 if (ret < 0) { 1141 dev_err(dev, "failed to init codec %d", codec_index); 1142 return ret; 1143 } 1144 1145 *cpu_id += cpu_dai_num; 1146 j++; 1147 } 1148 1149 return 0; 1150 } 1151 1152 #define IDISP_CODEC_MASK 0x4 1153 1154 static int sof_card_codec_conf_alloc(struct device *dev, 1155 struct snd_soc_acpi_mach_params *mach_params, 1156 struct snd_soc_codec_conf **codec_conf, 1157 int *codec_conf_count) 1158 { 1159 const struct snd_soc_acpi_link_adr *adr_link; 1160 struct snd_soc_codec_conf *c_conf; 1161 int num_codecs = 0; 1162 int i; 1163 1164 adr_link = mach_params->links; 1165 if (!adr_link) 1166 return -EINVAL; 1167 1168 /* generate DAI links by each sdw link */ 1169 for (; adr_link->num_adr; adr_link++) { 1170 for (i = 0; i < adr_link->num_adr; i++) { 1171 if (!adr_link->adr_d[i].name_prefix) { 1172 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1173 adr_link->adr_d[i].adr); 1174 return -EINVAL; 1175 } 1176 } 1177 num_codecs += adr_link->num_adr; 1178 } 1179 1180 c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL); 1181 if (!c_conf) 1182 return -ENOMEM; 1183 1184 *codec_conf = c_conf; 1185 *codec_conf_count = num_codecs; 1186 1187 return 0; 1188 } 1189 1190 static int sof_card_dai_links_create(struct device *dev, 1191 struct snd_soc_acpi_mach *mach, 1192 struct snd_soc_card *card) 1193 { 1194 int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; 1195 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1196 struct snd_soc_dai_link_component *idisp_components; 1197 struct snd_soc_dai_link_component *ssp_components; 1198 struct snd_soc_acpi_mach_params *mach_params; 1199 const struct snd_soc_acpi_link_adr *adr_link; 1200 struct snd_soc_dai_link_component *cpus; 1201 struct snd_soc_codec_conf *codec_conf; 1202 bool ignore_pch_dmic = false; 1203 int codec_conf_count; 1204 int codec_conf_index = 0; 1205 bool group_generated[SDW_MAX_GROUPS]; 1206 int ssp_codec_index, ssp_mask; 1207 struct snd_soc_dai_link *links; 1208 int num_links, link_index = 0; 1209 char *name, *cpu_name; 1210 int total_cpu_dai_num; 1211 int sdw_cpu_dai_num; 1212 int i, j, be_id = 0; 1213 int cpu_id = 0; 1214 int comp_num; 1215 int ret; 1216 1217 mach_params = &mach->mach_params; 1218 1219 /* allocate codec conf, will be populated when dailinks are created */ 1220 ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count); 1221 if (ret < 0) 1222 return ret; 1223 1224 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1225 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1226 codec_info_list[i].amp_num = 0; 1227 1228 if (mach_params->codec_mask & IDISP_CODEC_MASK) { 1229 ctx->idisp_codec = true; 1230 1231 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1232 hdmi_num = SOF_TGL_HDMI_COUNT; 1233 else 1234 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1235 } 1236 1237 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1238 /* 1239 * on generic tgl platform, I2S or sdw mode is supported 1240 * based on board rework. A ACPI device is registered in 1241 * system only when I2S mode is supported, not sdw mode. 1242 * Here check ACPI ID to confirm I2S is supported. 1243 */ 1244 ssp_codec_index = find_codec_info_acpi(mach->id); 1245 ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0; 1246 comp_num = hdmi_num + ssp_num; 1247 1248 ret = get_sdw_dailink_info(dev, mach_params->links, 1249 &sdw_be_num, &sdw_cpu_dai_num); 1250 if (ret < 0) { 1251 dev_err(dev, "failed to get sdw link info %d", ret); 1252 return ret; 1253 } 1254 1255 /* enable dmic01 & dmic16k */ 1256 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; 1257 comp_num += dmic_num; 1258 1259 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1260 comp_num++; 1261 1262 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, 1263 dmic_num, ctx->idisp_codec ? hdmi_num : 0); 1264 1265 /* allocate BE dailinks */ 1266 num_links = comp_num + sdw_be_num; 1267 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL); 1268 1269 /* allocated CPU DAIs */ 1270 total_cpu_dai_num = comp_num + sdw_cpu_dai_num; 1271 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus), 1272 GFP_KERNEL); 1273 1274 if (!links || !cpus) 1275 return -ENOMEM; 1276 1277 /* SDW */ 1278 if (!sdw_be_num) 1279 goto SSP; 1280 1281 adr_link = mach_params->links; 1282 if (!adr_link) 1283 return -EINVAL; 1284 1285 /* 1286 * SoundWire Slaves aggregated in the same group may be 1287 * located on different hardware links. Clear array to indicate 1288 * CPU DAIs for this group have not been generated. 1289 */ 1290 for (i = 0; i < SDW_MAX_GROUPS; i++) 1291 group_generated[i] = false; 1292 1293 /* generate DAI links by each sdw link */ 1294 for (; adr_link->num_adr; adr_link++) { 1295 const struct snd_soc_acpi_endpoint *endpoint; 1296 1297 endpoint = adr_link->adr_d->endpoints; 1298 if (endpoint->aggregated && !endpoint->group_id) { 1299 dev_err(dev, "invalid group id on link %x", 1300 adr_link->mask); 1301 continue; 1302 } 1303 1304 /* this group has been generated */ 1305 if (endpoint->aggregated && 1306 group_generated[endpoint->group_id]) 1307 continue; 1308 1309 ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, 1310 sdw_cpu_dai_num, cpus, adr_link, 1311 &cpu_id, group_generated, 1312 codec_conf, codec_conf_count, 1313 &be_id, &codec_conf_index, 1314 &ignore_pch_dmic); 1315 if (ret < 0) { 1316 dev_err(dev, "failed to create dai link %d", link_index); 1317 return ret; 1318 } 1319 } 1320 1321 SSP: 1322 /* SSP */ 1323 if (!ssp_num) 1324 goto DMIC; 1325 1326 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1327 struct sof_sdw_codec_info *info; 1328 int playback, capture; 1329 char *codec_name; 1330 1331 if (!(ssp_mask & 0x1)) 1332 continue; 1333 1334 name = devm_kasprintf(dev, GFP_KERNEL, 1335 "SSP%d-Codec", i); 1336 if (!name) 1337 return -ENOMEM; 1338 1339 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1340 if (!cpu_name) 1341 return -ENOMEM; 1342 1343 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1344 GFP_KERNEL); 1345 if (!ssp_components) 1346 return -ENOMEM; 1347 1348 info = &codec_info_list[ssp_codec_index]; 1349 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1350 info->acpi_id, j++); 1351 if (!codec_name) 1352 return -ENOMEM; 1353 1354 ssp_components->name = codec_name; 1355 ssp_components->dai_name = info->dai_name; 1356 cpus[cpu_id].dai_name = cpu_name; 1357 1358 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; 1359 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; 1360 init_dai_link(dev, links + link_index, be_id, name, 1361 playback, capture, 1362 cpus + cpu_id, 1, 1363 ssp_components, 1, 1364 NULL, info->ops); 1365 1366 ret = info->init(card, NULL, links + link_index, info, 0); 1367 if (ret < 0) 1368 return ret; 1369 1370 INC_ID(be_id, cpu_id, link_index); 1371 } 1372 1373 DMIC: 1374 /* dmic */ 1375 if (dmic_num > 0) { 1376 if (ignore_pch_dmic) { 1377 dev_warn(dev, "Ignoring PCH DMIC\n"); 1378 goto HDMI; 1379 } 1380 cpus[cpu_id].dai_name = "DMIC01 Pin"; 1381 init_dai_link(dev, links + link_index, be_id, "dmic01", 1382 0, 1, // DMIC only supports capture 1383 cpus + cpu_id, 1, 1384 dmic_component, 1, 1385 sof_sdw_dmic_init, NULL); 1386 INC_ID(be_id, cpu_id, link_index); 1387 1388 cpus[cpu_id].dai_name = "DMIC16k Pin"; 1389 init_dai_link(dev, links + link_index, be_id, "dmic16k", 1390 0, 1, // DMIC only supports capture 1391 cpus + cpu_id, 1, 1392 dmic_component, 1, 1393 /* don't call sof_sdw_dmic_init() twice */ 1394 NULL, NULL); 1395 INC_ID(be_id, cpu_id, link_index); 1396 } 1397 1398 HDMI: 1399 /* HDMI */ 1400 if (hdmi_num > 0) { 1401 idisp_components = devm_kcalloc(dev, hdmi_num, 1402 sizeof(*idisp_components), 1403 GFP_KERNEL); 1404 if (!idisp_components) 1405 return -ENOMEM; 1406 } 1407 1408 for (i = 0; i < hdmi_num; i++) { 1409 name = devm_kasprintf(dev, GFP_KERNEL, 1410 "iDisp%d", i + 1); 1411 if (!name) 1412 return -ENOMEM; 1413 1414 if (ctx->idisp_codec) { 1415 idisp_components[i].name = "ehdaudio0D2"; 1416 idisp_components[i].dai_name = devm_kasprintf(dev, 1417 GFP_KERNEL, 1418 "intel-hdmi-hifi%d", 1419 i + 1); 1420 if (!idisp_components[i].dai_name) 1421 return -ENOMEM; 1422 } else { 1423 idisp_components[i].name = "snd-soc-dummy"; 1424 idisp_components[i].dai_name = "snd-soc-dummy-dai"; 1425 } 1426 1427 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1428 "iDisp%d Pin", i + 1); 1429 if (!cpu_name) 1430 return -ENOMEM; 1431 1432 cpus[cpu_id].dai_name = cpu_name; 1433 init_dai_link(dev, links + link_index, be_id, name, 1434 1, 0, // HDMI only supports playback 1435 cpus + cpu_id, 1, 1436 idisp_components + i, 1, 1437 sof_sdw_hdmi_init, NULL); 1438 INC_ID(be_id, cpu_id, link_index); 1439 } 1440 1441 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1442 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1443 SOF_BT_OFFLOAD_SSP_SHIFT; 1444 1445 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1446 if (!name) 1447 return -ENOMEM; 1448 1449 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1450 GFP_KERNEL); 1451 if (!ssp_components) 1452 return -ENOMEM; 1453 1454 ssp_components->name = "snd-soc-dummy"; 1455 ssp_components->dai_name = "snd-soc-dummy-dai"; 1456 1457 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1458 if (!cpu_name) 1459 return -ENOMEM; 1460 1461 cpus[cpu_id].dai_name = cpu_name; 1462 init_dai_link(dev, links + link_index, be_id, name, 1, 1, 1463 cpus + cpu_id, 1, ssp_components, 1, NULL, NULL); 1464 } 1465 1466 card->dai_link = links; 1467 card->num_links = num_links; 1468 1469 card->codec_conf = codec_conf; 1470 card->num_configs = codec_conf_count; 1471 1472 return 0; 1473 } 1474 1475 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1476 { 1477 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1478 int ret = 0; 1479 int i; 1480 1481 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1482 if (!codec_info_list[i].late_probe) 1483 continue; 1484 1485 ret = codec_info_list[i].codec_card_late_probe(card); 1486 if (ret < 0) 1487 return ret; 1488 } 1489 1490 if (ctx->idisp_codec) 1491 ret = sof_sdw_hdmi_card_late_probe(card); 1492 1493 return ret; 1494 } 1495 1496 /* SoC card */ 1497 static const char sdw_card_long_name[] = "Intel Soundwire SOF"; 1498 1499 static struct snd_soc_card card_sof_sdw = { 1500 .name = "soundwire", 1501 .owner = THIS_MODULE, 1502 .late_probe = sof_sdw_card_late_probe, 1503 }; 1504 1505 static void mc_dailink_exit_loop(struct snd_soc_card *card) 1506 { 1507 struct snd_soc_dai_link *link; 1508 int ret; 1509 int i, j; 1510 1511 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1512 if (!codec_info_list[i].exit) 1513 continue; 1514 /* 1515 * We don't need to call .exit function if there is no matched 1516 * dai link found. 1517 */ 1518 for_each_card_prelinks(card, j, link) { 1519 if (!strcmp(link->codecs[0].dai_name, 1520 codec_info_list[i].dai_name)) { 1521 ret = codec_info_list[i].exit(card, link); 1522 if (ret) 1523 dev_warn(card->dev, 1524 "codec exit failed %d\n", 1525 ret); 1526 break; 1527 } 1528 } 1529 } 1530 } 1531 1532 static int mc_probe(struct platform_device *pdev) 1533 { 1534 struct snd_soc_card *card = &card_sof_sdw; 1535 struct snd_soc_acpi_mach *mach; 1536 struct mc_private *ctx; 1537 int amp_num = 0, i; 1538 int ret; 1539 1540 dev_dbg(&pdev->dev, "Entry\n"); 1541 1542 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1543 if (!ctx) 1544 return -ENOMEM; 1545 1546 dmi_check_system(sof_sdw_quirk_table); 1547 1548 if (quirk_override != -1) { 1549 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", 1550 sof_sdw_quirk, quirk_override); 1551 sof_sdw_quirk = quirk_override; 1552 } 1553 log_quirks(&pdev->dev); 1554 1555 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 1556 1557 card->dev = &pdev->dev; 1558 snd_soc_card_set_drvdata(card, ctx); 1559 1560 mach = pdev->dev.platform_data; 1561 ret = sof_card_dai_links_create(&pdev->dev, mach, 1562 card); 1563 if (ret < 0) 1564 return ret; 1565 1566 /* 1567 * the default amp_num is zero for each codec and 1568 * amp_num will only be increased for active amp 1569 * codecs on used platform 1570 */ 1571 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1572 amp_num += codec_info_list[i].amp_num; 1573 1574 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1575 "cfg-spk:%d cfg-amp:%d", 1576 (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 1577 ? 4 : 2, amp_num); 1578 if (!card->components) 1579 return -ENOMEM; 1580 1581 if (mach->mach_params.dmic_num) { 1582 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1583 "%s mic:dmic cfg-mics:%d", 1584 card->components, 1585 mach->mach_params.dmic_num); 1586 if (!card->components) 1587 return -ENOMEM; 1588 } 1589 1590 card->long_name = sdw_card_long_name; 1591 1592 /* Register the card */ 1593 ret = devm_snd_soc_register_card(&pdev->dev, card); 1594 if (ret) { 1595 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); 1596 mc_dailink_exit_loop(card); 1597 return ret; 1598 } 1599 1600 platform_set_drvdata(pdev, card); 1601 1602 return ret; 1603 } 1604 1605 static int mc_remove(struct platform_device *pdev) 1606 { 1607 struct snd_soc_card *card = platform_get_drvdata(pdev); 1608 1609 mc_dailink_exit_loop(card); 1610 1611 return 0; 1612 } 1613 1614 static struct platform_driver sof_sdw_driver = { 1615 .driver = { 1616 .name = "sof_sdw", 1617 .pm = &snd_soc_pm_ops, 1618 }, 1619 .probe = mc_probe, 1620 .remove = mc_remove, 1621 }; 1622 1623 module_platform_driver(sof_sdw_driver); 1624 1625 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1626 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1627 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1628 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1629 MODULE_LICENSE("GPL v2"); 1630 MODULE_ALIAS("platform:sof_sdw"); 1631 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 1632 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 1633