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/acpi.h> 9 #include <linux/bitmap.h> 10 #include <linux/device.h> 11 #include <linux/dmi.h> 12 #include <linux/module.h> 13 #include <linux/soundwire/sdw.h> 14 #include <linux/soundwire/sdw_type.h> 15 #include <linux/soundwire/sdw_intel.h> 16 #include <sound/soc-acpi.h> 17 #include "sof_sdw_common.h" 18 #include "../../codecs/rt711.h" 19 20 static unsigned long sof_sdw_quirk = RT711_JD1; 21 static int quirk_override = -1; 22 module_param_named(quirk, quirk_override, int, 0444); 23 MODULE_PARM_DESC(quirk, "Board-specific quirk override"); 24 25 static void log_quirks(struct device *dev) 26 { 27 if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk)) 28 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", 29 SOC_SDW_JACK_JDSRC(sof_sdw_quirk)); 30 if (sof_sdw_quirk & SOC_SDW_FOUR_SPK) 31 dev_err(dev, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\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 & SOC_SDW_PCH_DMIC) 35 dev_dbg(dev, "quirk SOC_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 & SOC_SDW_NO_AGGREGATION) 40 dev_err(dev, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n"); 41 if (sof_sdw_quirk & SOC_SDW_CODEC_SPKR) 42 dev_dbg(dev, "quirk SOC_SDW_CODEC_SPKR enabled\n"); 43 if (sof_sdw_quirk & SOC_SDW_SIDECAR_AMPS) 44 dev_dbg(dev, "quirk SOC_SDW_SIDECAR_AMPS enabled\n"); 45 } 46 47 static int sof_sdw_quirk_cb(const struct dmi_system_id *id) 48 { 49 sof_sdw_quirk = (unsigned long)id->driver_data; 50 return 1; 51 } 52 53 static const struct dmi_system_id sof_sdw_quirk_table[] = { 54 /* CometLake devices */ 55 { 56 .callback = sof_sdw_quirk_cb, 57 .matches = { 58 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 59 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), 60 }, 61 .driver_data = (void *)SOC_SDW_PCH_DMIC, 62 }, 63 { 64 .callback = sof_sdw_quirk_cb, 65 .matches = { 66 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 67 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 68 }, 69 .driver_data = (void *)RT711_JD2, 70 }, 71 { 72 /* early version of SKU 09C6 */ 73 .callback = sof_sdw_quirk_cb, 74 .matches = { 75 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 76 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 77 }, 78 .driver_data = (void *)RT711_JD2, 79 }, 80 { 81 .callback = sof_sdw_quirk_cb, 82 .matches = { 83 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 84 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 85 }, 86 .driver_data = (void *)(RT711_JD2), 87 }, 88 { 89 .callback = sof_sdw_quirk_cb, 90 .matches = { 91 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 92 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 93 }, 94 .driver_data = (void *)(RT711_JD2), 95 }, 96 /* IceLake devices */ 97 { 98 .callback = sof_sdw_quirk_cb, 99 .matches = { 100 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 101 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), 102 }, 103 .driver_data = (void *)SOC_SDW_PCH_DMIC, 104 }, 105 /* TigerLake devices */ 106 { 107 .callback = sof_sdw_quirk_cb, 108 .matches = { 109 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 110 DMI_MATCH(DMI_PRODUCT_NAME, 111 "Tiger Lake Client Platform"), 112 }, 113 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 114 RT711_JD1 | 115 SOC_SDW_PCH_DMIC | 116 SOF_SSP_PORT(SOF_I2S_SSP2)), 117 }, 118 { 119 .callback = sof_sdw_quirk_cb, 120 .matches = { 121 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 122 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") 123 }, 124 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 125 RT711_JD2), 126 }, 127 { 128 /* another SKU of Dell Latitude 9520 */ 129 .callback = sof_sdw_quirk_cb, 130 .matches = { 131 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 132 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F") 133 }, 134 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 135 RT711_JD2), 136 }, 137 { 138 /* Dell XPS 9710 */ 139 .callback = sof_sdw_quirk_cb, 140 .matches = { 141 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 142 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") 143 }, 144 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 145 RT711_JD2), 146 }, 147 { 148 .callback = sof_sdw_quirk_cb, 149 .matches = { 150 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 151 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") 152 }, 153 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 154 RT711_JD2), 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 SOC_SDW_PCH_DMIC | 164 SOF_BT_OFFLOAD_SSP(2) | 165 SOF_SSP_BT_OFFLOAD_PRESENT), 166 }, 167 { 168 .callback = sof_sdw_quirk_cb, 169 .matches = { 170 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 171 DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), 172 }, 173 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 174 SOC_SDW_PCH_DMIC), 175 }, 176 { 177 /* 178 * this entry covers multiple HP SKUs. The family name 179 * does not seem robust enough, so we use a partial 180 * match that ignores the product name suffix 181 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) 182 */ 183 .callback = sof_sdw_quirk_cb, 184 .matches = { 185 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 186 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"), 187 }, 188 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 189 SOC_SDW_PCH_DMIC | 190 RT711_JD1), 191 }, 192 { 193 /* 194 * this entry covers HP Spectre x360 where the DMI information 195 * changed somehow 196 */ 197 .callback = sof_sdw_quirk_cb, 198 .matches = { 199 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 200 DMI_MATCH(DMI_BOARD_NAME, "8709"), 201 }, 202 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 203 SOC_SDW_PCH_DMIC | 204 RT711_JD1), 205 }, 206 { 207 /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */ 208 .callback = sof_sdw_quirk_cb, 209 .matches = { 210 DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 211 DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"), 212 }, 213 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 214 SOC_SDW_PCH_DMIC | 215 RT711_JD1), 216 }, 217 { 218 /* NUC15 LAPBC710 skews */ 219 .callback = sof_sdw_quirk_cb, 220 .matches = { 221 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 222 DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"), 223 }, 224 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 225 SOC_SDW_PCH_DMIC | 226 RT711_JD1), 227 }, 228 { 229 /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ 230 .callback = sof_sdw_quirk_cb, 231 .matches = { 232 DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 233 DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"), 234 }, 235 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 236 SOC_SDW_PCH_DMIC | 237 RT711_JD2_100K), 238 }, 239 { 240 /* NUC15 LAPRC710 skews */ 241 .callback = sof_sdw_quirk_cb, 242 .matches = { 243 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 244 DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"), 245 }, 246 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 247 SOC_SDW_PCH_DMIC | 248 RT711_JD2_100K), 249 }, 250 /* TigerLake-SDCA devices */ 251 { 252 .callback = sof_sdw_quirk_cb, 253 .matches = { 254 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 255 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") 256 }, 257 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 258 RT711_JD2), 259 }, 260 { 261 .callback = sof_sdw_quirk_cb, 262 .matches = { 263 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 264 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45") 265 }, 266 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 267 RT711_JD2), 268 }, 269 /* AlderLake devices */ 270 { 271 .callback = sof_sdw_quirk_cb, 272 .matches = { 273 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 274 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), 275 }, 276 .driver_data = (void *)(RT711_JD2_100K | 277 SOF_SDW_TGL_HDMI | 278 SOF_BT_OFFLOAD_SSP(2) | 279 SOF_SSP_BT_OFFLOAD_PRESENT), 280 }, 281 { 282 .callback = sof_sdw_quirk_cb, 283 .matches = { 284 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 285 DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"), 286 }, 287 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 288 RT711_JD2_100K), 289 }, 290 { 291 .callback = sof_sdw_quirk_cb, 292 .matches = { 293 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 294 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), 295 }, 296 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 297 SOC_SDW_PCH_DMIC | 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 }, 310 { 311 .callback = sof_sdw_quirk_cb, 312 .matches = { 313 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 314 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"), 315 }, 316 /* No Jack */ 317 .driver_data = (void *)(SOF_SDW_TGL_HDMI), 318 }, 319 { 320 .callback = sof_sdw_quirk_cb, 321 .matches = { 322 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 323 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") 324 }, 325 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 326 RT711_JD2), 327 }, 328 { 329 .callback = sof_sdw_quirk_cb, 330 .matches = { 331 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 332 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") 333 }, 334 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 335 RT711_JD2), 336 }, 337 { 338 .callback = sof_sdw_quirk_cb, 339 .matches = { 340 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 341 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") 342 }, 343 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 344 RT711_JD2), 345 }, 346 { 347 .callback = sof_sdw_quirk_cb, 348 .matches = { 349 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 350 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") 351 }, 352 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 353 RT711_JD2), 354 }, 355 { 356 .callback = sof_sdw_quirk_cb, 357 .matches = { 358 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 359 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11") 360 }, 361 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 362 RT711_JD2), 363 }, 364 { 365 .callback = sof_sdw_quirk_cb, 366 .matches = { 367 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 368 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12") 369 }, 370 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 371 RT711_JD2), 372 }, 373 { 374 .callback = sof_sdw_quirk_cb, 375 .matches = { 376 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 377 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"), 378 }, 379 /* No Jack */ 380 .driver_data = (void *)SOF_SDW_TGL_HDMI, 381 }, 382 { 383 .callback = sof_sdw_quirk_cb, 384 .matches = { 385 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 386 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"), 387 }, 388 /* No Jack */ 389 .driver_data = (void *)SOF_SDW_TGL_HDMI, 390 }, 391 392 { 393 .callback = sof_sdw_quirk_cb, 394 .matches = { 395 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 396 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"), 397 }, 398 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 399 RT711_JD2), 400 }, 401 { 402 .callback = sof_sdw_quirk_cb, 403 .matches = { 404 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 405 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"), 406 }, 407 /* No Jack */ 408 .driver_data = (void *)SOF_SDW_TGL_HDMI, 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, "0B8C"), 415 }, 416 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 417 RT711_JD2), 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"), 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 }, 438 { 439 .callback = sof_sdw_quirk_cb, 440 .matches = { 441 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 442 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F") 443 }, 444 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 445 RT711_JD2), 446 }, 447 { 448 .callback = sof_sdw_quirk_cb, 449 .matches = { 450 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 451 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"), 452 }, 453 /* No Jack */ 454 .driver_data = (void *)(SOF_SDW_TGL_HDMI), 455 }, 456 { 457 .callback = sof_sdw_quirk_cb, 458 .matches = { 459 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 460 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11") 461 }, 462 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 463 RT711_JD2), 464 }, 465 { 466 .callback = sof_sdw_quirk_cb, 467 .matches = { 468 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 469 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40") 470 }, 471 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 472 RT711_JD2), 473 }, 474 { 475 .callback = sof_sdw_quirk_cb, 476 .matches = { 477 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 478 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F") 479 }, 480 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 481 RT711_JD2), 482 }, 483 { 484 .callback = sof_sdw_quirk_cb, 485 .matches = { 486 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 487 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF9") 488 }, 489 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 490 }, 491 /* MeteorLake devices */ 492 { 493 .callback = sof_sdw_quirk_cb, 494 .matches = { 495 DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"), 496 }, 497 .driver_data = (void *)(RT711_JD1), 498 }, 499 { 500 .callback = sof_sdw_quirk_cb, 501 .matches = { 502 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 503 DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"), 504 }, 505 .driver_data = (void *)(RT711_JD2_100K), 506 }, 507 { 508 .callback = sof_sdw_quirk_cb, 509 .matches = { 510 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 511 DMI_MATCH(DMI_PRODUCT_NAME, "Rex"), 512 }, 513 .driver_data = (void *)(SOC_SDW_PCH_DMIC | 514 SOF_BT_OFFLOAD_SSP(1) | 515 SOF_SSP_BT_OFFLOAD_PRESENT), 516 }, 517 { 518 .callback = sof_sdw_quirk_cb, 519 .matches = { 520 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 521 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"), 522 }, 523 .driver_data = (void *)(RT711_JD2), 524 }, 525 526 /* LunarLake devices */ 527 { 528 .callback = sof_sdw_quirk_cb, 529 .matches = { 530 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 531 DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"), 532 }, 533 .driver_data = (void *)(RT711_JD2), 534 }, 535 { 536 .callback = sof_sdw_quirk_cb, 537 .matches = { 538 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 539 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3") 540 }, 541 .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS), 542 }, 543 { 544 .callback = sof_sdw_quirk_cb, 545 .matches = { 546 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 547 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4") 548 }, 549 .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS), 550 }, 551 { 552 .callback = sof_sdw_quirk_cb, 553 .matches = { 554 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 555 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDB") 556 }, 557 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 558 }, 559 { 560 .callback = sof_sdw_quirk_cb, 561 .matches = { 562 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 563 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDC") 564 }, 565 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 566 }, 567 { 568 .callback = sof_sdw_quirk_cb, 569 .matches = { 570 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 571 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDD") 572 }, 573 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 574 }, 575 { 576 .callback = sof_sdw_quirk_cb, 577 .matches = { 578 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 579 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8") 580 }, 581 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 582 }, 583 584 /* ArrowLake devices */ 585 { 586 .callback = sof_sdw_quirk_cb, 587 .matches = { 588 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 589 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE8") 590 }, 591 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 592 }, 593 { 594 .callback = sof_sdw_quirk_cb, 595 .matches = { 596 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 597 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7") 598 }, 599 .driver_data = (void *)(SOC_SDW_CODEC_SPKR), 600 }, 601 {} 602 }; 603 604 static struct snd_soc_dai_link_component platform_component[] = { 605 { 606 /* name might be overridden during probe */ 607 .name = "0000:00:1f.3" 608 } 609 }; 610 611 static const struct snd_soc_ops sdw_ops = { 612 .startup = asoc_sdw_startup, 613 .prepare = asoc_sdw_prepare, 614 .trigger = asoc_sdw_trigger, 615 .hw_params = asoc_sdw_hw_params, 616 .hw_free = asoc_sdw_hw_free, 617 .shutdown = asoc_sdw_shutdown, 618 }; 619 620 struct sof_sdw_endpoint { 621 struct list_head list; 622 623 u32 link_mask; 624 const char *codec_name; 625 const char *name_prefix; 626 bool include_sidecar; 627 628 struct asoc_sdw_codec_info *codec_info; 629 const struct asoc_sdw_dai_info *dai_info; 630 }; 631 632 struct sof_sdw_dailink { 633 bool initialised; 634 635 u8 group_id; 636 u32 link_mask[SNDRV_PCM_STREAM_LAST + 1]; 637 int num_devs[SNDRV_PCM_STREAM_LAST + 1]; 638 struct list_head endpoints; 639 }; 640 641 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 642 643 static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends) 644 { 645 struct device *dev = card->dev; 646 struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); 647 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 648 const struct snd_soc_acpi_link_adr *adr_link; 649 int i; 650 651 for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { 652 *num_devs += adr_link->num_adr; 653 654 for (i = 0; i < adr_link->num_adr; i++) 655 *num_ends += adr_link->adr_d[i].num_endpoints; 656 } 657 658 dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends); 659 660 return 0; 661 } 662 663 static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks, 664 const struct snd_soc_acpi_endpoint *new) 665 { 666 while (dailinks->initialised) { 667 if (new->aggregated && dailinks->group_id == new->group_id) 668 return dailinks; 669 670 dailinks++; 671 } 672 673 INIT_LIST_HEAD(&dailinks->endpoints); 674 dailinks->group_id = new->group_id; 675 dailinks->initialised = true; 676 677 return dailinks; 678 } 679 680 static int parse_sdw_endpoints(struct snd_soc_card *card, 681 struct sof_sdw_dailink *sof_dais, 682 struct sof_sdw_endpoint *sof_ends, 683 int *num_devs) 684 { 685 struct device *dev = card->dev; 686 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 687 struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); 688 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 689 const struct snd_soc_acpi_link_adr *adr_link; 690 struct sof_sdw_endpoint *sof_end = sof_ends; 691 int num_dais = 0; 692 int i, j; 693 int ret; 694 695 for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { 696 int num_link_dailinks = 0; 697 698 if (!is_power_of_2(adr_link->mask)) { 699 dev_err(dev, "link with multiple mask bits: 0x%x\n", 700 adr_link->mask); 701 return -EINVAL; 702 } 703 704 for (i = 0; i < adr_link->num_adr; i++) { 705 const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i]; 706 struct asoc_sdw_codec_info *codec_info; 707 const char *codec_name; 708 709 if (!adr_dev->name_prefix) { 710 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 711 adr_dev->adr); 712 return -EINVAL; 713 } 714 715 codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr); 716 if (!codec_info) 717 return -EINVAL; 718 719 ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic; 720 721 codec_name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, i); 722 if (!codec_name) 723 return -ENOMEM; 724 725 dev_dbg(dev, "Adding prefix %s for %s\n", 726 adr_dev->name_prefix, codec_name); 727 728 sof_end->name_prefix = adr_dev->name_prefix; 729 730 if (codec_info->count_sidecar && codec_info->add_sidecar) { 731 ret = codec_info->count_sidecar(card, &num_dais, num_devs); 732 if (ret) 733 return ret; 734 735 sof_end->include_sidecar = true; 736 } 737 738 for (j = 0; j < adr_dev->num_endpoints; j++) { 739 const struct snd_soc_acpi_endpoint *adr_end; 740 const struct asoc_sdw_dai_info *dai_info; 741 struct sof_sdw_dailink *sof_dai; 742 int stream; 743 744 adr_end = &adr_dev->endpoints[j]; 745 dai_info = &codec_info->dais[adr_end->num]; 746 sof_dai = find_dailink(sof_dais, adr_end); 747 748 if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk)) 749 continue; 750 751 dev_dbg(dev, 752 "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", 753 ffs(adr_link->mask) - 1, adr_dev->adr, 754 adr_end->num, type_strings[dai_info->dai_type], 755 dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-', 756 dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-', 757 adr_end->aggregated ? "group" : "solo", 758 adr_end->group_id); 759 760 if (adr_end->num >= codec_info->dai_num) { 761 dev_err(dev, 762 "%d is too many endpoints for codec: 0x%x\n", 763 adr_end->num, codec_info->part_id); 764 return -EINVAL; 765 } 766 767 for_each_pcm_streams(stream) { 768 if (dai_info->direction[stream] && 769 dai_info->dailink[stream] < 0) { 770 dev_err(dev, 771 "Invalid dailink id %d for codec: 0x%x\n", 772 dai_info->dailink[stream], 773 codec_info->part_id); 774 return -EINVAL; 775 } 776 777 if (dai_info->direction[stream]) { 778 num_dais += !sof_dai->num_devs[stream]; 779 sof_dai->num_devs[stream]++; 780 sof_dai->link_mask[stream] |= adr_link->mask; 781 } 782 } 783 784 num_link_dailinks += !!list_empty(&sof_dai->endpoints); 785 list_add_tail(&sof_end->list, &sof_dai->endpoints); 786 787 sof_end->link_mask = adr_link->mask; 788 sof_end->codec_name = codec_name; 789 sof_end->codec_info = codec_info; 790 sof_end->dai_info = dai_info; 791 sof_end++; 792 } 793 } 794 795 ctx->append_dai_type |= (num_link_dailinks > 1); 796 } 797 798 return num_dais; 799 } 800 801 static int create_sdw_dailink(struct snd_soc_card *card, 802 struct sof_sdw_dailink *sof_dai, 803 struct snd_soc_dai_link **dai_links, 804 int *be_id, struct snd_soc_codec_conf **codec_conf) 805 { 806 struct device *dev = card->dev; 807 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 808 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 809 struct sof_sdw_endpoint *sof_end; 810 int stream; 811 int ret; 812 813 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 814 if (sof_end->name_prefix) { 815 (*codec_conf)->dlc.name = sof_end->codec_name; 816 (*codec_conf)->name_prefix = sof_end->name_prefix; 817 (*codec_conf)++; 818 } 819 820 if (sof_end->include_sidecar) { 821 ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf); 822 if (ret) 823 return ret; 824 } 825 } 826 827 for_each_pcm_streams(stream) { 828 static const char * const sdw_stream_name[] = { 829 "SDW%d-Playback", 830 "SDW%d-Capture", 831 "SDW%d-Playback-%s", 832 "SDW%d-Capture-%s", 833 }; 834 struct snd_soc_dai_link_ch_map *codec_maps; 835 struct snd_soc_dai_link_component *codecs; 836 struct snd_soc_dai_link_component *cpus; 837 int num_cpus = hweight32(sof_dai->link_mask[stream]); 838 int num_codecs = sof_dai->num_devs[stream]; 839 int playback, capture; 840 int cur_link = 0; 841 int i = 0, j = 0; 842 char *name; 843 844 if (!sof_dai->num_devs[stream]) 845 continue; 846 847 sof_end = list_first_entry(&sof_dai->endpoints, 848 struct sof_sdw_endpoint, list); 849 850 *be_id = sof_end->dai_info->dailink[stream]; 851 if (*be_id < 0) { 852 dev_err(dev, "Invalid dailink id %d\n", *be_id); 853 return -EINVAL; 854 } 855 856 /* create stream name according to first link id */ 857 if (ctx->append_dai_type) 858 name = devm_kasprintf(dev, GFP_KERNEL, 859 sdw_stream_name[stream + 2], 860 ffs(sof_end->link_mask) - 1, 861 type_strings[sof_end->dai_info->dai_type]); 862 else 863 name = devm_kasprintf(dev, GFP_KERNEL, 864 sdw_stream_name[stream], 865 ffs(sof_end->link_mask) - 1); 866 if (!name) 867 return -ENOMEM; 868 869 cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); 870 if (!cpus) 871 return -ENOMEM; 872 873 codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); 874 if (!codecs) 875 return -ENOMEM; 876 877 codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); 878 if (!codec_maps) 879 return -ENOMEM; 880 881 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 882 if (!sof_end->dai_info->direction[stream]) 883 continue; 884 885 if (cur_link != sof_end->link_mask) { 886 int link_num = ffs(sof_end->link_mask) - 1; 887 int pin_num = intel_ctx->sdw_pin_index[link_num]++; 888 889 cur_link = sof_end->link_mask; 890 891 cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, 892 "SDW%d Pin%d", 893 link_num, pin_num); 894 if (!cpus[i].dai_name) 895 return -ENOMEM; 896 i++; 897 } 898 899 codec_maps[j].cpu = i - 1; 900 codec_maps[j].codec = j; 901 902 codecs[j].name = sof_end->codec_name; 903 codecs[j].dai_name = sof_end->dai_info->dai_name; 904 j++; 905 } 906 907 WARN_ON(i != num_cpus || j != num_codecs); 908 909 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 910 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 911 912 asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, 913 cpus, num_cpus, platform_component, 914 ARRAY_SIZE(platform_component), codecs, num_codecs, 915 asoc_sdw_rtd_init, &sdw_ops); 916 917 /* 918 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 919 * based on wait_for_completion(), tag them as 'nonatomic'. 920 */ 921 (*dai_links)->nonatomic = true; 922 (*dai_links)->ch_maps = codec_maps; 923 924 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 925 if (sof_end->dai_info->init) 926 sof_end->dai_info->init(card, *dai_links, 927 sof_end->codec_info, 928 playback); 929 } 930 931 (*dai_links)++; 932 } 933 934 return 0; 935 } 936 937 static int create_sdw_dailinks(struct snd_soc_card *card, 938 struct snd_soc_dai_link **dai_links, int *be_id, 939 struct sof_sdw_dailink *sof_dais, 940 struct snd_soc_codec_conf **codec_conf) 941 { 942 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 943 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 944 int ret, i; 945 946 for (i = 0; i < SDW_INTEL_MAX_LINKS; i++) 947 intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE; 948 949 /* generate DAI links by each sdw link */ 950 while (sof_dais->initialised) { 951 int current_be_id; 952 953 ret = create_sdw_dailink(card, sof_dais, dai_links, 954 ¤t_be_id, codec_conf); 955 if (ret) 956 return ret; 957 958 /* Update the be_id to match the highest ID used for SDW link */ 959 if (*be_id < current_be_id) 960 *be_id = current_be_id; 961 962 sof_dais++; 963 } 964 965 return 0; 966 } 967 968 static int create_ssp_dailinks(struct snd_soc_card *card, 969 struct snd_soc_dai_link **dai_links, int *be_id, 970 struct asoc_sdw_codec_info *ssp_info, 971 unsigned long ssp_mask) 972 { 973 struct device *dev = card->dev; 974 int i, j = 0; 975 int ret; 976 977 for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { 978 char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); 979 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 980 char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 981 ssp_info->acpi_id, j++); 982 int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 983 int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 984 985 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 986 playback, capture, cpu_dai_name, 987 platform_component->name, 988 ARRAY_SIZE(platform_component), codec_name, 989 ssp_info->dais[0].dai_name, NULL, 990 ssp_info->ops); 991 if (ret) 992 return ret; 993 994 ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0); 995 if (ret < 0) 996 return ret; 997 998 (*dai_links)++; 999 } 1000 1001 return 0; 1002 } 1003 1004 static int create_dmic_dailinks(struct snd_soc_card *card, 1005 struct snd_soc_dai_link **dai_links, int *be_id) 1006 { 1007 struct device *dev = card->dev; 1008 int ret; 1009 1010 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01", 1011 0, 1, // DMIC only supports capture 1012 "DMIC01 Pin", platform_component->name, 1013 ARRAY_SIZE(platform_component), 1014 "dmic-codec", "dmic-hifi", 1015 asoc_sdw_dmic_init, NULL); 1016 if (ret) 1017 return ret; 1018 1019 (*dai_links)++; 1020 1021 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", 1022 0, 1, // DMIC only supports capture 1023 "DMIC16k Pin", platform_component->name, 1024 ARRAY_SIZE(platform_component), 1025 "dmic-codec", "dmic-hifi", 1026 /* don't call asoc_sdw_dmic_init() twice */ 1027 NULL, NULL); 1028 if (ret) 1029 return ret; 1030 1031 (*dai_links)++; 1032 1033 return 0; 1034 } 1035 1036 static int create_hdmi_dailinks(struct snd_soc_card *card, 1037 struct snd_soc_dai_link **dai_links, int *be_id, 1038 int hdmi_num) 1039 { 1040 struct device *dev = card->dev; 1041 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1042 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1043 int i, ret; 1044 1045 for (i = 0; i < hdmi_num; i++) { 1046 char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); 1047 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); 1048 char *codec_name, *codec_dai_name; 1049 1050 if (intel_ctx->hdmi.idisp_codec) { 1051 codec_name = "ehdaudio0D2"; 1052 codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, 1053 "intel-hdmi-hifi%d", i + 1); 1054 } else { 1055 codec_name = "snd-soc-dummy"; 1056 codec_dai_name = "snd-soc-dummy-dai"; 1057 } 1058 1059 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 1060 1, 0, // HDMI only supports playback 1061 cpu_dai_name, platform_component->name, 1062 ARRAY_SIZE(platform_component), 1063 codec_name, codec_dai_name, 1064 i == 0 ? sof_sdw_hdmi_init : NULL, NULL); 1065 if (ret) 1066 return ret; 1067 1068 (*dai_links)++; 1069 } 1070 1071 return 0; 1072 } 1073 1074 static int create_bt_dailinks(struct snd_soc_card *card, 1075 struct snd_soc_dai_link **dai_links, int *be_id) 1076 { 1077 struct device *dev = card->dev; 1078 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1079 SOF_BT_OFFLOAD_SSP_SHIFT; 1080 char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1081 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1082 int ret; 1083 1084 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 1085 1, 1, cpu_dai_name, platform_component->name, 1086 ARRAY_SIZE(platform_component), 1087 snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, 1088 NULL, NULL); 1089 if (ret) 1090 return ret; 1091 1092 (*dai_links)++; 1093 1094 return 0; 1095 } 1096 1097 static int sof_card_dai_links_create(struct snd_soc_card *card) 1098 { 1099 struct device *dev = card->dev; 1100 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 1101 int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; 1102 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1103 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1104 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1105 struct snd_soc_codec_conf *codec_conf; 1106 struct asoc_sdw_codec_info *ssp_info; 1107 struct sof_sdw_endpoint *sof_ends; 1108 struct sof_sdw_dailink *sof_dais; 1109 int num_devs = 0; 1110 int num_ends = 0; 1111 struct snd_soc_dai_link *dai_links; 1112 int num_links; 1113 int be_id = 0; 1114 int hdmi_num; 1115 unsigned long ssp_mask; 1116 int ret; 1117 1118 ret = count_sdw_endpoints(card, &num_devs, &num_ends); 1119 if (ret < 0) { 1120 dev_err(dev, "failed to count devices/endpoints: %d\n", ret); 1121 return ret; 1122 } 1123 1124 /* One per DAI link, worst case is a DAI link for every endpoint */ 1125 sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); 1126 if (!sof_dais) 1127 return -ENOMEM; 1128 1129 /* One per endpoint, ie. each DAI on each codec/amp */ 1130 sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); 1131 if (!sof_ends) { 1132 ret = -ENOMEM; 1133 goto err_dai; 1134 } 1135 1136 ret = parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs); 1137 if (ret < 0) 1138 goto err_end; 1139 1140 sdw_be_num = ret; 1141 1142 /* 1143 * on generic tgl platform, I2S or sdw mode is supported 1144 * based on board rework. A ACPI device is registered in 1145 * system only when I2S mode is supported, not sdw mode. 1146 * Here check ACPI ID to confirm I2S is supported. 1147 */ 1148 ssp_info = asoc_sdw_find_codec_info_acpi(mach->id); 1149 if (ssp_info) { 1150 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1151 ssp_num = hweight_long(ssp_mask); 1152 } 1153 1154 if (mach_params->codec_mask & IDISP_CODEC_MASK) 1155 intel_ctx->hdmi.idisp_codec = true; 1156 1157 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1158 hdmi_num = SOF_TGL_HDMI_COUNT; 1159 else 1160 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1161 1162 /* enable dmic01 & dmic16k */ 1163 if (sof_sdw_quirk & SOC_SDW_PCH_DMIC || mach_params->dmic_num) { 1164 if (ctx->ignore_internal_dmic) 1165 dev_warn(dev, "Ignoring PCH DMIC\n"); 1166 else 1167 dmic_num = 2; 1168 } 1169 /* 1170 * mach_params->dmic_num will be used to set the cfg-mics value of card->components 1171 * string. Overwrite it to the actual number of PCH DMICs used in the device. 1172 */ 1173 mach_params->dmic_num = dmic_num; 1174 1175 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1176 bt_num = 1; 1177 1178 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", 1179 sdw_be_num, ssp_num, dmic_num, 1180 intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); 1181 1182 codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); 1183 if (!codec_conf) { 1184 ret = -ENOMEM; 1185 goto err_end; 1186 } 1187 1188 /* allocate BE dailinks */ 1189 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; 1190 dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 1191 if (!dai_links) { 1192 ret = -ENOMEM; 1193 goto err_end; 1194 } 1195 1196 card->codec_conf = codec_conf; 1197 card->num_configs = num_devs; 1198 card->dai_link = dai_links; 1199 card->num_links = num_links; 1200 1201 /* SDW */ 1202 if (sdw_be_num) { 1203 ret = create_sdw_dailinks(card, &dai_links, &be_id, 1204 sof_dais, &codec_conf); 1205 if (ret) 1206 goto err_end; 1207 } 1208 1209 /* SSP */ 1210 if (ssp_num) { 1211 ret = create_ssp_dailinks(card, &dai_links, &be_id, 1212 ssp_info, ssp_mask); 1213 if (ret) 1214 goto err_end; 1215 } 1216 1217 /* dmic */ 1218 if (dmic_num) { 1219 ret = create_dmic_dailinks(card, &dai_links, &be_id); 1220 if (ret) 1221 goto err_end; 1222 } 1223 1224 /* HDMI */ 1225 ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); 1226 if (ret) 1227 goto err_end; 1228 1229 /* BT */ 1230 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1231 ret = create_bt_dailinks(card, &dai_links, &be_id); 1232 if (ret) 1233 goto err_end; 1234 } 1235 1236 WARN_ON(codec_conf != card->codec_conf + card->num_configs); 1237 WARN_ON(dai_links != card->dai_link + card->num_links); 1238 1239 err_end: 1240 kfree(sof_ends); 1241 err_dai: 1242 kfree(sof_dais); 1243 1244 return ret; 1245 } 1246 1247 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1248 { 1249 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1250 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1251 int ret = 0; 1252 1253 ret = asoc_sdw_card_late_probe(card); 1254 if (ret < 0) 1255 return ret; 1256 1257 if (intel_ctx->hdmi.idisp_codec) 1258 ret = sof_sdw_hdmi_card_late_probe(card); 1259 1260 return ret; 1261 } 1262 1263 static int mc_probe(struct platform_device *pdev) 1264 { 1265 struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); 1266 struct snd_soc_card *card; 1267 struct asoc_sdw_mc_private *ctx; 1268 struct intel_mc_ctx *intel_ctx; 1269 int amp_num = 0, i; 1270 int ret; 1271 1272 dev_dbg(&pdev->dev, "Entry\n"); 1273 1274 intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL); 1275 if (!intel_ctx) 1276 return -ENOMEM; 1277 1278 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1279 if (!ctx) 1280 return -ENOMEM; 1281 1282 ctx->private = intel_ctx; 1283 ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); 1284 card = &ctx->card; 1285 card->dev = &pdev->dev; 1286 card->name = "soundwire"; 1287 card->owner = THIS_MODULE; 1288 card->late_probe = sof_sdw_card_late_probe; 1289 1290 snd_soc_card_set_drvdata(card, ctx); 1291 1292 dmi_check_system(sof_sdw_quirk_table); 1293 1294 if (quirk_override != -1) { 1295 dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", 1296 sof_sdw_quirk, quirk_override); 1297 sof_sdw_quirk = quirk_override; 1298 } 1299 1300 log_quirks(card->dev); 1301 1302 ctx->mc_quirk = sof_sdw_quirk; 1303 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1304 for (i = 0; i < ctx->codec_info_list_count; i++) 1305 codec_info_list[i].amp_num = 0; 1306 1307 if (mach->mach_params.subsystem_id_set) { 1308 snd_soc_card_set_pci_ssid(card, 1309 mach->mach_params.subsystem_vendor, 1310 mach->mach_params.subsystem_device); 1311 } 1312 1313 ret = sof_card_dai_links_create(card); 1314 if (ret < 0) 1315 return ret; 1316 1317 /* 1318 * the default amp_num is zero for each codec and 1319 * amp_num will only be increased for active amp 1320 * codecs on used platform 1321 */ 1322 for (i = 0; i < ctx->codec_info_list_count; i++) 1323 amp_num += codec_info_list[i].amp_num; 1324 1325 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1326 " cfg-amp:%d", amp_num); 1327 if (!card->components) 1328 return -ENOMEM; 1329 1330 if (mach->mach_params.dmic_num) { 1331 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1332 "%s mic:dmic cfg-mics:%d", 1333 card->components, 1334 mach->mach_params.dmic_num); 1335 if (!card->components) 1336 return -ENOMEM; 1337 } 1338 1339 /* Register the card */ 1340 ret = devm_snd_soc_register_card(card->dev, card); 1341 if (ret) { 1342 dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); 1343 asoc_sdw_mc_dailink_exit_loop(card); 1344 return ret; 1345 } 1346 1347 platform_set_drvdata(pdev, card); 1348 1349 return ret; 1350 } 1351 1352 static void mc_remove(struct platform_device *pdev) 1353 { 1354 struct snd_soc_card *card = platform_get_drvdata(pdev); 1355 1356 asoc_sdw_mc_dailink_exit_loop(card); 1357 } 1358 1359 static const struct platform_device_id mc_id_table[] = { 1360 { "sof_sdw", }, 1361 {} 1362 }; 1363 MODULE_DEVICE_TABLE(platform, mc_id_table); 1364 1365 static struct platform_driver sof_sdw_driver = { 1366 .driver = { 1367 .name = "sof_sdw", 1368 .pm = &snd_soc_pm_ops, 1369 }, 1370 .probe = mc_probe, 1371 .remove_new = mc_remove, 1372 .id_table = mc_id_table, 1373 }; 1374 1375 module_platform_driver(sof_sdw_driver); 1376 1377 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1378 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1379 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1380 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1381 MODULE_LICENSE("GPL v2"); 1382 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 1383 MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); 1384