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