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