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