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