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