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_type = SOF_SDW_CODEC_TYPE_AMP, 625 }, 626 { 627 .part_id = 0x5682, 628 .direction = {true, true}, 629 .dai_name = "rt5682-sdw", 630 .init = sof_sdw_rt5682_init, 631 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 632 }, 633 { 634 .part_id = 0xaaaa, /* generic codec mockup */ 635 .version_id = 0, 636 .direction = {true, true}, 637 .dai_name = "sdw-mockup-aif1", 638 .init = NULL, 639 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 640 }, 641 { 642 .part_id = 0xaa55, /* headset codec mockup */ 643 .version_id = 0, 644 .direction = {true, true}, 645 .dai_name = "sdw-mockup-aif1", 646 .init = NULL, 647 .codec_type = SOF_SDW_CODEC_TYPE_JACK, 648 }, 649 { 650 .part_id = 0x55aa, /* amplifier mockup */ 651 .version_id = 0, 652 .direction = {true, false}, 653 .dai_name = "sdw-mockup-aif1", 654 .init = NULL, 655 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 656 }, 657 { 658 .part_id = 0x5555, 659 .version_id = 0, 660 .direction = {false, true}, 661 .dai_name = "sdw-mockup-aif1", 662 .codec_type = SOF_SDW_CODEC_TYPE_MIC, 663 }, 664 }; 665 666 static inline int find_codec_info_part(u64 adr) 667 { 668 unsigned int part_id, sdw_version; 669 int i; 670 671 part_id = SDW_PART_ID(adr); 672 sdw_version = SDW_VERSION(adr); 673 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 674 /* 675 * A codec info is for all sdw version with the part id if 676 * version_id is not specified in the codec info. 677 */ 678 if (part_id == codec_info_list[i].part_id && 679 (!codec_info_list[i].version_id || 680 sdw_version == codec_info_list[i].version_id)) 681 return i; 682 683 return -EINVAL; 684 685 } 686 687 static inline int find_codec_info_acpi(const u8 *acpi_id) 688 { 689 int i; 690 691 if (!acpi_id[0]) 692 return -EINVAL; 693 694 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 695 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, 696 ACPI_ID_LEN)) 697 break; 698 699 if (i == ARRAY_SIZE(codec_info_list)) 700 return -EINVAL; 701 702 return i; 703 } 704 705 /* 706 * get BE dailink number and CPU DAI number based on sdw link adr. 707 * Since some sdw slaves may be aggregated, the CPU DAI number 708 * may be larger than the number of BE dailinks. 709 */ 710 static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_link_adr *links, 711 int *sdw_be_num, int *sdw_cpu_dai_num) 712 { 713 const struct snd_soc_acpi_link_adr *link; 714 int _codec_type = SOF_SDW_CODEC_TYPE_JACK; 715 bool group_visited[SDW_MAX_GROUPS]; 716 bool no_aggregation; 717 int i; 718 719 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 720 *sdw_cpu_dai_num = 0; 721 *sdw_be_num = 0; 722 723 if (!links) 724 return -EINVAL; 725 726 for (i = 0; i < SDW_MAX_GROUPS; i++) 727 group_visited[i] = false; 728 729 for (link = links; link->num_adr; link++) { 730 const struct snd_soc_acpi_endpoint *endpoint; 731 int codec_index; 732 int stream; 733 u64 adr; 734 735 for (i = 0; i < link->num_adr; i++) { 736 adr = link->adr_d[i].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[i].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 767 return 0; 768 } 769 770 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 771 int be_id, char *name, int playback, int capture, 772 struct snd_soc_dai_link_component *cpus, int cpus_num, 773 struct snd_soc_dai_link_component *codecs, int codecs_num, 774 int (*init)(struct snd_soc_pcm_runtime *rtd), 775 const struct snd_soc_ops *ops) 776 { 777 dev_dbg(dev, "create dai link %s, id %d\n", name, be_id); 778 dai_links->id = be_id; 779 dai_links->name = name; 780 dai_links->platforms = platform_component; 781 dai_links->num_platforms = ARRAY_SIZE(platform_component); 782 dai_links->no_pcm = 1; 783 dai_links->cpus = cpus; 784 dai_links->num_cpus = cpus_num; 785 dai_links->codecs = codecs; 786 dai_links->num_codecs = codecs_num; 787 dai_links->dpcm_playback = playback; 788 dai_links->dpcm_capture = capture; 789 dai_links->init = init; 790 dai_links->ops = ops; 791 } 792 793 static bool is_unique_device(const struct snd_soc_acpi_link_adr *link, 794 unsigned int sdw_version, 795 unsigned int mfg_id, 796 unsigned int part_id, 797 unsigned int class_id, 798 int index_in_link 799 ) 800 { 801 int i; 802 803 for (i = 0; i < link->num_adr; i++) { 804 unsigned int sdw1_version, mfg1_id, part1_id, class1_id; 805 u64 adr; 806 807 /* skip itself */ 808 if (i == index_in_link) 809 continue; 810 811 adr = link->adr_d[i].adr; 812 813 sdw1_version = SDW_VERSION(adr); 814 mfg1_id = SDW_MFG_ID(adr); 815 part1_id = SDW_PART_ID(adr); 816 class1_id = SDW_CLASS_ID(adr); 817 818 if (sdw_version == sdw1_version && 819 mfg_id == mfg1_id && 820 part_id == part1_id && 821 class_id == class1_id) 822 return false; 823 } 824 825 return true; 826 } 827 828 static int create_codec_dai_name(struct device *dev, 829 const struct snd_soc_acpi_link_adr *link, 830 struct snd_soc_dai_link_component *codec, 831 int offset, 832 struct snd_soc_codec_conf *codec_conf, 833 int codec_count, 834 int *codec_conf_index, 835 int adr_index) 836 { 837 int _codec_index = -1; 838 int i; 839 840 /* sanity check */ 841 if (*codec_conf_index + link->num_adr - adr_index > codec_count) { 842 dev_err(dev, "codec_conf: out-of-bounds access requested\n"); 843 return -EINVAL; 844 } 845 846 for (i = adr_index; i < link->num_adr; i++) { 847 unsigned int sdw_version, unique_id, mfg_id; 848 unsigned int link_id, part_id, class_id; 849 int codec_index, comp_index; 850 char *codec_str; 851 u64 adr; 852 853 adr = link->adr_d[i].adr; 854 855 sdw_version = SDW_VERSION(adr); 856 link_id = SDW_DISCO_LINK_ID(adr); 857 unique_id = SDW_UNIQUE_ID(adr); 858 mfg_id = SDW_MFG_ID(adr); 859 part_id = SDW_PART_ID(adr); 860 class_id = SDW_CLASS_ID(adr); 861 862 comp_index = i - adr_index + offset; 863 if (is_unique_device(link, sdw_version, mfg_id, part_id, 864 class_id, i)) { 865 codec_str = "sdw:%01x:%04x:%04x:%02x"; 866 codec[comp_index].name = 867 devm_kasprintf(dev, GFP_KERNEL, codec_str, 868 link_id, mfg_id, part_id, 869 class_id); 870 } else { 871 codec_str = "sdw:%01x:%04x:%04x:%02x:%01x"; 872 codec[comp_index].name = 873 devm_kasprintf(dev, GFP_KERNEL, codec_str, 874 link_id, mfg_id, part_id, 875 class_id, unique_id); 876 } 877 878 if (!codec[comp_index].name) 879 return -ENOMEM; 880 881 codec_index = find_codec_info_part(adr); 882 if (codec_index < 0) 883 return codec_index; 884 if (_codec_index != -1 && codec_index != _codec_index) { 885 dev_dbg(dev, "Different devices on the same sdw link\n"); 886 break; 887 } 888 _codec_index = codec_index; 889 890 codec[comp_index].dai_name = 891 codec_info_list[codec_index].dai_name; 892 893 codec_conf[*codec_conf_index].dlc = codec[comp_index]; 894 codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix; 895 896 ++*codec_conf_index; 897 } 898 899 return 0; 900 } 901 902 static int set_codec_init_func(struct snd_soc_card *card, 903 const struct snd_soc_acpi_link_adr *link, 904 struct snd_soc_dai_link *dai_links, 905 bool playback, int group_id) 906 { 907 int i; 908 909 do { 910 /* 911 * Initialize the codec. If codec is part of an aggregated 912 * group (group_id>0), initialize all codecs belonging to 913 * same group. 914 */ 915 for (i = 0; i < link->num_adr; i++) { 916 int codec_index; 917 918 codec_index = find_codec_info_part(link->adr_d[i].adr); 919 920 if (codec_index < 0) 921 return codec_index; 922 /* The group_id is > 0 iff the codec is aggregated */ 923 if (link->adr_d[i].endpoints->group_id != group_id) 924 continue; 925 if (codec_info_list[codec_index].init) 926 codec_info_list[codec_index].init(card, 927 link, 928 dai_links, 929 &codec_info_list[codec_index], 930 playback); 931 } 932 link++; 933 } while (link->mask && group_id); 934 935 return 0; 936 } 937 938 /* 939 * check endpoint status in slaves and gather link ID for all slaves in 940 * the same group to generate different CPU DAI. Now only support 941 * one sdw link with all slaves set with only single group id. 942 * 943 * one slave on one sdw link with aggregated = 0 944 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 945 * 946 * two or more slaves on one sdw link with aggregated = 0 947 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 948 * 949 * multiple links with multiple slaves with aggregated = 1 950 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 951 */ 952 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 953 struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 954 int *codec_num, unsigned int *group_id, 955 bool *group_generated, int adr_index) 956 { 957 const struct snd_soc_acpi_adr_device *adr_d; 958 const struct snd_soc_acpi_link_adr *adr_next; 959 bool no_aggregation; 960 int index = 0; 961 int i; 962 963 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 964 adr_d = &adr_link->adr_d[adr_index]; 965 966 /* make sure the link mask has a single bit set */ 967 if (!is_power_of_2(adr_link->mask)) 968 return -EINVAL; 969 970 cpu_dai_id[index++] = ffs(adr_link->mask) - 1; 971 if (!adr_d->endpoints->aggregated || no_aggregation) { 972 *cpu_dai_num = 1; 973 *codec_num = 1; 974 *group_id = 0; 975 return 0; 976 } 977 978 *group_id = adr_d->endpoints->group_id; 979 980 /* Count endpoints with the same group_id in the adr_link */ 981 *codec_num = 0; 982 for (i = 0; i < adr_link->num_adr; i++) { 983 if (adr_link->adr_d[i].endpoints->aggregated && 984 adr_link->adr_d[i].endpoints->group_id == *group_id) 985 (*codec_num)++; 986 } 987 988 /* gather other link ID of slaves in the same group */ 989 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; 990 adr_next++) { 991 const struct snd_soc_acpi_endpoint *endpoint; 992 993 endpoint = adr_next->adr_d->endpoints; 994 if (!endpoint->aggregated || 995 endpoint->group_id != *group_id) 996 continue; 997 998 /* make sure the link mask has a single bit set */ 999 if (!is_power_of_2(adr_next->mask)) 1000 return -EINVAL; 1001 1002 if (index >= SDW_MAX_CPU_DAIS) { 1003 dev_err(dev, " cpu_dai_id array overflows"); 1004 return -EINVAL; 1005 } 1006 1007 cpu_dai_id[index++] = ffs(adr_next->mask) - 1; 1008 for (i = 0; i < adr_next->num_adr; i++) { 1009 if (adr_next->adr_d[i].endpoints->aggregated && 1010 adr_next->adr_d[i].endpoints->group_id == *group_id) 1011 (*codec_num)++; 1012 } 1013 } 1014 1015 /* 1016 * indicate CPU DAIs for this group have been generated 1017 * to avoid generating CPU DAIs for this group again. 1018 */ 1019 group_generated[*group_id] = true; 1020 *cpu_dai_num = index; 1021 1022 return 0; 1023 } 1024 1025 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 1026 1027 static int create_sdw_dailink(struct snd_soc_card *card, 1028 struct device *dev, int *link_index, 1029 struct snd_soc_dai_link *dai_links, 1030 int sdw_be_num, int sdw_cpu_dai_num, 1031 struct snd_soc_dai_link_component *cpus, 1032 const struct snd_soc_acpi_link_adr *link, 1033 int *cpu_id, bool *group_generated, 1034 struct snd_soc_codec_conf *codec_conf, 1035 int codec_count, int *link_id, 1036 int *codec_conf_index, 1037 bool *ignore_pch_dmic, 1038 bool append_codec_type, 1039 int adr_index) 1040 { 1041 const struct snd_soc_acpi_link_adr *link_next; 1042 struct snd_soc_dai_link_component *codecs; 1043 int cpu_dai_id[SDW_MAX_CPU_DAIS]; 1044 int cpu_dai_num, cpu_dai_index; 1045 unsigned int group_id; 1046 int codec_idx = 0; 1047 int i = 0, j = 0; 1048 int codec_index; 1049 int codec_num; 1050 int stream; 1051 int ret; 1052 int k; 1053 1054 ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 1055 &group_id, group_generated, adr_index); 1056 if (ret) 1057 return ret; 1058 1059 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 1060 if (!codecs) 1061 return -ENOMEM; 1062 1063 /* generate codec name on different links in the same group */ 1064 for (link_next = link; link_next && link_next->num_adr && 1065 i < cpu_dai_num; link_next++) { 1066 const struct snd_soc_acpi_endpoint *endpoints; 1067 1068 endpoints = link_next->adr_d->endpoints; 1069 if (group_id && (!endpoints->aggregated || 1070 endpoints->group_id != group_id)) 1071 continue; 1072 1073 /* skip the link excluded by this processed group */ 1074 if (cpu_dai_id[i] != ffs(link_next->mask) - 1) 1075 continue; 1076 1077 ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, 1078 codec_conf, codec_count, codec_conf_index, adr_index); 1079 if (ret < 0) 1080 return ret; 1081 1082 /* check next link to create codec dai in the processed group */ 1083 i++; 1084 codec_idx += link_next->num_adr; 1085 } 1086 1087 /* find codec info to create BE DAI */ 1088 codec_index = find_codec_info_part(link->adr_d[adr_index].adr); 1089 if (codec_index < 0) 1090 return codec_index; 1091 1092 if (codec_info_list[codec_index].ignore_pch_dmic) 1093 *ignore_pch_dmic = true; 1094 1095 /* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */ 1096 if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP && 1097 *link_id < SDW_AMP_DAI_ID) 1098 *link_id = SDW_AMP_DAI_ID; 1099 1100 /* 1101 * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to 1102 * keep sdw DMIC and HDMI setting static in UCM 1103 */ 1104 if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC && 1105 *link_id < SDW_DMIC_DAI_ID) 1106 *link_id = SDW_DMIC_DAI_ID; 1107 1108 cpu_dai_index = *cpu_id; 1109 for_each_pcm_streams(stream) { 1110 char *name, *cpu_name; 1111 int playback, capture; 1112 static const char * const sdw_stream_name[] = { 1113 "SDW%d-Playback", 1114 "SDW%d-Capture", 1115 "SDW%d-Playback-%s", 1116 "SDW%d-Capture-%s", 1117 }; 1118 1119 if (!codec_info_list[codec_index].direction[stream]) 1120 continue; 1121 1122 /* create stream name according to first link id */ 1123 if (append_codec_type) { 1124 name = devm_kasprintf(dev, GFP_KERNEL, 1125 sdw_stream_name[stream + 2], cpu_dai_id[0], 1126 type_strings[codec_info_list[codec_index].codec_type]); 1127 } else { 1128 name = devm_kasprintf(dev, GFP_KERNEL, 1129 sdw_stream_name[stream], cpu_dai_id[0]); 1130 } 1131 if (!name) 1132 return -ENOMEM; 1133 1134 /* 1135 * generate CPU DAI name base on the sdw link ID and 1136 * PIN ID with offset of 2 according to sdw dai driver. 1137 */ 1138 for (k = 0; k < cpu_dai_num; k++) { 1139 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1140 "SDW%d Pin%d", cpu_dai_id[k], 1141 j + SDW_INTEL_BIDIR_PDI_BASE); 1142 if (!cpu_name) 1143 return -ENOMEM; 1144 1145 if (cpu_dai_index >= sdw_cpu_dai_num) { 1146 dev_err(dev, "invalid cpu dai index %d", 1147 cpu_dai_index); 1148 return -EINVAL; 1149 } 1150 1151 cpus[cpu_dai_index++].dai_name = cpu_name; 1152 } 1153 1154 /* 1155 * We create sdw dai links at first stage, so link index should 1156 * not be larger than sdw_be_num 1157 */ 1158 if (*link_index >= sdw_be_num) { 1159 dev_err(dev, "invalid dai link index %d", *link_index); 1160 return -EINVAL; 1161 } 1162 1163 if (*cpu_id >= sdw_cpu_dai_num) { 1164 dev_err(dev, " invalid cpu dai index %d", *cpu_id); 1165 return -EINVAL; 1166 } 1167 1168 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 1169 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 1170 init_dai_link(dev, dai_links + *link_index, (*link_id)++, name, 1171 playback, capture, 1172 cpus + *cpu_id, cpu_dai_num, 1173 codecs, codec_num, 1174 NULL, &sdw_ops); 1175 1176 /* 1177 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 1178 * based on wait_for_completion(), tag them as 'nonatomic'. 1179 */ 1180 dai_links[*link_index].nonatomic = true; 1181 1182 ret = set_codec_init_func(card, link, dai_links + (*link_index)++, 1183 playback, group_id); 1184 if (ret < 0) { 1185 dev_err(dev, "failed to init codec %d", codec_index); 1186 return ret; 1187 } 1188 1189 *cpu_id += cpu_dai_num; 1190 j++; 1191 } 1192 1193 return 0; 1194 } 1195 1196 #define IDISP_CODEC_MASK 0x4 1197 1198 static int sof_card_codec_conf_alloc(struct device *dev, 1199 struct snd_soc_acpi_mach_params *mach_params, 1200 struct snd_soc_codec_conf **codec_conf, 1201 int *codec_conf_count) 1202 { 1203 const struct snd_soc_acpi_link_adr *adr_link; 1204 struct snd_soc_codec_conf *c_conf; 1205 int num_codecs = 0; 1206 int i; 1207 1208 adr_link = mach_params->links; 1209 if (!adr_link) 1210 return -EINVAL; 1211 1212 /* generate DAI links by each sdw link */ 1213 for (; adr_link->num_adr; adr_link++) { 1214 for (i = 0; i < adr_link->num_adr; i++) { 1215 if (!adr_link->adr_d[i].name_prefix) { 1216 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1217 adr_link->adr_d[i].adr); 1218 return -EINVAL; 1219 } 1220 } 1221 num_codecs += adr_link->num_adr; 1222 } 1223 1224 c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL); 1225 if (!c_conf) 1226 return -ENOMEM; 1227 1228 *codec_conf = c_conf; 1229 *codec_conf_count = num_codecs; 1230 1231 return 0; 1232 } 1233 1234 static int sof_card_dai_links_create(struct device *dev, 1235 struct snd_soc_acpi_mach *mach, 1236 struct snd_soc_card *card) 1237 { 1238 int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; 1239 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1240 struct snd_soc_dai_link_component *idisp_components; 1241 struct snd_soc_dai_link_component *ssp_components; 1242 struct snd_soc_acpi_mach_params *mach_params; 1243 const struct snd_soc_acpi_link_adr *adr_link; 1244 struct snd_soc_dai_link_component *cpus; 1245 struct snd_soc_codec_conf *codec_conf; 1246 bool append_codec_type = false; 1247 bool ignore_pch_dmic = false; 1248 int codec_conf_count; 1249 int codec_conf_index = 0; 1250 bool group_generated[SDW_MAX_GROUPS]; 1251 int ssp_codec_index, ssp_mask; 1252 struct snd_soc_dai_link *links; 1253 int num_links, link_index = 0; 1254 char *name, *cpu_name; 1255 int total_cpu_dai_num; 1256 int sdw_cpu_dai_num; 1257 int i, j, be_id = 0; 1258 int cpu_id = 0; 1259 int comp_num; 1260 int ret; 1261 1262 mach_params = &mach->mach_params; 1263 1264 /* allocate codec conf, will be populated when dailinks are created */ 1265 ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count); 1266 if (ret < 0) 1267 return ret; 1268 1269 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1270 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1271 codec_info_list[i].amp_num = 0; 1272 1273 if (mach_params->codec_mask & IDISP_CODEC_MASK) { 1274 ctx->idisp_codec = true; 1275 1276 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1277 hdmi_num = SOF_TGL_HDMI_COUNT; 1278 else 1279 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1280 } 1281 1282 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1283 /* 1284 * on generic tgl platform, I2S or sdw mode is supported 1285 * based on board rework. A ACPI device is registered in 1286 * system only when I2S mode is supported, not sdw mode. 1287 * Here check ACPI ID to confirm I2S is supported. 1288 */ 1289 ssp_codec_index = find_codec_info_acpi(mach->id); 1290 ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0; 1291 comp_num = hdmi_num + ssp_num; 1292 1293 ret = get_sdw_dailink_info(dev, mach_params->links, 1294 &sdw_be_num, &sdw_cpu_dai_num); 1295 if (ret < 0) { 1296 dev_err(dev, "failed to get sdw link info %d", ret); 1297 return ret; 1298 } 1299 1300 /* enable dmic01 & dmic16k */ 1301 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; 1302 comp_num += dmic_num; 1303 1304 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1305 comp_num++; 1306 1307 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, 1308 dmic_num, ctx->idisp_codec ? hdmi_num : 0); 1309 1310 /* allocate BE dailinks */ 1311 num_links = comp_num + sdw_be_num; 1312 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL); 1313 1314 /* allocated CPU DAIs */ 1315 total_cpu_dai_num = comp_num + sdw_cpu_dai_num; 1316 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus), 1317 GFP_KERNEL); 1318 1319 if (!links || !cpus) 1320 return -ENOMEM; 1321 1322 /* SDW */ 1323 if (!sdw_be_num) 1324 goto SSP; 1325 1326 adr_link = mach_params->links; 1327 if (!adr_link) 1328 return -EINVAL; 1329 1330 /* 1331 * SoundWire Slaves aggregated in the same group may be 1332 * located on different hardware links. Clear array to indicate 1333 * CPU DAIs for this group have not been generated. 1334 */ 1335 for (i = 0; i < SDW_MAX_GROUPS; i++) 1336 group_generated[i] = false; 1337 1338 for (; adr_link->num_adr; adr_link++) { 1339 /* 1340 * If there are two or more different devices on the same sdw link, we have to 1341 * append the codec type to the dai link name to prevent duplicated dai link name. 1342 * The same type devices on the same sdw link will be in the same 1343 * snd_soc_acpi_adr_device array. They won't be described in different adr_links. 1344 */ 1345 for (i = 0; i < adr_link->num_adr; i++) { 1346 for (j = 0; j < i; j++) { 1347 if ((SDW_PART_ID(adr_link->adr_d[i].adr) != 1348 SDW_PART_ID(adr_link->adr_d[j].adr)) || 1349 (SDW_MFG_ID(adr_link->adr_d[i].adr) != 1350 SDW_MFG_ID(adr_link->adr_d[i].adr))) { 1351 append_codec_type = true; 1352 goto out; 1353 } 1354 } 1355 } 1356 } 1357 out: 1358 1359 /* generate DAI links by each sdw link */ 1360 for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { 1361 for (i = 0; i < adr_link->num_adr; i++) { 1362 const struct snd_soc_acpi_endpoint *endpoint; 1363 1364 endpoint = adr_link->adr_d[i].endpoints; 1365 if (endpoint->aggregated && !endpoint->group_id) { 1366 dev_err(dev, "invalid group id on link %x", 1367 adr_link->mask); 1368 continue; 1369 } 1370 1371 /* this group has been generated */ 1372 if (endpoint->aggregated && 1373 group_generated[endpoint->group_id]) 1374 continue; 1375 1376 ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, 1377 sdw_cpu_dai_num, cpus, adr_link, 1378 &cpu_id, group_generated, 1379 codec_conf, codec_conf_count, 1380 &be_id, &codec_conf_index, 1381 &ignore_pch_dmic, append_codec_type, i); 1382 if (ret < 0) { 1383 dev_err(dev, "failed to create dai link %d", link_index); 1384 return ret; 1385 } 1386 } 1387 } 1388 1389 SSP: 1390 /* SSP */ 1391 if (!ssp_num) 1392 goto DMIC; 1393 1394 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1395 struct sof_sdw_codec_info *info; 1396 int playback, capture; 1397 char *codec_name; 1398 1399 if (!(ssp_mask & 0x1)) 1400 continue; 1401 1402 name = devm_kasprintf(dev, GFP_KERNEL, 1403 "SSP%d-Codec", i); 1404 if (!name) 1405 return -ENOMEM; 1406 1407 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1408 if (!cpu_name) 1409 return -ENOMEM; 1410 1411 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1412 GFP_KERNEL); 1413 if (!ssp_components) 1414 return -ENOMEM; 1415 1416 info = &codec_info_list[ssp_codec_index]; 1417 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1418 info->acpi_id, j++); 1419 if (!codec_name) 1420 return -ENOMEM; 1421 1422 ssp_components->name = codec_name; 1423 ssp_components->dai_name = info->dai_name; 1424 cpus[cpu_id].dai_name = cpu_name; 1425 1426 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; 1427 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; 1428 init_dai_link(dev, links + link_index, be_id, name, 1429 playback, capture, 1430 cpus + cpu_id, 1, 1431 ssp_components, 1, 1432 NULL, info->ops); 1433 1434 ret = info->init(card, NULL, links + link_index, info, 0); 1435 if (ret < 0) 1436 return ret; 1437 1438 INC_ID(be_id, cpu_id, link_index); 1439 } 1440 1441 DMIC: 1442 /* dmic */ 1443 if (dmic_num > 0) { 1444 if (ignore_pch_dmic) { 1445 dev_warn(dev, "Ignoring PCH DMIC\n"); 1446 goto HDMI; 1447 } 1448 cpus[cpu_id].dai_name = "DMIC01 Pin"; 1449 init_dai_link(dev, links + link_index, be_id, "dmic01", 1450 0, 1, // DMIC only supports capture 1451 cpus + cpu_id, 1, 1452 dmic_component, 1, 1453 sof_sdw_dmic_init, NULL); 1454 INC_ID(be_id, cpu_id, link_index); 1455 1456 cpus[cpu_id].dai_name = "DMIC16k Pin"; 1457 init_dai_link(dev, links + link_index, be_id, "dmic16k", 1458 0, 1, // DMIC only supports capture 1459 cpus + cpu_id, 1, 1460 dmic_component, 1, 1461 /* don't call sof_sdw_dmic_init() twice */ 1462 NULL, NULL); 1463 INC_ID(be_id, cpu_id, link_index); 1464 } 1465 1466 HDMI: 1467 /* HDMI */ 1468 if (hdmi_num > 0) { 1469 idisp_components = devm_kcalloc(dev, hdmi_num, 1470 sizeof(*idisp_components), 1471 GFP_KERNEL); 1472 if (!idisp_components) 1473 return -ENOMEM; 1474 } 1475 1476 for (i = 0; i < hdmi_num; i++) { 1477 name = devm_kasprintf(dev, GFP_KERNEL, 1478 "iDisp%d", i + 1); 1479 if (!name) 1480 return -ENOMEM; 1481 1482 if (ctx->idisp_codec) { 1483 idisp_components[i].name = "ehdaudio0D2"; 1484 idisp_components[i].dai_name = devm_kasprintf(dev, 1485 GFP_KERNEL, 1486 "intel-hdmi-hifi%d", 1487 i + 1); 1488 if (!idisp_components[i].dai_name) 1489 return -ENOMEM; 1490 } else { 1491 idisp_components[i].name = "snd-soc-dummy"; 1492 idisp_components[i].dai_name = "snd-soc-dummy-dai"; 1493 } 1494 1495 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1496 "iDisp%d Pin", i + 1); 1497 if (!cpu_name) 1498 return -ENOMEM; 1499 1500 cpus[cpu_id].dai_name = cpu_name; 1501 init_dai_link(dev, links + link_index, be_id, name, 1502 1, 0, // HDMI only supports playback 1503 cpus + cpu_id, 1, 1504 idisp_components + i, 1, 1505 sof_sdw_hdmi_init, NULL); 1506 INC_ID(be_id, cpu_id, link_index); 1507 } 1508 1509 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1510 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1511 SOF_BT_OFFLOAD_SSP_SHIFT; 1512 1513 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1514 if (!name) 1515 return -ENOMEM; 1516 1517 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1518 GFP_KERNEL); 1519 if (!ssp_components) 1520 return -ENOMEM; 1521 1522 ssp_components->name = "snd-soc-dummy"; 1523 ssp_components->dai_name = "snd-soc-dummy-dai"; 1524 1525 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1526 if (!cpu_name) 1527 return -ENOMEM; 1528 1529 cpus[cpu_id].dai_name = cpu_name; 1530 init_dai_link(dev, links + link_index, be_id, name, 1, 1, 1531 cpus + cpu_id, 1, ssp_components, 1, NULL, NULL); 1532 } 1533 1534 card->dai_link = links; 1535 card->num_links = num_links; 1536 1537 card->codec_conf = codec_conf; 1538 card->num_configs = codec_conf_count; 1539 1540 return 0; 1541 } 1542 1543 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1544 { 1545 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1546 int ret = 0; 1547 int i; 1548 1549 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1550 if (codec_info_list[i].codec_card_late_probe) { 1551 ret = codec_info_list[i].codec_card_late_probe(card); 1552 1553 if (ret < 0) 1554 return ret; 1555 } 1556 } 1557 1558 if (ctx->idisp_codec) 1559 ret = sof_sdw_hdmi_card_late_probe(card); 1560 1561 return ret; 1562 } 1563 1564 /* SoC card */ 1565 static const char sdw_card_long_name[] = "Intel Soundwire SOF"; 1566 1567 static struct snd_soc_card card_sof_sdw = { 1568 .name = "soundwire", 1569 .owner = THIS_MODULE, 1570 .late_probe = sof_sdw_card_late_probe, 1571 }; 1572 1573 static void mc_dailink_exit_loop(struct snd_soc_card *card) 1574 { 1575 struct snd_soc_dai_link *link; 1576 int ret; 1577 int i, j; 1578 1579 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1580 if (!codec_info_list[i].exit) 1581 continue; 1582 /* 1583 * We don't need to call .exit function if there is no matched 1584 * dai link found. 1585 */ 1586 for_each_card_prelinks(card, j, link) { 1587 if (!strcmp(link->codecs[0].dai_name, 1588 codec_info_list[i].dai_name)) { 1589 ret = codec_info_list[i].exit(card, link); 1590 if (ret) 1591 dev_warn(card->dev, 1592 "codec exit failed %d\n", 1593 ret); 1594 break; 1595 } 1596 } 1597 } 1598 } 1599 1600 static int mc_probe(struct platform_device *pdev) 1601 { 1602 struct snd_soc_card *card = &card_sof_sdw; 1603 struct snd_soc_acpi_mach *mach; 1604 struct mc_private *ctx; 1605 int amp_num = 0, i; 1606 int ret; 1607 1608 dev_dbg(&pdev->dev, "Entry\n"); 1609 1610 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1611 if (!ctx) 1612 return -ENOMEM; 1613 1614 dmi_check_system(sof_sdw_quirk_table); 1615 1616 if (quirk_override != -1) { 1617 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", 1618 sof_sdw_quirk, quirk_override); 1619 sof_sdw_quirk = quirk_override; 1620 } 1621 log_quirks(&pdev->dev); 1622 1623 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 1624 1625 card->dev = &pdev->dev; 1626 snd_soc_card_set_drvdata(card, ctx); 1627 1628 mach = pdev->dev.platform_data; 1629 ret = sof_card_dai_links_create(&pdev->dev, mach, 1630 card); 1631 if (ret < 0) 1632 return ret; 1633 1634 /* 1635 * the default amp_num is zero for each codec and 1636 * amp_num will only be increased for active amp 1637 * codecs on used platform 1638 */ 1639 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1640 amp_num += codec_info_list[i].amp_num; 1641 1642 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1643 "cfg-spk:%d cfg-amp:%d", 1644 (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 1645 ? 4 : 2, amp_num); 1646 if (!card->components) 1647 return -ENOMEM; 1648 1649 if (mach->mach_params.dmic_num) { 1650 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1651 "%s mic:dmic cfg-mics:%d", 1652 card->components, 1653 mach->mach_params.dmic_num); 1654 if (!card->components) 1655 return -ENOMEM; 1656 } 1657 1658 card->long_name = sdw_card_long_name; 1659 1660 /* Register the card */ 1661 ret = devm_snd_soc_register_card(&pdev->dev, card); 1662 if (ret) { 1663 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); 1664 mc_dailink_exit_loop(card); 1665 return ret; 1666 } 1667 1668 platform_set_drvdata(pdev, card); 1669 1670 return ret; 1671 } 1672 1673 static void mc_remove(struct platform_device *pdev) 1674 { 1675 struct snd_soc_card *card = platform_get_drvdata(pdev); 1676 1677 mc_dailink_exit_loop(card); 1678 } 1679 1680 static struct platform_driver sof_sdw_driver = { 1681 .driver = { 1682 .name = "sof_sdw", 1683 .pm = &snd_soc_pm_ops, 1684 }, 1685 .probe = mc_probe, 1686 .remove_new = mc_remove, 1687 }; 1688 1689 module_platform_driver(sof_sdw_driver); 1690 1691 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1692 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1693 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1694 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1695 MODULE_LICENSE("GPL v2"); 1696 MODULE_ALIAS("platform:sof_sdw"); 1697 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 1698 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 1699