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 SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC), 768 {} 769 }; 770 771 static void sof_sdw_check_ssid_quirk(const struct snd_soc_acpi_mach *mach) 772 { 773 const struct snd_pci_quirk *quirk_entry; 774 775 quirk_entry = snd_pci_quirk_lookup_id(mach->mach_params.subsystem_vendor, 776 mach->mach_params.subsystem_device, 777 sof_sdw_ssid_quirk_table); 778 779 if (quirk_entry) 780 sof_sdw_quirk = quirk_entry->value; 781 } 782 783 static struct snd_soc_dai_link_component platform_component[] = { 784 { 785 /* name might be overridden during probe */ 786 .name = "0000:00:1f.3" 787 } 788 }; 789 790 static const struct snd_soc_ops sdw_ops = { 791 .startup = asoc_sdw_startup, 792 .prepare = asoc_sdw_prepare, 793 .trigger = asoc_sdw_trigger, 794 .hw_params = asoc_sdw_hw_params, 795 .hw_free = asoc_sdw_hw_free, 796 .shutdown = asoc_sdw_shutdown, 797 }; 798 799 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 800 801 static int create_sdw_dailink(struct snd_soc_card *card, 802 struct asoc_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 snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 808 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 809 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 810 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 811 struct asoc_sdw_endpoint *sof_end; 812 int stream; 813 int ret; 814 815 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 816 if (sof_end->name_prefix) { 817 (*codec_conf)->dlc.name = sof_end->codec_name; 818 (*codec_conf)->name_prefix = sof_end->name_prefix; 819 (*codec_conf)++; 820 } 821 822 if (sof_end->include_sidecar) { 823 ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf); 824 if (ret) 825 return ret; 826 } 827 } 828 829 for_each_pcm_streams(stream) { 830 static const char * const sdw_stream_name[] = { 831 "SDW%d-Playback", 832 "SDW%d-Capture", 833 "SDW%d-Playback-%s", 834 "SDW%d-Capture-%s", 835 }; 836 struct snd_soc_dai_link_ch_map *codec_maps; 837 struct snd_soc_dai_link_component *codecs; 838 struct snd_soc_dai_link_component *cpus; 839 int num_cpus = hweight32(sof_dai->link_mask[stream]); 840 int num_codecs = sof_dai->num_devs[stream]; 841 int playback, capture; 842 int cur_link = 0; 843 int i = 0, j = 0; 844 char *name; 845 846 if (!sof_dai->num_devs[stream]) 847 continue; 848 849 sof_end = list_first_entry(&sof_dai->endpoints, 850 struct asoc_sdw_endpoint, list); 851 852 *be_id = sof_end->dai_info->dailink[stream]; 853 if (*be_id < 0) { 854 dev_err(dev, "Invalid dailink id %d\n", *be_id); 855 return -EINVAL; 856 } 857 858 /* create stream name according to first link id */ 859 if (ctx->append_dai_type) 860 name = devm_kasprintf(dev, GFP_KERNEL, 861 sdw_stream_name[stream + 2], 862 ffs(sof_end->link_mask) - 1, 863 type_strings[sof_end->dai_info->dai_type]); 864 else 865 name = devm_kasprintf(dev, GFP_KERNEL, 866 sdw_stream_name[stream], 867 ffs(sof_end->link_mask) - 1); 868 if (!name) 869 return -ENOMEM; 870 871 cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); 872 if (!cpus) 873 return -ENOMEM; 874 875 codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); 876 if (!codecs) 877 return -ENOMEM; 878 879 codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); 880 if (!codec_maps) 881 return -ENOMEM; 882 883 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 884 if (!sof_end->dai_info->direction[stream]) 885 continue; 886 887 if (cur_link != sof_end->link_mask) { 888 int link_num = ffs(sof_end->link_mask) - 1; 889 int pin_num = intel_ctx->sdw_pin_index[link_num]++; 890 891 cur_link = sof_end->link_mask; 892 893 cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, 894 "SDW%d Pin%d", 895 link_num, pin_num); 896 if (!cpus[i].dai_name) 897 return -ENOMEM; 898 i++; 899 } 900 901 codec_maps[j].cpu = i - 1; 902 codec_maps[j].codec = j; 903 904 codecs[j].name = sof_end->codec_name; 905 codecs[j].dai_name = sof_end->dai_info->dai_name; 906 if (sof_end->dai_info->dai_type == SOC_SDW_DAI_TYPE_MIC && 907 mach_params->dmic_num > 0) { 908 dev_warn(dev, 909 "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"); 910 } 911 j++; 912 } 913 914 WARN_ON(i != num_cpus || j != num_codecs); 915 916 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 917 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 918 919 asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, 920 cpus, num_cpus, platform_component, 921 ARRAY_SIZE(platform_component), codecs, num_codecs, 922 1, asoc_sdw_rtd_init, &sdw_ops); 923 924 /* 925 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 926 * based on wait_for_completion(), tag them as 'nonatomic'. 927 */ 928 (*dai_links)->nonatomic = true; 929 (*dai_links)->ch_maps = codec_maps; 930 931 list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 932 if (sof_end->dai_info->init) 933 sof_end->dai_info->init(card, *dai_links, 934 sof_end->codec_info, 935 playback); 936 } 937 938 (*dai_links)++; 939 } 940 941 return 0; 942 } 943 944 static int create_sdw_dailinks(struct snd_soc_card *card, 945 struct snd_soc_dai_link **dai_links, int *be_id, 946 struct asoc_sdw_dailink *sof_dais, 947 struct snd_soc_codec_conf **codec_conf) 948 { 949 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 950 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 951 int ret, i; 952 953 for (i = 0; i < SDW_INTEL_MAX_LINKS; i++) 954 intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE; 955 956 /* generate DAI links by each sdw link */ 957 while (sof_dais->initialised) { 958 int current_be_id = 0; 959 960 ret = create_sdw_dailink(card, sof_dais, dai_links, 961 ¤t_be_id, codec_conf); 962 if (ret) 963 return ret; 964 965 /* Update the be_id to match the highest ID used for SDW link */ 966 if (*be_id < current_be_id) 967 *be_id = current_be_id; 968 969 sof_dais++; 970 } 971 972 return 0; 973 } 974 975 static int create_ssp_dailinks(struct snd_soc_card *card, 976 struct snd_soc_dai_link **dai_links, int *be_id, 977 struct asoc_sdw_codec_info *ssp_info, 978 unsigned long ssp_mask) 979 { 980 struct device *dev = card->dev; 981 int i, j = 0; 982 int ret; 983 984 for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { 985 char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); 986 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 987 char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 988 ssp_info->acpi_id, j++); 989 if (!name || !cpu_dai_name || !codec_name) 990 return -ENOMEM; 991 992 int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 993 int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 994 995 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 996 playback, capture, cpu_dai_name, 997 platform_component->name, 998 ARRAY_SIZE(platform_component), codec_name, 999 ssp_info->dais[0].dai_name, 1, NULL, 1000 ssp_info->ops); 1001 if (ret) 1002 return ret; 1003 1004 ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0); 1005 if (ret < 0) 1006 return ret; 1007 1008 (*dai_links)++; 1009 } 1010 1011 return 0; 1012 } 1013 1014 static int create_dmic_dailinks(struct snd_soc_card *card, 1015 struct snd_soc_dai_link **dai_links, int *be_id) 1016 { 1017 struct device *dev = card->dev; 1018 int ret; 1019 1020 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01", 1021 0, 1, // DMIC only supports capture 1022 "DMIC01 Pin", platform_component->name, 1023 ARRAY_SIZE(platform_component), 1024 "dmic-codec", "dmic-hifi", 1, 1025 asoc_sdw_dmic_init, NULL); 1026 if (ret) 1027 return ret; 1028 1029 (*dai_links)++; 1030 1031 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", 1032 0, 1, // DMIC only supports capture 1033 "DMIC16k Pin", platform_component->name, 1034 ARRAY_SIZE(platform_component), 1035 "dmic-codec", "dmic-hifi", 1, 1036 /* don't call asoc_sdw_dmic_init() twice */ 1037 NULL, NULL); 1038 if (ret) 1039 return ret; 1040 1041 (*dai_links)++; 1042 1043 return 0; 1044 } 1045 1046 static int create_hdmi_dailinks(struct snd_soc_card *card, 1047 struct snd_soc_dai_link **dai_links, int *be_id, 1048 int hdmi_num) 1049 { 1050 struct device *dev = card->dev; 1051 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1052 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1053 int i, ret; 1054 1055 for (i = 0; i < hdmi_num; i++) { 1056 char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); 1057 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); 1058 if (!name || !cpu_dai_name) 1059 return -ENOMEM; 1060 1061 char *codec_name, *codec_dai_name; 1062 1063 if (intel_ctx->hdmi.idisp_codec) { 1064 codec_name = "ehdaudio0D2"; 1065 codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, 1066 "intel-hdmi-hifi%d", i + 1); 1067 } else { 1068 codec_name = "snd-soc-dummy"; 1069 codec_dai_name = "snd-soc-dummy-dai"; 1070 } 1071 1072 if (!codec_dai_name) 1073 return -ENOMEM; 1074 1075 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 1076 1, 0, // HDMI only supports playback 1077 cpu_dai_name, platform_component->name, 1078 ARRAY_SIZE(platform_component), 1079 codec_name, codec_dai_name, 1, 1080 i == 0 ? sof_sdw_hdmi_init : NULL, NULL); 1081 if (ret) 1082 return ret; 1083 1084 (*dai_links)++; 1085 } 1086 1087 return 0; 1088 } 1089 1090 static int create_bt_dailinks(struct snd_soc_card *card, 1091 struct snd_soc_dai_link **dai_links, int *be_id) 1092 { 1093 struct device *dev = card->dev; 1094 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1095 SOF_BT_OFFLOAD_SSP_SHIFT; 1096 char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1097 char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1098 if (!name || !cpu_dai_name) 1099 return -ENOMEM; 1100 1101 int ret; 1102 1103 ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, 1104 1, 1, cpu_dai_name, platform_component->name, 1105 ARRAY_SIZE(platform_component), 1106 snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, 1107 1, NULL, NULL); 1108 if (ret) 1109 return ret; 1110 1111 (*dai_links)++; 1112 1113 return 0; 1114 } 1115 1116 static int sof_card_dai_links_create(struct snd_soc_card *card) 1117 { 1118 struct device *dev = card->dev; 1119 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 1120 int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; 1121 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1122 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1123 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1124 struct snd_soc_codec_conf *codec_conf; 1125 struct asoc_sdw_codec_info *ssp_info; 1126 struct asoc_sdw_endpoint *sof_ends; 1127 struct asoc_sdw_dailink *sof_dais; 1128 int num_devs = 0; 1129 int num_ends = 0; 1130 struct snd_soc_dai_link *dai_links; 1131 int num_links; 1132 int be_id = 0; 1133 int hdmi_num; 1134 unsigned long ssp_mask; 1135 int ret; 1136 1137 ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends); 1138 if (ret < 0) { 1139 dev_err(dev, "failed to count devices/endpoints: %d\n", ret); 1140 return ret; 1141 } 1142 1143 /* 1144 * One per DAI link, worst case is a DAI link for every endpoint, also 1145 * add one additional to act as a terminator such that code can iterate 1146 * until it hits an uninitialised DAI. 1147 */ 1148 sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL); 1149 if (!sof_dais) 1150 return -ENOMEM; 1151 1152 /* One per endpoint, ie. each DAI on each codec/amp */ 1153 sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); 1154 if (!sof_ends) { 1155 ret = -ENOMEM; 1156 goto err_dai; 1157 } 1158 1159 ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs); 1160 if (ret < 0) 1161 goto err_end; 1162 1163 sdw_be_num = ret; 1164 1165 /* 1166 * on generic tgl platform, I2S or sdw mode is supported 1167 * based on board rework. A ACPI device is registered in 1168 * system only when I2S mode is supported, not sdw mode. 1169 * Here check ACPI ID to confirm I2S is supported. 1170 */ 1171 ssp_info = asoc_sdw_find_codec_info_acpi(mach->id); 1172 if (ssp_info) { 1173 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1174 ssp_num = hweight_long(ssp_mask); 1175 } 1176 1177 if (mach_params->codec_mask & IDISP_CODEC_MASK) 1178 intel_ctx->hdmi.idisp_codec = true; 1179 1180 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1181 hdmi_num = SOF_TGL_HDMI_COUNT; 1182 else 1183 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1184 1185 /* enable dmic01 & dmic16k */ 1186 if (ctx->ignore_internal_dmic) { 1187 dev_dbg(dev, "SoundWire DMIC is used, ignoring internal DMIC\n"); 1188 mach_params->dmic_num = 0; 1189 } else if (mach_params->dmic_num) { 1190 dmic_num = 2; 1191 } else if (sof_sdw_quirk & SOC_SDW_PCH_DMIC) { 1192 dmic_num = 2; 1193 /* 1194 * mach_params->dmic_num will be used to set the cfg-mics value of 1195 * card->components string. Set it to the default value. 1196 */ 1197 mach_params->dmic_num = DMIC_DEFAULT_CHANNELS; 1198 } 1199 1200 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1201 bt_num = 1; 1202 1203 dev_dbg(dev, "DAI link numbers: sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", 1204 sdw_be_num, ssp_num, dmic_num, 1205 intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); 1206 1207 codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); 1208 if (!codec_conf) { 1209 ret = -ENOMEM; 1210 goto err_end; 1211 } 1212 1213 /* allocate BE dailinks */ 1214 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; 1215 dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 1216 if (!dai_links) { 1217 ret = -ENOMEM; 1218 goto err_end; 1219 } 1220 1221 card->codec_conf = codec_conf; 1222 card->num_configs = num_devs; 1223 card->dai_link = dai_links; 1224 card->num_links = num_links; 1225 1226 /* SDW */ 1227 if (sdw_be_num) { 1228 ret = create_sdw_dailinks(card, &dai_links, &be_id, 1229 sof_dais, &codec_conf); 1230 if (ret) 1231 goto err_end; 1232 } 1233 1234 /* SSP */ 1235 if (ssp_num) { 1236 ret = create_ssp_dailinks(card, &dai_links, &be_id, 1237 ssp_info, ssp_mask); 1238 if (ret) 1239 goto err_end; 1240 } 1241 1242 /* dmic */ 1243 if (dmic_num) { 1244 ret = create_dmic_dailinks(card, &dai_links, &be_id); 1245 if (ret) 1246 goto err_end; 1247 } 1248 1249 /* HDMI */ 1250 ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); 1251 if (ret) 1252 goto err_end; 1253 1254 /* BT */ 1255 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1256 ret = create_bt_dailinks(card, &dai_links, &be_id); 1257 if (ret) 1258 goto err_end; 1259 } 1260 1261 WARN_ON(codec_conf != card->codec_conf + card->num_configs); 1262 WARN_ON(dai_links != card->dai_link + card->num_links); 1263 1264 err_end: 1265 kfree(sof_ends); 1266 err_dai: 1267 kfree(sof_dais); 1268 1269 return ret; 1270 } 1271 1272 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1273 { 1274 struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 1275 struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; 1276 int ret = 0; 1277 1278 ret = asoc_sdw_card_late_probe(card); 1279 if (ret < 0) 1280 return ret; 1281 1282 if (intel_ctx->hdmi.idisp_codec) 1283 ret = sof_sdw_hdmi_card_late_probe(card); 1284 1285 return ret; 1286 } 1287 1288 static int mc_probe(struct platform_device *pdev) 1289 { 1290 struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); 1291 struct snd_soc_card *card; 1292 struct asoc_sdw_mc_private *ctx; 1293 struct intel_mc_ctx *intel_ctx; 1294 int amp_num = 0, i; 1295 int ret; 1296 1297 dev_dbg(&pdev->dev, "Entry\n"); 1298 1299 intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL); 1300 if (!intel_ctx) 1301 return -ENOMEM; 1302 1303 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1304 if (!ctx) 1305 return -ENOMEM; 1306 1307 ctx->private = intel_ctx; 1308 ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); 1309 card = &ctx->card; 1310 card->dev = &pdev->dev; 1311 card->name = "soundwire"; 1312 card->owner = THIS_MODULE; 1313 card->late_probe = sof_sdw_card_late_probe; 1314 1315 snd_soc_card_set_drvdata(card, ctx); 1316 1317 if (mach->mach_params.subsystem_id_set) { 1318 snd_soc_card_set_pci_ssid(card, 1319 mach->mach_params.subsystem_vendor, 1320 mach->mach_params.subsystem_device); 1321 sof_sdw_check_ssid_quirk(mach); 1322 } 1323 1324 dmi_check_system(sof_sdw_quirk_table); 1325 1326 if (quirk_override != -1) { 1327 dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", 1328 sof_sdw_quirk, quirk_override); 1329 sof_sdw_quirk = quirk_override; 1330 } 1331 1332 log_quirks(card->dev); 1333 1334 ctx->mc_quirk = sof_sdw_quirk; 1335 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1336 for (i = 0; i < ctx->codec_info_list_count; i++) 1337 codec_info_list[i].amp_num = 0; 1338 1339 ret = sof_card_dai_links_create(card); 1340 if (ret < 0) 1341 return ret; 1342 1343 /* 1344 * the default amp_num is zero for each codec and 1345 * amp_num will only be increased for active amp 1346 * codecs on used platform 1347 */ 1348 for (i = 0; i < ctx->codec_info_list_count; i++) 1349 amp_num += codec_info_list[i].amp_num; 1350 1351 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1352 " cfg-amp:%d", amp_num); 1353 if (!card->components) 1354 return -ENOMEM; 1355 1356 if (mach->mach_params.dmic_num) { 1357 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1358 "%s mic:dmic cfg-mics:%d", 1359 card->components, 1360 mach->mach_params.dmic_num); 1361 if (!card->components) 1362 return -ENOMEM; 1363 } 1364 1365 /* Register the card */ 1366 ret = devm_snd_soc_register_card(card->dev, card); 1367 if (ret) { 1368 dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); 1369 asoc_sdw_mc_dailink_exit_loop(card); 1370 return ret; 1371 } 1372 1373 platform_set_drvdata(pdev, card); 1374 1375 return ret; 1376 } 1377 1378 static void mc_remove(struct platform_device *pdev) 1379 { 1380 struct snd_soc_card *card = platform_get_drvdata(pdev); 1381 1382 asoc_sdw_mc_dailink_exit_loop(card); 1383 } 1384 1385 static const struct platform_device_id mc_id_table[] = { 1386 { "sof_sdw", }, 1387 {} 1388 }; 1389 MODULE_DEVICE_TABLE(platform, mc_id_table); 1390 1391 static struct platform_driver sof_sdw_driver = { 1392 .driver = { 1393 .name = "sof_sdw", 1394 .pm = &snd_soc_pm_ops, 1395 }, 1396 .probe = mc_probe, 1397 .remove = mc_remove, 1398 .id_table = mc_id_table, 1399 }; 1400 1401 module_platform_driver(sof_sdw_driver); 1402 1403 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1404 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1405 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1406 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1407 MODULE_LICENSE("GPL v2"); 1408 MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON"); 1409 MODULE_IMPORT_NS("SND_SOC_SDW_UTILS"); 1410