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