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