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 #define SDW_MAX_LINKS 4 26 27 /* To store SDW Pin index for each SoundWire link */ 28 static unsigned int sdw_pin_index[SDW_MAX_LINKS]; 29 30 static void log_quirks(struct device *dev) 31 { 32 if (SOF_JACK_JDSRC(sof_sdw_quirk)) 33 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", 34 SOF_JACK_JDSRC(sof_sdw_quirk)); 35 if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 36 dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); 37 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 38 dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); 39 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) 40 dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); 41 if (SOF_SSP_GET_PORT(sof_sdw_quirk)) 42 dev_dbg(dev, "SSP port %ld\n", 43 SOF_SSP_GET_PORT(sof_sdw_quirk)); 44 if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) 45 dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); 46 } 47 48 static int sof_sdw_quirk_cb(const struct dmi_system_id *id) 49 { 50 sof_sdw_quirk = (unsigned long)id->driver_data; 51 return 1; 52 } 53 54 static const struct dmi_system_id sof_sdw_quirk_table[] = { 55 /* CometLake devices */ 56 { 57 .callback = sof_sdw_quirk_cb, 58 .matches = { 59 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 60 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), 61 }, 62 .driver_data = (void *)SOF_SDW_PCH_DMIC, 63 }, 64 { 65 .callback = sof_sdw_quirk_cb, 66 .matches = { 67 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 68 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 69 }, 70 .driver_data = (void *)RT711_JD2, 71 }, 72 { 73 /* early version of SKU 09C6 */ 74 .callback = sof_sdw_quirk_cb, 75 .matches = { 76 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 77 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 78 }, 79 .driver_data = (void *)RT711_JD2, 80 }, 81 { 82 .callback = sof_sdw_quirk_cb, 83 .matches = { 84 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 85 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 86 }, 87 .driver_data = (void *)(RT711_JD2 | 88 SOF_SDW_FOUR_SPK), 89 }, 90 { 91 .callback = sof_sdw_quirk_cb, 92 .matches = { 93 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 94 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 95 }, 96 .driver_data = (void *)(RT711_JD2 | 97 SOF_SDW_FOUR_SPK), 98 }, 99 /* IceLake devices */ 100 { 101 .callback = sof_sdw_quirk_cb, 102 .matches = { 103 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 104 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), 105 }, 106 .driver_data = (void *)SOF_SDW_PCH_DMIC, 107 }, 108 /* TigerLake devices */ 109 { 110 .callback = sof_sdw_quirk_cb, 111 .matches = { 112 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 113 DMI_MATCH(DMI_PRODUCT_NAME, 114 "Tiger Lake Client Platform"), 115 }, 116 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 117 RT711_JD1 | 118 SOF_SDW_PCH_DMIC | 119 SOF_SSP_PORT(SOF_I2S_SSP2)), 120 }, 121 { 122 .callback = sof_sdw_quirk_cb, 123 .matches = { 124 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 125 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") 126 }, 127 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 128 RT711_JD2), 129 }, 130 { 131 /* another SKU of Dell Latitude 9520 */ 132 .callback = sof_sdw_quirk_cb, 133 .matches = { 134 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 135 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F") 136 }, 137 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 138 RT711_JD2), 139 }, 140 { 141 /* Dell XPS 9710 */ 142 .callback = sof_sdw_quirk_cb, 143 .matches = { 144 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 145 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") 146 }, 147 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 148 RT711_JD2 | 149 SOF_SDW_FOUR_SPK), 150 }, 151 { 152 .callback = sof_sdw_quirk_cb, 153 .matches = { 154 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 155 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") 156 }, 157 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 158 RT711_JD2 | 159 SOF_SDW_FOUR_SPK), 160 }, 161 { 162 .callback = sof_sdw_quirk_cb, 163 .matches = { 164 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 165 DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), 166 }, 167 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 168 SOF_SDW_PCH_DMIC | 169 SOF_SDW_FOUR_SPK | 170 SOF_BT_OFFLOAD_SSP(2) | 171 SOF_SSP_BT_OFFLOAD_PRESENT), 172 }, 173 { 174 .callback = sof_sdw_quirk_cb, 175 .matches = { 176 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 177 DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), 178 }, 179 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 180 SOF_SDW_PCH_DMIC | 181 SOF_SDW_FOUR_SPK), 182 }, 183 { 184 /* 185 * this entry covers multiple HP SKUs. The family name 186 * does not seem robust enough, so we use a partial 187 * match that ignores the product name suffix 188 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) 189 */ 190 .callback = sof_sdw_quirk_cb, 191 .matches = { 192 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 193 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"), 194 }, 195 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 196 SOF_SDW_PCH_DMIC | 197 RT711_JD1), 198 }, 199 { 200 /* 201 * this entry covers HP Spectre x360 where the DMI information 202 * changed somehow 203 */ 204 .callback = sof_sdw_quirk_cb, 205 .matches = { 206 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 207 DMI_MATCH(DMI_BOARD_NAME, "8709"), 208 }, 209 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 210 SOF_SDW_PCH_DMIC | 211 RT711_JD1), 212 }, 213 { 214 /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */ 215 .callback = sof_sdw_quirk_cb, 216 .matches = { 217 DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 218 DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"), 219 }, 220 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 221 SOF_SDW_PCH_DMIC | 222 RT711_JD1), 223 }, 224 { 225 /* NUC15 LAPBC710 skews */ 226 .callback = sof_sdw_quirk_cb, 227 .matches = { 228 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 229 DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"), 230 }, 231 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 232 SOF_SDW_PCH_DMIC | 233 RT711_JD1), 234 }, 235 { 236 /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ 237 .callback = sof_sdw_quirk_cb, 238 .matches = { 239 DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 240 DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"), 241 }, 242 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 243 SOF_SDW_PCH_DMIC | 244 RT711_JD2_100K), 245 }, 246 { 247 /* NUC15 LAPRC710 skews */ 248 .callback = sof_sdw_quirk_cb, 249 .matches = { 250 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 251 DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"), 252 }, 253 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 254 SOF_SDW_PCH_DMIC | 255 RT711_JD2_100K), 256 }, 257 /* TigerLake-SDCA devices */ 258 { 259 .callback = sof_sdw_quirk_cb, 260 .matches = { 261 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 262 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") 263 }, 264 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 265 RT711_JD2 | 266 SOF_SDW_FOUR_SPK), 267 }, 268 { 269 .callback = sof_sdw_quirk_cb, 270 .matches = { 271 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 272 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45") 273 }, 274 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 275 RT711_JD2), 276 }, 277 /* AlderLake devices */ 278 { 279 .callback = sof_sdw_quirk_cb, 280 .matches = { 281 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 282 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), 283 }, 284 .driver_data = (void *)(RT711_JD2_100K | 285 SOF_SDW_TGL_HDMI | 286 SOF_BT_OFFLOAD_SSP(2) | 287 SOF_SSP_BT_OFFLOAD_PRESENT), 288 }, 289 { 290 .callback = sof_sdw_quirk_cb, 291 .matches = { 292 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 293 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), 294 }, 295 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 296 SOF_SDW_PCH_DMIC | 297 SOF_SDW_FOUR_SPK | 298 SOF_BT_OFFLOAD_SSP(2) | 299 SOF_SSP_BT_OFFLOAD_PRESENT), 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, "0AF0") 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, "0AF3"), 316 }, 317 /* No Jack */ 318 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 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, "0AFE") 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, "0AFF") 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, "0B00") 346 }, 347 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 348 RT711_JD2 | 349 SOF_SDW_FOUR_SPK), 350 }, 351 { 352 .callback = sof_sdw_quirk_cb, 353 .matches = { 354 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 355 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") 356 }, 357 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 358 RT711_JD2 | 359 SOF_SDW_FOUR_SPK), 360 }, 361 { 362 .callback = sof_sdw_quirk_cb, 363 .matches = { 364 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 365 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11") 366 }, 367 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 368 RT711_JD2 | 369 SOF_SDW_FOUR_SPK), 370 }, 371 { 372 .callback = sof_sdw_quirk_cb, 373 .matches = { 374 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 375 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12") 376 }, 377 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 378 RT711_JD2 | 379 SOF_SDW_FOUR_SPK), 380 }, 381 { 382 .callback = sof_sdw_quirk_cb, 383 .matches = { 384 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 385 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"), 386 }, 387 /* No Jack */ 388 .driver_data = (void *)SOF_SDW_TGL_HDMI, 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, "0B14"), 395 }, 396 /* No Jack */ 397 .driver_data = (void *)SOF_SDW_TGL_HDMI, 398 }, 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, "0B29"), 405 }, 406 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 407 RT711_JD2 | 408 SOF_SDW_FOUR_SPK), 409 }, 410 { 411 .callback = sof_sdw_quirk_cb, 412 .matches = { 413 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 414 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"), 415 }, 416 /* No Jack */ 417 .driver_data = (void *)SOF_SDW_TGL_HDMI, 418 }, 419 { 420 .callback = sof_sdw_quirk_cb, 421 .matches = { 422 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 423 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"), 424 }, 425 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 426 RT711_JD2), 427 }, 428 /* RaptorLake devices */ 429 { 430 .callback = sof_sdw_quirk_cb, 431 .matches = { 432 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 433 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA") 434 }, 435 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 436 RT711_JD2 | 437 SOF_SDW_FOUR_SPK), 438 }, 439 { 440 .callback = sof_sdw_quirk_cb, 441 .matches = { 442 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 443 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F") 444 }, 445 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 446 RT711_JD2 | 447 SOF_SDW_FOUR_SPK), 448 }, 449 { 450 .callback = sof_sdw_quirk_cb, 451 .matches = { 452 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 453 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"), 454 }, 455 /* No Jack */ 456 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 457 SOF_SDW_FOUR_SPK), 458 }, 459 { 460 .callback = sof_sdw_quirk_cb, 461 .matches = { 462 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 463 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11") 464 }, 465 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 466 RT711_JD2 | 467 SOF_SDW_FOUR_SPK), 468 }, 469 { 470 .callback = sof_sdw_quirk_cb, 471 .matches = { 472 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 473 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40") 474 }, 475 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 476 RT711_JD2 | 477 SOF_SDW_FOUR_SPK), 478 }, 479 { 480 .callback = sof_sdw_quirk_cb, 481 .matches = { 482 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 483 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F") 484 }, 485 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 486 RT711_JD2 | 487 SOF_SDW_FOUR_SPK), 488 }, 489 /* MeteorLake devices */ 490 { 491 .callback = sof_sdw_quirk_cb, 492 .matches = { 493 DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"), 494 }, 495 .driver_data = (void *)(RT711_JD1), 496 }, 497 { 498 .callback = sof_sdw_quirk_cb, 499 .matches = { 500 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 501 DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"), 502 }, 503 .driver_data = (void *)(RT711_JD2_100K), 504 }, 505 { 506 .callback = sof_sdw_quirk_cb, 507 .matches = { 508 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 509 DMI_MATCH(DMI_PRODUCT_NAME, "Rex"), 510 }, 511 .driver_data = (void *)(SOF_SDW_PCH_DMIC | 512 SOF_BT_OFFLOAD_SSP(1) | 513 SOF_SSP_BT_OFFLOAD_PRESENT), 514 }, 515 { 516 .callback = sof_sdw_quirk_cb, 517 .matches = { 518 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 519 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"), 520 }, 521 .driver_data = (void *)(RT711_JD2), 522 }, 523 524 /* LunarLake devices */ 525 { 526 .callback = sof_sdw_quirk_cb, 527 .matches = { 528 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 529 DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"), 530 }, 531 .driver_data = (void *)(RT711_JD2), 532 }, 533 {} 534 }; 535 536 static struct snd_soc_dai_link_component dmic_component[] = { 537 { 538 .name = "dmic-codec", 539 .dai_name = "dmic-hifi", 540 } 541 }; 542 543 static struct snd_soc_dai_link_component platform_component[] = { 544 { 545 /* name might be overridden during probe */ 546 .name = "0000:00:1f.3" 547 } 548 }; 549 550 /* these wrappers are only needed to avoid typecast compilation errors */ 551 int sdw_startup(struct snd_pcm_substream *substream) 552 { 553 return sdw_startup_stream(substream); 554 } 555 556 int sdw_prepare(struct snd_pcm_substream *substream) 557 { 558 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 559 struct sdw_stream_runtime *sdw_stream; 560 struct snd_soc_dai *dai; 561 562 /* Find stream from first CPU DAI */ 563 dai = asoc_rtd_to_cpu(rtd, 0); 564 565 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 566 if (IS_ERR(sdw_stream)) { 567 dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 568 return PTR_ERR(sdw_stream); 569 } 570 571 return sdw_prepare_stream(sdw_stream); 572 } 573 574 int sdw_trigger(struct snd_pcm_substream *substream, int cmd) 575 { 576 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 577 struct sdw_stream_runtime *sdw_stream; 578 struct snd_soc_dai *dai; 579 int ret; 580 581 /* Find stream from first CPU DAI */ 582 dai = asoc_rtd_to_cpu(rtd, 0); 583 584 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 585 if (IS_ERR(sdw_stream)) { 586 dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 587 return PTR_ERR(sdw_stream); 588 } 589 590 switch (cmd) { 591 case SNDRV_PCM_TRIGGER_START: 592 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 593 case SNDRV_PCM_TRIGGER_RESUME: 594 ret = sdw_enable_stream(sdw_stream); 595 break; 596 597 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 598 case SNDRV_PCM_TRIGGER_SUSPEND: 599 case SNDRV_PCM_TRIGGER_STOP: 600 ret = sdw_disable_stream(sdw_stream); 601 break; 602 default: 603 ret = -EINVAL; 604 break; 605 } 606 607 if (ret) 608 dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret); 609 610 return ret; 611 } 612 613 int sdw_hw_params(struct snd_pcm_substream *substream, 614 struct snd_pcm_hw_params *params) 615 { 616 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 617 int ch = params_channels(params); 618 struct snd_soc_dai *codec_dai; 619 struct snd_soc_dai *cpu_dai; 620 unsigned int ch_mask; 621 int num_codecs; 622 int step; 623 int i; 624 int j; 625 626 if (!rtd->dai_link->codec_ch_maps) 627 return 0; 628 629 /* Identical data will be sent to all codecs in playback */ 630 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 631 ch_mask = GENMASK(ch - 1, 0); 632 step = 0; 633 } else { 634 num_codecs = rtd->dai_link->num_codecs; 635 636 if (ch < num_codecs || ch % num_codecs != 0) { 637 dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", 638 ch, num_codecs); 639 return -EINVAL; 640 } 641 642 ch_mask = GENMASK(ch / num_codecs - 1, 0); 643 step = hweight_long(ch_mask); 644 645 } 646 647 /* 648 * The captured data will be combined from each cpu DAI if the dai 649 * link has more than one codec DAIs. Set codec channel mask and 650 * ASoC will set the corresponding channel numbers for each cpu dai. 651 */ 652 for_each_rtd_cpu_dais(rtd, i, cpu_dai) { 653 for_each_rtd_codec_dais(rtd, j, codec_dai) { 654 if (rtd->dai_link->codec_ch_maps[j].connected_cpu_id != i) 655 continue; 656 rtd->dai_link->codec_ch_maps[j].ch_mask = ch_mask << (j * step); 657 } 658 } 659 return 0; 660 } 661 662 int sdw_hw_free(struct snd_pcm_substream *substream) 663 { 664 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 665 struct sdw_stream_runtime *sdw_stream; 666 struct snd_soc_dai *dai; 667 668 /* Find stream from first CPU DAI */ 669 dai = asoc_rtd_to_cpu(rtd, 0); 670 671 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 672 if (IS_ERR(sdw_stream)) { 673 dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 674 return PTR_ERR(sdw_stream); 675 } 676 677 return sdw_deprepare_stream(sdw_stream); 678 } 679 680 void sdw_shutdown(struct snd_pcm_substream *substream) 681 { 682 sdw_shutdown_stream(substream); 683 } 684 685 static const struct snd_soc_ops sdw_ops = { 686 .startup = sdw_startup, 687 .prepare = sdw_prepare, 688 .trigger = sdw_trigger, 689 .hw_params = sdw_hw_params, 690 .hw_free = sdw_hw_free, 691 .shutdown = sdw_shutdown, 692 }; 693 694 static struct sof_sdw_codec_info codec_info_list[] = { 695 { 696 .part_id = 0x700, 697 .dais = { 698 { 699 .direction = {true, true}, 700 .dai_name = "rt700-aif1", 701 .dai_type = SOF_SDW_DAI_TYPE_JACK, 702 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 703 .init = sof_sdw_rt700_init, 704 }, 705 }, 706 .dai_num = 1, 707 }, 708 { 709 .part_id = 0x711, 710 .version_id = 3, 711 .dais = { 712 { 713 .direction = {true, true}, 714 .dai_name = "rt711-sdca-aif1", 715 .dai_type = SOF_SDW_DAI_TYPE_JACK, 716 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 717 .init = sof_sdw_rt_sdca_jack_init, 718 .exit = sof_sdw_rt_sdca_jack_exit, 719 }, 720 }, 721 .dai_num = 1, 722 }, 723 { 724 .part_id = 0x711, 725 .version_id = 2, 726 .dais = { 727 { 728 .direction = {true, true}, 729 .dai_name = "rt711-aif1", 730 .dai_type = SOF_SDW_DAI_TYPE_JACK, 731 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 732 .init = sof_sdw_rt711_init, 733 .exit = sof_sdw_rt711_exit, 734 }, 735 }, 736 .dai_num = 1, 737 }, 738 { 739 .part_id = 0x712, 740 .version_id = 3, 741 .dais = { 742 { 743 .direction = {true, true}, 744 .dai_name = "rt712-sdca-aif1", 745 .dai_type = SOF_SDW_DAI_TYPE_JACK, 746 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 747 .init = sof_sdw_rt_sdca_jack_init, 748 .exit = sof_sdw_rt_sdca_jack_exit, 749 }, 750 { 751 .direction = {true, false}, 752 .dai_name = "rt712-sdca-aif2", 753 .dai_type = SOF_SDW_DAI_TYPE_AMP, 754 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 755 .init = sof_sdw_rt712_spk_init, 756 }, 757 }, 758 .dai_num = 2, 759 }, 760 { 761 .part_id = 0x1712, 762 .version_id = 3, 763 .dais = { 764 { 765 .direction = {false, true}, 766 .dai_name = "rt712-sdca-dmic-aif1", 767 .dai_type = SOF_SDW_DAI_TYPE_MIC, 768 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 769 .init = sof_sdw_rt712_sdca_dmic_init, 770 }, 771 }, 772 .dai_num = 1, 773 }, 774 { 775 .part_id = 0x713, 776 .version_id = 3, 777 .dais = { 778 { 779 .direction = {true, true}, 780 .dai_name = "rt712-sdca-aif1", 781 .dai_type = SOF_SDW_DAI_TYPE_JACK, 782 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 783 .init = sof_sdw_rt_sdca_jack_init, 784 .exit = sof_sdw_rt_sdca_jack_exit, 785 }, 786 }, 787 .dai_num = 1, 788 }, 789 { 790 .part_id = 0x1713, 791 .version_id = 3, 792 .dais = { 793 { 794 .direction = {false, true}, 795 .dai_name = "rt712-sdca-dmic-aif1", 796 .dai_type = SOF_SDW_DAI_TYPE_MIC, 797 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 798 .init = sof_sdw_rt712_sdca_dmic_init, 799 }, 800 }, 801 .dai_num = 1, 802 }, 803 { 804 .part_id = 0x1308, 805 .acpi_id = "10EC1308", 806 .dais = { 807 { 808 .direction = {true, false}, 809 .dai_name = "rt1308-aif", 810 .dai_type = SOF_SDW_DAI_TYPE_AMP, 811 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 812 .init = sof_sdw_rt_amp_init, 813 .exit = sof_sdw_rt_amp_exit, 814 }, 815 }, 816 .dai_num = 1, 817 .ops = &sof_sdw_rt1308_i2s_ops, 818 }, 819 { 820 .part_id = 0x1316, 821 .dais = { 822 { 823 .direction = {true, true}, 824 .dai_name = "rt1316-aif", 825 .dai_type = SOF_SDW_DAI_TYPE_AMP, 826 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 827 .init = sof_sdw_rt_amp_init, 828 .exit = sof_sdw_rt_amp_exit, 829 }, 830 }, 831 .dai_num = 1, 832 }, 833 { 834 .part_id = 0x1318, 835 .dais = { 836 { 837 .direction = {true, true}, 838 .dai_name = "rt1318-aif", 839 .dai_type = SOF_SDW_DAI_TYPE_AMP, 840 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 841 .init = sof_sdw_rt_amp_init, 842 .exit = sof_sdw_rt_amp_exit, 843 }, 844 }, 845 .dai_num = 1, 846 }, 847 { 848 .part_id = 0x714, 849 .version_id = 3, 850 .ignore_pch_dmic = true, 851 .dais = { 852 { 853 .direction = {false, true}, 854 .dai_name = "rt715-aif2", 855 .dai_type = SOF_SDW_DAI_TYPE_MIC, 856 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 857 .init = sof_sdw_rt715_sdca_init, 858 }, 859 }, 860 .dai_num = 1, 861 }, 862 { 863 .part_id = 0x715, 864 .version_id = 3, 865 .ignore_pch_dmic = true, 866 .dais = { 867 { 868 .direction = {false, true}, 869 .dai_name = "rt715-aif2", 870 .dai_type = SOF_SDW_DAI_TYPE_MIC, 871 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 872 .init = sof_sdw_rt715_sdca_init, 873 }, 874 }, 875 .dai_num = 1, 876 }, 877 { 878 .part_id = 0x714, 879 .version_id = 2, 880 .ignore_pch_dmic = true, 881 .dais = { 882 { 883 .direction = {false, true}, 884 .dai_name = "rt715-aif2", 885 .dai_type = SOF_SDW_DAI_TYPE_MIC, 886 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 887 .init = sof_sdw_rt715_init, 888 }, 889 }, 890 .dai_num = 1, 891 }, 892 { 893 .part_id = 0x715, 894 .version_id = 2, 895 .ignore_pch_dmic = true, 896 .dais = { 897 { 898 .direction = {false, true}, 899 .dai_name = "rt715-aif2", 900 .dai_type = SOF_SDW_DAI_TYPE_MIC, 901 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 902 .init = sof_sdw_rt715_init, 903 }, 904 }, 905 .dai_num = 1, 906 }, 907 { 908 .part_id = 0x8373, 909 .dais = { 910 { 911 .direction = {true, true}, 912 .dai_name = "max98373-aif1", 913 .dai_type = SOF_SDW_DAI_TYPE_AMP, 914 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 915 .init = sof_sdw_maxim_init, 916 }, 917 }, 918 .dai_num = 1, 919 }, 920 { 921 .part_id = 0x8363, 922 .dais = { 923 { 924 .direction = {true, false}, 925 .dai_name = "max98363-aif1", 926 .dai_type = SOF_SDW_DAI_TYPE_AMP, 927 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 928 .init = sof_sdw_maxim_init, 929 }, 930 }, 931 .dai_num = 1, 932 }, 933 { 934 .part_id = 0x5682, 935 .dais = { 936 { 937 .direction = {true, true}, 938 .dai_name = "rt5682-sdw", 939 .dai_type = SOF_SDW_DAI_TYPE_JACK, 940 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 941 .init = sof_sdw_rt5682_init, 942 }, 943 }, 944 .dai_num = 1, 945 }, 946 { 947 .part_id = 0x3556, 948 .dais = { 949 { 950 .direction = {true, true}, 951 .dai_name = "cs35l56-sdw1", 952 .dai_type = SOF_SDW_DAI_TYPE_AMP, 953 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 954 .init = sof_sdw_cs_amp_init, 955 }, 956 }, 957 .dai_num = 1, 958 }, 959 { 960 .part_id = 0x4242, 961 .dais = { 962 { 963 .direction = {true, true}, 964 .dai_name = "cs42l42-sdw", 965 .dai_type = SOF_SDW_DAI_TYPE_JACK, 966 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 967 .init = sof_sdw_cs42l42_init, 968 }, 969 }, 970 .dai_num = 1, 971 }, 972 { 973 .part_id = 0xaaaa, /* generic codec mockup */ 974 .version_id = 0, 975 .dais = { 976 { 977 .direction = {true, true}, 978 .dai_name = "sdw-mockup-aif1", 979 .dai_type = SOF_SDW_DAI_TYPE_JACK, 980 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 981 .init = NULL, 982 }, 983 }, 984 .dai_num = 1, 985 }, 986 { 987 .part_id = 0xaa55, /* headset codec mockup */ 988 .version_id = 0, 989 .dais = { 990 { 991 .direction = {true, true}, 992 .dai_name = "sdw-mockup-aif1", 993 .dai_type = SOF_SDW_DAI_TYPE_JACK, 994 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 995 .init = NULL, 996 }, 997 }, 998 .dai_num = 1, 999 }, 1000 { 1001 .part_id = 0x55aa, /* amplifier mockup */ 1002 .version_id = 0, 1003 .dais = { 1004 { 1005 .direction = {true, true}, 1006 .dai_name = "sdw-mockup-aif1", 1007 .dai_type = SOF_SDW_DAI_TYPE_AMP, 1008 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 1009 .init = NULL, 1010 }, 1011 }, 1012 .dai_num = 1, 1013 }, 1014 { 1015 .part_id = 0x5555, 1016 .version_id = 0, 1017 .dais = { 1018 { 1019 .dai_name = "sdw-mockup-aif1", 1020 .direction = {false, true}, 1021 .dai_type = SOF_SDW_DAI_TYPE_MIC, 1022 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 1023 .init = NULL, 1024 }, 1025 }, 1026 .dai_num = 1, 1027 }, 1028 }; 1029 1030 static inline int find_codec_info_part(const u64 adr) 1031 { 1032 unsigned int part_id, sdw_version; 1033 int i; 1034 1035 part_id = SDW_PART_ID(adr); 1036 sdw_version = SDW_VERSION(adr); 1037 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1038 /* 1039 * A codec info is for all sdw version with the part id if 1040 * version_id is not specified in the codec info. 1041 */ 1042 if (part_id == codec_info_list[i].part_id && 1043 (!codec_info_list[i].version_id || 1044 sdw_version == codec_info_list[i].version_id)) 1045 return i; 1046 1047 return -EINVAL; 1048 1049 } 1050 1051 static inline int find_codec_info_acpi(const u8 *acpi_id) 1052 { 1053 int i; 1054 1055 if (!acpi_id[0]) 1056 return -EINVAL; 1057 1058 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1059 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) 1060 return i; 1061 1062 return -EINVAL; 1063 } 1064 1065 /* 1066 * get BE dailink number and CPU DAI number based on sdw link adr. 1067 * Since some sdw slaves may be aggregated, the CPU DAI number 1068 * may be larger than the number of BE dailinks. 1069 */ 1070 static int get_dailink_info(struct device *dev, 1071 const struct snd_soc_acpi_link_adr *adr_link, 1072 int *sdw_be_num, int *sdw_cpu_dai_num, int *codecs_num) 1073 { 1074 bool group_visited[SDW_MAX_GROUPS]; 1075 bool no_aggregation; 1076 int i; 1077 int j; 1078 1079 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1080 *sdw_cpu_dai_num = 0; 1081 *sdw_be_num = 0; 1082 1083 if (!adr_link) 1084 return -EINVAL; 1085 1086 for (i = 0; i < SDW_MAX_GROUPS; i++) 1087 group_visited[i] = false; 1088 1089 for (; adr_link->num_adr; adr_link++) { 1090 const struct snd_soc_acpi_endpoint *endpoint; 1091 struct sof_sdw_codec_info *codec_info; 1092 int codec_index; 1093 int stream; 1094 u64 adr; 1095 1096 /* make sure the link mask has a single bit set */ 1097 if (!is_power_of_2(adr_link->mask)) 1098 return -EINVAL; 1099 1100 for (i = 0; i < adr_link->num_adr; i++) { 1101 adr = adr_link->adr_d[i].adr; 1102 codec_index = find_codec_info_part(adr); 1103 if (codec_index < 0) 1104 return codec_index; 1105 1106 codec_info = &codec_info_list[codec_index]; 1107 1108 *codecs_num += codec_info->dai_num; 1109 1110 if (!adr_link->adr_d[i].name_prefix) { 1111 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1112 adr_link->adr_d[i].adr); 1113 return -EINVAL; 1114 } 1115 1116 endpoint = adr_link->adr_d[i].endpoints; 1117 if (endpoint->aggregated && !endpoint->group_id) { 1118 dev_err(dev, "invalid group id on link %x\n", 1119 adr_link->mask); 1120 return -EINVAL; 1121 } 1122 1123 for (j = 0; j < codec_info->dai_num; j++) { 1124 /* count DAI number for playback and capture */ 1125 for_each_pcm_streams(stream) { 1126 if (!codec_info->dais[j].direction[stream]) 1127 continue; 1128 1129 (*sdw_cpu_dai_num)++; 1130 1131 /* count BE for each non-aggregated slave or group */ 1132 if (!endpoint->aggregated || no_aggregation || 1133 !group_visited[endpoint->group_id]) 1134 (*sdw_be_num)++; 1135 } 1136 } 1137 1138 if (endpoint->aggregated) 1139 group_visited[endpoint->group_id] = true; 1140 } 1141 } 1142 1143 return 0; 1144 } 1145 1146 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 1147 int be_id, char *name, int playback, int capture, 1148 struct snd_soc_dai_link_component *cpus, int cpus_num, 1149 struct snd_soc_dai_link_component *codecs, int codecs_num, 1150 int (*init)(struct snd_soc_pcm_runtime *rtd), 1151 const struct snd_soc_ops *ops) 1152 { 1153 dev_dbg(dev, "create dai link %s, id %d\n", name, be_id); 1154 dai_links->id = be_id; 1155 dai_links->name = name; 1156 dai_links->platforms = platform_component; 1157 dai_links->num_platforms = ARRAY_SIZE(platform_component); 1158 dai_links->no_pcm = 1; 1159 dai_links->cpus = cpus; 1160 dai_links->num_cpus = cpus_num; 1161 dai_links->codecs = codecs; 1162 dai_links->num_codecs = codecs_num; 1163 dai_links->dpcm_playback = playback; 1164 dai_links->dpcm_capture = capture; 1165 dai_links->init = init; 1166 dai_links->ops = ops; 1167 } 1168 1169 static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, 1170 unsigned int sdw_version, 1171 unsigned int mfg_id, 1172 unsigned int part_id, 1173 unsigned int class_id, 1174 int index_in_link) 1175 { 1176 int i; 1177 1178 for (i = 0; i < adr_link->num_adr; i++) { 1179 unsigned int sdw1_version, mfg1_id, part1_id, class1_id; 1180 u64 adr; 1181 1182 /* skip itself */ 1183 if (i == index_in_link) 1184 continue; 1185 1186 adr = adr_link->adr_d[i].adr; 1187 1188 sdw1_version = SDW_VERSION(adr); 1189 mfg1_id = SDW_MFG_ID(adr); 1190 part1_id = SDW_PART_ID(adr); 1191 class1_id = SDW_CLASS_ID(adr); 1192 1193 if (sdw_version == sdw1_version && 1194 mfg_id == mfg1_id && 1195 part_id == part1_id && 1196 class_id == class1_id) 1197 return false; 1198 } 1199 1200 return true; 1201 } 1202 1203 static int fill_sdw_codec_dlc(struct device *dev, 1204 const struct snd_soc_acpi_link_adr *adr_link, 1205 struct snd_soc_dai_link_component *codec, 1206 int adr_index, int dai_index) 1207 { 1208 unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; 1209 u64 adr = adr_link->adr_d[adr_index].adr; 1210 int codec_index; 1211 1212 codec_index = find_codec_info_part(adr); 1213 if (codec_index < 0) 1214 return codec_index; 1215 1216 sdw_version = SDW_VERSION(adr); 1217 link_id = SDW_DISCO_LINK_ID(adr); 1218 unique_id = SDW_UNIQUE_ID(adr); 1219 mfg_id = SDW_MFG_ID(adr); 1220 part_id = SDW_PART_ID(adr); 1221 class_id = SDW_CLASS_ID(adr); 1222 1223 if (codec_info_list[codec_index].codec_name) 1224 codec->name = devm_kstrdup(dev, 1225 codec_info_list[codec_index].codec_name, 1226 GFP_KERNEL); 1227 else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, 1228 class_id, adr_index)) 1229 codec->name = devm_kasprintf(dev, GFP_KERNEL, 1230 "sdw:0:%01x:%04x:%04x:%02x", link_id, 1231 mfg_id, part_id, class_id); 1232 else 1233 codec->name = devm_kasprintf(dev, GFP_KERNEL, 1234 "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id, 1235 mfg_id, part_id, class_id, unique_id); 1236 1237 if (!codec->name) 1238 return -ENOMEM; 1239 1240 codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name; 1241 1242 return 0; 1243 } 1244 1245 static int set_codec_init_func(struct snd_soc_card *card, 1246 const struct snd_soc_acpi_link_adr *adr_link, 1247 struct snd_soc_dai_link *dai_links, 1248 bool playback, int group_id, int adr_index, int dai_index) 1249 { 1250 int i = adr_index; 1251 1252 do { 1253 /* 1254 * Initialize the codec. If codec is part of an aggregated 1255 * group (group_id>0), initialize all codecs belonging to 1256 * same group. 1257 * The first link should start with adr_link->adr_d[adr_index] 1258 * because that is the device that we want to initialize and 1259 * we should end immediately if it is not aggregated (group_id=0) 1260 */ 1261 for ( ; i < adr_link->num_adr; i++) { 1262 int codec_index; 1263 1264 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1265 if (codec_index < 0) 1266 return codec_index; 1267 1268 /* The group_id is > 0 iff the codec is aggregated */ 1269 if (adr_link->adr_d[i].endpoints->group_id != group_id) 1270 continue; 1271 1272 if (codec_info_list[codec_index].dais[dai_index].init) 1273 codec_info_list[codec_index].dais[dai_index].init(card, 1274 adr_link, 1275 dai_links, 1276 &codec_info_list[codec_index], 1277 playback); 1278 if (!group_id) 1279 return 0; 1280 } 1281 1282 i = 0; 1283 adr_link++; 1284 } while (adr_link->mask); 1285 1286 return 0; 1287 } 1288 1289 /* 1290 * check endpoint status in slaves and gather link ID for all slaves in 1291 * the same group to generate different CPU DAI. Now only support 1292 * one sdw link with all slaves set with only single group id. 1293 * 1294 * one slave on one sdw link with aggregated = 0 1295 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 1296 * 1297 * two or more slaves on one sdw link with aggregated = 0 1298 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 1299 * 1300 * multiple links with multiple slaves with aggregated = 1 1301 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 1302 */ 1303 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 1304 struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 1305 int *codec_num, unsigned int *group_id, 1306 int adr_index) 1307 { 1308 bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1309 int i; 1310 1311 if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) { 1312 cpu_dai_id[0] = ffs(adr_link->mask) - 1; 1313 *cpu_dai_num = 1; 1314 *codec_num = 1; 1315 *group_id = 0; 1316 return 0; 1317 } 1318 1319 *codec_num = 0; 1320 *cpu_dai_num = 0; 1321 *group_id = adr_link->adr_d[adr_index].endpoints->group_id; 1322 1323 /* Count endpoints with the same group_id in the adr_link */ 1324 for (; adr_link && adr_link->num_adr; adr_link++) { 1325 unsigned int link_codecs = 0; 1326 1327 for (i = 0; i < adr_link->num_adr; i++) { 1328 if (adr_link->adr_d[i].endpoints->aggregated && 1329 adr_link->adr_d[i].endpoints->group_id == *group_id) 1330 link_codecs++; 1331 } 1332 1333 if (link_codecs) { 1334 *codec_num += link_codecs; 1335 1336 if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) { 1337 dev_err(dev, "cpu_dai_id array overflowed\n"); 1338 return -EINVAL; 1339 } 1340 1341 cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; 1342 } 1343 } 1344 1345 return 0; 1346 } 1347 1348 static void set_dailink_map(struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps, 1349 int codec_num, int cpu_num) 1350 { 1351 int step; 1352 int i; 1353 1354 step = codec_num / cpu_num; 1355 for (i = 0; i < codec_num; i++) 1356 sdw_codec_ch_maps[i].connected_cpu_id = i / step; 1357 } 1358 1359 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 1360 1361 static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, 1362 struct snd_soc_dai_link *dai_links, 1363 int sdw_be_num, int sdw_cpu_dai_num, 1364 struct snd_soc_dai_link_component *cpus, 1365 const struct snd_soc_acpi_link_adr *adr_link, 1366 int *cpu_id, struct snd_soc_codec_conf *codec_conf, 1367 int codec_count, int *be_id, 1368 int *codec_conf_index, 1369 bool *ignore_pch_dmic, 1370 bool append_dai_type, 1371 int adr_index, 1372 int dai_index) 1373 { 1374 struct device *dev = card->dev; 1375 const struct snd_soc_acpi_link_adr *adr_link_next; 1376 struct snd_soc_dai_link_component *codecs; 1377 struct sof_sdw_codec_info *codec_info; 1378 int cpu_dai_id[SDW_MAX_CPU_DAIS]; 1379 int cpu_dai_num, cpu_dai_index; 1380 unsigned int group_id; 1381 int codec_dlc_index = 0; 1382 int codec_index; 1383 int codec_num; 1384 int stream; 1385 int i = 0; 1386 int j, k; 1387 int ret; 1388 1389 ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 1390 &group_id, adr_index); 1391 if (ret) 1392 return ret; 1393 1394 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 1395 if (!codecs) 1396 return -ENOMEM; 1397 1398 /* generate codec name on different links in the same group */ 1399 j = adr_index; 1400 for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && 1401 i < cpu_dai_num; adr_link_next++) { 1402 /* skip the link excluded by this processed group */ 1403 if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) 1404 continue; 1405 1406 /* j reset after loop, adr_index only applies to first link */ 1407 for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) { 1408 const struct snd_soc_acpi_endpoint *endpoints; 1409 1410 endpoints = adr_link_next->adr_d[j].endpoints; 1411 1412 if (group_id && (!endpoints->aggregated || 1413 endpoints->group_id != group_id)) 1414 continue; 1415 1416 /* sanity check */ 1417 if (*codec_conf_index >= codec_count) { 1418 dev_err(dev, "codec_conf array overflowed\n"); 1419 return -EINVAL; 1420 } 1421 1422 ret = fill_sdw_codec_dlc(dev, adr_link_next, 1423 &codecs[codec_dlc_index], 1424 j, dai_index); 1425 if (ret) 1426 return ret; 1427 1428 codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index]; 1429 codec_conf[*codec_conf_index].name_prefix = 1430 adr_link_next->adr_d[j].name_prefix; 1431 1432 codec_dlc_index++; 1433 (*codec_conf_index)++; 1434 } 1435 j = 0; 1436 1437 /* check next link to create codec dai in the processed group */ 1438 i++; 1439 } 1440 1441 /* find codec info to create BE DAI */ 1442 codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr); 1443 if (codec_index < 0) 1444 return codec_index; 1445 codec_info = &codec_info_list[codec_index]; 1446 1447 if (codec_info->ignore_pch_dmic) 1448 *ignore_pch_dmic = true; 1449 1450 cpu_dai_index = *cpu_id; 1451 for_each_pcm_streams(stream) { 1452 struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps; 1453 char *name, *cpu_name; 1454 int playback, capture; 1455 static const char * const sdw_stream_name[] = { 1456 "SDW%d-Playback", 1457 "SDW%d-Capture", 1458 "SDW%d-Playback-%s", 1459 "SDW%d-Capture-%s", 1460 }; 1461 1462 if (!codec_info->dais[dai_index].direction[stream]) 1463 continue; 1464 1465 *be_id = codec_info->dais[dai_index].dailink[stream]; 1466 if (*be_id < 0) { 1467 dev_err(dev, "Invalid dailink id %d\n", *be_id); 1468 return -EINVAL; 1469 } 1470 1471 sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, 1472 sizeof(*sdw_codec_ch_maps), GFP_KERNEL); 1473 if (!sdw_codec_ch_maps) 1474 return -ENOMEM; 1475 1476 /* create stream name according to first link id */ 1477 if (append_dai_type) { 1478 name = devm_kasprintf(dev, GFP_KERNEL, 1479 sdw_stream_name[stream + 2], cpu_dai_id[0], 1480 type_strings[codec_info->dais[dai_index].dai_type]); 1481 } else { 1482 name = devm_kasprintf(dev, GFP_KERNEL, 1483 sdw_stream_name[stream], cpu_dai_id[0]); 1484 } 1485 if (!name) 1486 return -ENOMEM; 1487 1488 /* 1489 * generate CPU DAI name base on the sdw link ID and 1490 * PIN ID with offset of 2 according to sdw dai driver. 1491 */ 1492 for (k = 0; k < cpu_dai_num; k++) { 1493 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1494 "SDW%d Pin%d", cpu_dai_id[k], 1495 sdw_pin_index[cpu_dai_id[k]]++); 1496 if (!cpu_name) 1497 return -ENOMEM; 1498 1499 if (cpu_dai_index >= sdw_cpu_dai_num) { 1500 dev_err(dev, "invalid cpu dai index %d\n", 1501 cpu_dai_index); 1502 return -EINVAL; 1503 } 1504 1505 cpus[cpu_dai_index++].dai_name = cpu_name; 1506 } 1507 1508 /* 1509 * We create sdw dai links at first stage, so link index should 1510 * not be larger than sdw_be_num 1511 */ 1512 if (*link_index >= sdw_be_num) { 1513 dev_err(dev, "invalid dai link index %d\n", *link_index); 1514 return -EINVAL; 1515 } 1516 1517 if (*cpu_id >= sdw_cpu_dai_num) { 1518 dev_err(dev, "invalid cpu dai index %d\n", *cpu_id); 1519 return -EINVAL; 1520 } 1521 1522 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 1523 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 1524 init_dai_link(dev, dai_links + *link_index, (*be_id)++, name, 1525 playback, capture, 1526 cpus + *cpu_id, cpu_dai_num, 1527 codecs, codec_num, 1528 NULL, &sdw_ops); 1529 1530 /* 1531 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 1532 * based on wait_for_completion(), tag them as 'nonatomic'. 1533 */ 1534 dai_links[*link_index].nonatomic = true; 1535 1536 set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num); 1537 dai_links[*link_index].codec_ch_maps = sdw_codec_ch_maps; 1538 ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, 1539 playback, group_id, adr_index, dai_index); 1540 if (ret < 0) { 1541 dev_err(dev, "failed to init codec %d\n", codec_index); 1542 return ret; 1543 } 1544 1545 *cpu_id += cpu_dai_num; 1546 } 1547 1548 return 0; 1549 } 1550 1551 #define IDISP_CODEC_MASK 0x4 1552 1553 static int sof_card_dai_links_create(struct snd_soc_card *card) 1554 { 1555 struct device *dev = card->dev; 1556 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 1557 int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, hdmi_num = 0, bt_num = 0; 1558 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1559 struct snd_soc_dai_link_component *idisp_components; 1560 struct snd_soc_dai_link_component *ssp_components; 1561 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1562 const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; 1563 bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); 1564 struct snd_soc_dai_link_component *cpus; 1565 struct snd_soc_codec_conf *codec_conf; 1566 bool append_dai_type = false; 1567 bool ignore_pch_dmic = false; 1568 int codec_conf_num = 0; 1569 int codec_conf_index = 0; 1570 bool group_generated[SDW_MAX_GROUPS] = { }; 1571 int ssp_codec_index, ssp_mask; 1572 struct snd_soc_dai_link *dai_links; 1573 int num_links, link_index = 0; 1574 char *name, *cpu_name; 1575 int total_cpu_dai_num; 1576 int sdw_cpu_dai_num; 1577 int i, j, be_id = 0; 1578 int codec_index; 1579 int cpu_id = 0; 1580 int ret; 1581 1582 ret = get_dailink_info(dev, adr_link, &sdw_be_num, &sdw_cpu_dai_num, 1583 &codec_conf_num); 1584 if (ret < 0) { 1585 dev_err(dev, "failed to get sdw link info %d\n", ret); 1586 return ret; 1587 } 1588 1589 /* 1590 * on generic tgl platform, I2S or sdw mode is supported 1591 * based on board rework. A ACPI device is registered in 1592 * system only when I2S mode is supported, not sdw mode. 1593 * Here check ACPI ID to confirm I2S is supported. 1594 */ 1595 ssp_codec_index = find_codec_info_acpi(mach->id); 1596 if (ssp_codec_index >= 0) { 1597 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1598 ssp_num = hweight_long(ssp_mask); 1599 } 1600 1601 if (mach_params->codec_mask & IDISP_CODEC_MASK) { 1602 ctx->idisp_codec = true; 1603 1604 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1605 hdmi_num = SOF_TGL_HDMI_COUNT; 1606 else 1607 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1608 } 1609 1610 /* enable dmic01 & dmic16k */ 1611 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) 1612 dmic_num = 2; 1613 1614 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1615 bt_num = 1; 1616 1617 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", 1618 sdw_be_num, ssp_num, dmic_num, hdmi_num, bt_num); 1619 1620 /* allocate BE dailinks */ 1621 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; 1622 dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 1623 if (!dai_links) 1624 return -ENOMEM; 1625 1626 /* allocated CPU DAIs */ 1627 total_cpu_dai_num = sdw_cpu_dai_num + ssp_num + dmic_num + hdmi_num + bt_num; 1628 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus), GFP_KERNEL); 1629 if (!cpus) 1630 return -ENOMEM; 1631 1632 /* allocate codec conf, will be populated when dailinks are created */ 1633 codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), 1634 GFP_KERNEL); 1635 if (!codec_conf) 1636 return -ENOMEM; 1637 1638 /* SDW */ 1639 if (!sdw_be_num) 1640 goto SSP; 1641 1642 for (i = 0; i < SDW_MAX_LINKS; i++) 1643 sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; 1644 1645 for (; adr_link->num_adr; adr_link++) { 1646 /* 1647 * If there are two or more different devices on the same sdw link, we have to 1648 * append the codec type to the dai link name to prevent duplicated dai link name. 1649 * The same type devices on the same sdw link will be in the same 1650 * snd_soc_acpi_adr_device array. They won't be described in different adr_links. 1651 */ 1652 for (i = 0; i < adr_link->num_adr; i++) { 1653 /* find codec info to get dai_num */ 1654 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1655 if (codec_index < 0) 1656 return codec_index; 1657 if (codec_info_list[codec_index].dai_num > 1) { 1658 append_dai_type = true; 1659 goto out; 1660 } 1661 for (j = 0; j < i; j++) { 1662 if ((SDW_PART_ID(adr_link->adr_d[i].adr) != 1663 SDW_PART_ID(adr_link->adr_d[j].adr)) || 1664 (SDW_MFG_ID(adr_link->adr_d[i].adr) != 1665 SDW_MFG_ID(adr_link->adr_d[j].adr))) { 1666 append_dai_type = true; 1667 goto out; 1668 } 1669 } 1670 } 1671 } 1672 out: 1673 1674 /* generate DAI links by each sdw link */ 1675 for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { 1676 for (i = 0; i < adr_link->num_adr; i++) { 1677 const struct snd_soc_acpi_endpoint *endpoint; 1678 1679 endpoint = adr_link->adr_d[i].endpoints; 1680 1681 /* this group has been generated */ 1682 if (endpoint->aggregated && 1683 group_generated[endpoint->group_id]) 1684 continue; 1685 1686 /* find codec info to get dai_num */ 1687 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1688 if (codec_index < 0) 1689 return codec_index; 1690 1691 for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) { 1692 ret = create_sdw_dailink(card, &link_index, dai_links, 1693 sdw_be_num, sdw_cpu_dai_num, cpus, 1694 adr_link, &cpu_id, 1695 codec_conf, codec_conf_num, 1696 &be_id, &codec_conf_index, 1697 &ignore_pch_dmic, append_dai_type, i, j); 1698 if (ret < 0) { 1699 dev_err(dev, "failed to create dai link %d\n", link_index); 1700 return ret; 1701 } 1702 } 1703 1704 if (aggregation && endpoint->aggregated) 1705 group_generated[endpoint->group_id] = true; 1706 } 1707 } 1708 1709 SSP: 1710 /* SSP */ 1711 if (!ssp_num) 1712 goto DMIC; 1713 1714 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1715 struct sof_sdw_codec_info *info; 1716 int playback, capture; 1717 char *codec_name; 1718 1719 if (!(ssp_mask & 0x1)) 1720 continue; 1721 1722 name = devm_kasprintf(dev, GFP_KERNEL, 1723 "SSP%d-Codec", i); 1724 if (!name) 1725 return -ENOMEM; 1726 1727 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1728 if (!cpu_name) 1729 return -ENOMEM; 1730 1731 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1732 GFP_KERNEL); 1733 if (!ssp_components) 1734 return -ENOMEM; 1735 1736 info = &codec_info_list[ssp_codec_index]; 1737 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1738 info->acpi_id, j++); 1739 if (!codec_name) 1740 return -ENOMEM; 1741 1742 ssp_components->name = codec_name; 1743 /* TODO: support multi codec dai on SSP when it is needed */ 1744 ssp_components->dai_name = info->dais[0].dai_name; 1745 cpus[cpu_id].dai_name = cpu_name; 1746 1747 playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 1748 capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 1749 init_dai_link(dev, dai_links + link_index, be_id, name, 1750 playback, capture, 1751 cpus + cpu_id, 1, 1752 ssp_components, 1, 1753 NULL, info->ops); 1754 1755 ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0); 1756 if (ret < 0) 1757 return ret; 1758 1759 INC_ID(be_id, cpu_id, link_index); 1760 } 1761 1762 DMIC: 1763 /* dmic */ 1764 if (dmic_num > 0) { 1765 if (ignore_pch_dmic) { 1766 dev_warn(dev, "Ignoring PCH DMIC\n"); 1767 goto HDMI; 1768 } 1769 cpus[cpu_id].dai_name = "DMIC01 Pin"; 1770 init_dai_link(dev, dai_links + link_index, be_id, "dmic01", 1771 0, 1, // DMIC only supports capture 1772 cpus + cpu_id, 1, 1773 dmic_component, 1, 1774 sof_sdw_dmic_init, NULL); 1775 INC_ID(be_id, cpu_id, link_index); 1776 1777 cpus[cpu_id].dai_name = "DMIC16k Pin"; 1778 init_dai_link(dev, dai_links + link_index, be_id, "dmic16k", 1779 0, 1, // DMIC only supports capture 1780 cpus + cpu_id, 1, 1781 dmic_component, 1, 1782 /* don't call sof_sdw_dmic_init() twice */ 1783 NULL, NULL); 1784 INC_ID(be_id, cpu_id, link_index); 1785 } 1786 1787 HDMI: 1788 /* HDMI */ 1789 if (hdmi_num > 0) { 1790 idisp_components = devm_kcalloc(dev, hdmi_num, 1791 sizeof(*idisp_components), 1792 GFP_KERNEL); 1793 if (!idisp_components) 1794 return -ENOMEM; 1795 } 1796 1797 for (i = 0; i < hdmi_num; i++) { 1798 name = devm_kasprintf(dev, GFP_KERNEL, 1799 "iDisp%d", i + 1); 1800 if (!name) 1801 return -ENOMEM; 1802 1803 if (ctx->idisp_codec) { 1804 idisp_components[i].name = "ehdaudio0D2"; 1805 idisp_components[i].dai_name = devm_kasprintf(dev, 1806 GFP_KERNEL, 1807 "intel-hdmi-hifi%d", 1808 i + 1); 1809 if (!idisp_components[i].dai_name) 1810 return -ENOMEM; 1811 } else { 1812 idisp_components[i] = asoc_dummy_dlc; 1813 } 1814 1815 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1816 "iDisp%d Pin", i + 1); 1817 if (!cpu_name) 1818 return -ENOMEM; 1819 1820 cpus[cpu_id].dai_name = cpu_name; 1821 init_dai_link(dev, dai_links + link_index, be_id, name, 1822 1, 0, // HDMI only supports playback 1823 cpus + cpu_id, 1, 1824 idisp_components + i, 1, 1825 sof_sdw_hdmi_init, NULL); 1826 INC_ID(be_id, cpu_id, link_index); 1827 } 1828 1829 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1830 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1831 SOF_BT_OFFLOAD_SSP_SHIFT; 1832 1833 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1834 if (!name) 1835 return -ENOMEM; 1836 1837 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1838 if (!cpu_name) 1839 return -ENOMEM; 1840 1841 cpus[cpu_id].dai_name = cpu_name; 1842 init_dai_link(dev, dai_links + link_index, be_id, name, 1, 1, 1843 cpus + cpu_id, 1, &asoc_dummy_dlc, 1, NULL, NULL); 1844 } 1845 1846 card->dai_link = dai_links; 1847 card->num_links = num_links; 1848 1849 card->codec_conf = codec_conf; 1850 card->num_configs = codec_conf_num; 1851 1852 return 0; 1853 } 1854 1855 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1856 { 1857 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1858 int ret = 0; 1859 int i; 1860 1861 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1862 if (codec_info_list[i].codec_card_late_probe) { 1863 ret = codec_info_list[i].codec_card_late_probe(card); 1864 1865 if (ret < 0) 1866 return ret; 1867 } 1868 } 1869 1870 if (ctx->idisp_codec) 1871 ret = sof_sdw_hdmi_card_late_probe(card); 1872 1873 return ret; 1874 } 1875 1876 /* SoC card */ 1877 static const char sdw_card_long_name[] = "Intel Soundwire SOF"; 1878 1879 static struct snd_soc_card card_sof_sdw = { 1880 .name = "soundwire", 1881 .owner = THIS_MODULE, 1882 .late_probe = sof_sdw_card_late_probe, 1883 }; 1884 1885 /* helper to get the link that the codec DAI is used */ 1886 static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card, 1887 const char *dai_name) 1888 { 1889 struct snd_soc_dai_link *dai_link; 1890 int i; 1891 int j; 1892 1893 for_each_card_prelinks(card, i, dai_link) { 1894 for (j = 0; j < dai_link->num_codecs; j++) { 1895 /* Check each codec in a link */ 1896 if (!strcmp(dai_link->codecs[j].dai_name, dai_name)) 1897 return dai_link; 1898 } 1899 } 1900 return NULL; 1901 } 1902 1903 static void mc_dailink_exit_loop(struct snd_soc_card *card) 1904 { 1905 struct snd_soc_dai_link *dai_link; 1906 int ret; 1907 int i, j; 1908 1909 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1910 for (j = 0; j < codec_info_list[i].dai_num; j++) { 1911 /* Check each dai in codec_info_lis to see if it is used in the link */ 1912 if (!codec_info_list[i].dais[j].exit) 1913 continue; 1914 /* 1915 * We don't need to call .exit function if there is no matched 1916 * dai link found. 1917 */ 1918 dai_link = mc_find_codec_dai_used(card, 1919 codec_info_list[i].dais[j].dai_name); 1920 if (dai_link) { 1921 /* Do the .exit function if the codec dai is used in the link */ 1922 ret = codec_info_list[i].dais[j].exit(card, dai_link); 1923 if (ret) 1924 dev_warn(card->dev, 1925 "codec exit failed %d\n", 1926 ret); 1927 break; 1928 } 1929 } 1930 } 1931 } 1932 1933 static int mc_probe(struct platform_device *pdev) 1934 { 1935 struct snd_soc_card *card = &card_sof_sdw; 1936 struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); 1937 struct mc_private *ctx; 1938 int amp_num = 0, i; 1939 int ret; 1940 1941 card->dev = &pdev->dev; 1942 1943 dev_dbg(card->dev, "Entry\n"); 1944 1945 ctx = devm_kzalloc(card->dev, sizeof(*ctx), GFP_KERNEL); 1946 if (!ctx) 1947 return -ENOMEM; 1948 1949 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 1950 1951 snd_soc_card_set_drvdata(card, ctx); 1952 1953 dmi_check_system(sof_sdw_quirk_table); 1954 1955 if (quirk_override != -1) { 1956 dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", 1957 sof_sdw_quirk, quirk_override); 1958 sof_sdw_quirk = quirk_override; 1959 } 1960 1961 log_quirks(card->dev); 1962 1963 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1964 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1965 codec_info_list[i].amp_num = 0; 1966 1967 if (mach->mach_params.subsystem_id_set) { 1968 snd_soc_card_set_pci_ssid(card, 1969 mach->mach_params.subsystem_vendor, 1970 mach->mach_params.subsystem_device); 1971 } 1972 1973 ret = sof_card_dai_links_create(card); 1974 if (ret < 0) 1975 return ret; 1976 1977 /* 1978 * the default amp_num is zero for each codec and 1979 * amp_num will only be increased for active amp 1980 * codecs on used platform 1981 */ 1982 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1983 amp_num += codec_info_list[i].amp_num; 1984 1985 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1986 "cfg-spk:%d cfg-amp:%d", 1987 (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 1988 ? 4 : 2, amp_num); 1989 if (!card->components) 1990 return -ENOMEM; 1991 1992 if (mach->mach_params.dmic_num) { 1993 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1994 "%s mic:dmic cfg-mics:%d", 1995 card->components, 1996 mach->mach_params.dmic_num); 1997 if (!card->components) 1998 return -ENOMEM; 1999 } 2000 2001 card->long_name = sdw_card_long_name; 2002 2003 /* Register the card */ 2004 ret = devm_snd_soc_register_card(card->dev, card); 2005 if (ret) { 2006 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); 2007 mc_dailink_exit_loop(card); 2008 return ret; 2009 } 2010 2011 platform_set_drvdata(pdev, card); 2012 2013 return ret; 2014 } 2015 2016 static void mc_remove(struct platform_device *pdev) 2017 { 2018 struct snd_soc_card *card = platform_get_drvdata(pdev); 2019 2020 mc_dailink_exit_loop(card); 2021 } 2022 2023 static const struct platform_device_id mc_id_table[] = { 2024 { "sof_sdw", }, 2025 {} 2026 }; 2027 MODULE_DEVICE_TABLE(platform, mc_id_table); 2028 2029 static struct platform_driver sof_sdw_driver = { 2030 .driver = { 2031 .name = "sof_sdw", 2032 .pm = &snd_soc_pm_ops, 2033 }, 2034 .probe = mc_probe, 2035 .remove_new = mc_remove, 2036 .id_table = mc_id_table, 2037 }; 2038 2039 module_platform_driver(sof_sdw_driver); 2040 2041 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 2042 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 2043 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 2044 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 2045 MODULE_LICENSE("GPL v2"); 2046 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 2047 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 2048