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