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 int ch = params_channels(params); 574 struct snd_soc_dai *codec_dai; 575 struct snd_soc_dai *cpu_dai; 576 unsigned int ch_mask; 577 int num_codecs; 578 int step; 579 int i; 580 int j; 581 582 if (!rtd->dai_link->codec_ch_maps) 583 return 0; 584 585 /* Identical data will be sent to all codecs in playback */ 586 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 587 ch_mask = GENMASK(ch - 1, 0); 588 step = 0; 589 } else { 590 num_codecs = rtd->dai_link->num_codecs; 591 592 if (ch < num_codecs || ch % num_codecs != 0) { 593 dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", 594 ch, num_codecs); 595 return -EINVAL; 596 } 597 598 ch_mask = GENMASK(ch / num_codecs - 1, 0); 599 step = hweight_long(ch_mask); 600 601 } 602 603 /* 604 * The captured data will be combined from each cpu DAI if the dai 605 * link has more than one codec DAIs. Set codec channel mask and 606 * ASoC will set the corresponding channel numbers for each cpu dai. 607 */ 608 for_each_rtd_cpu_dais(rtd, i, cpu_dai) { 609 for_each_rtd_codec_dais(rtd, j, codec_dai) { 610 if (rtd->dai_link->codec_ch_maps[j].connected_cpu_id != i) 611 continue; 612 rtd->dai_link->codec_ch_maps[j].ch_mask = ch_mask << (j * step); 613 } 614 } 615 return 0; 616 } 617 618 int sdw_hw_free(struct snd_pcm_substream *substream) 619 { 620 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 621 struct sdw_stream_runtime *sdw_stream; 622 struct snd_soc_dai *dai; 623 624 /* Find stream from first CPU DAI */ 625 dai = snd_soc_rtd_to_cpu(rtd, 0); 626 627 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 628 if (IS_ERR(sdw_stream)) { 629 dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 630 return PTR_ERR(sdw_stream); 631 } 632 633 return sdw_deprepare_stream(sdw_stream); 634 } 635 636 void sdw_shutdown(struct snd_pcm_substream *substream) 637 { 638 sdw_shutdown_stream(substream); 639 } 640 641 static const struct snd_soc_ops sdw_ops = { 642 .startup = sdw_startup, 643 .prepare = sdw_prepare, 644 .trigger = sdw_trigger, 645 .hw_params = sdw_hw_params, 646 .hw_free = sdw_hw_free, 647 .shutdown = sdw_shutdown, 648 }; 649 650 static struct sof_sdw_codec_info codec_info_list[] = { 651 { 652 .part_id = 0x700, 653 .dais = { 654 { 655 .direction = {true, true}, 656 .dai_name = "rt700-aif1", 657 .dai_type = SOF_SDW_DAI_TYPE_JACK, 658 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 659 .init = sof_sdw_rt700_init, 660 }, 661 }, 662 .dai_num = 1, 663 }, 664 { 665 .part_id = 0x711, 666 .version_id = 3, 667 .dais = { 668 { 669 .direction = {true, true}, 670 .dai_name = "rt711-sdca-aif1", 671 .dai_type = SOF_SDW_DAI_TYPE_JACK, 672 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 673 .init = sof_sdw_rt_sdca_jack_init, 674 .exit = sof_sdw_rt_sdca_jack_exit, 675 }, 676 }, 677 .dai_num = 1, 678 }, 679 { 680 .part_id = 0x711, 681 .version_id = 2, 682 .dais = { 683 { 684 .direction = {true, true}, 685 .dai_name = "rt711-aif1", 686 .dai_type = SOF_SDW_DAI_TYPE_JACK, 687 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 688 .init = sof_sdw_rt711_init, 689 .exit = sof_sdw_rt711_exit, 690 }, 691 }, 692 .dai_num = 1, 693 }, 694 { 695 .part_id = 0x712, 696 .version_id = 3, 697 .dais = { 698 { 699 .direction = {true, true}, 700 .dai_name = "rt712-sdca-aif1", 701 .dai_type = SOF_SDW_DAI_TYPE_JACK, 702 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 703 .init = sof_sdw_rt_sdca_jack_init, 704 .exit = sof_sdw_rt_sdca_jack_exit, 705 }, 706 { 707 .direction = {true, false}, 708 .dai_name = "rt712-sdca-aif2", 709 .dai_type = SOF_SDW_DAI_TYPE_AMP, 710 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 711 .init = sof_sdw_rt712_spk_init, 712 }, 713 }, 714 .dai_num = 2, 715 }, 716 { 717 .part_id = 0x1712, 718 .version_id = 3, 719 .dais = { 720 { 721 .direction = {false, true}, 722 .dai_name = "rt712-sdca-dmic-aif1", 723 .dai_type = SOF_SDW_DAI_TYPE_MIC, 724 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 725 .init = sof_sdw_rt712_sdca_dmic_init, 726 }, 727 }, 728 .dai_num = 1, 729 }, 730 { 731 .part_id = 0x713, 732 .version_id = 3, 733 .dais = { 734 { 735 .direction = {true, true}, 736 .dai_name = "rt712-sdca-aif1", 737 .dai_type = SOF_SDW_DAI_TYPE_JACK, 738 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 739 .init = sof_sdw_rt_sdca_jack_init, 740 .exit = sof_sdw_rt_sdca_jack_exit, 741 }, 742 }, 743 .dai_num = 1, 744 }, 745 { 746 .part_id = 0x1713, 747 .version_id = 3, 748 .dais = { 749 { 750 .direction = {false, true}, 751 .dai_name = "rt712-sdca-dmic-aif1", 752 .dai_type = SOF_SDW_DAI_TYPE_MIC, 753 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 754 .init = sof_sdw_rt712_sdca_dmic_init, 755 }, 756 }, 757 .dai_num = 1, 758 }, 759 { 760 .part_id = 0x1308, 761 .acpi_id = "10EC1308", 762 .dais = { 763 { 764 .direction = {true, false}, 765 .dai_name = "rt1308-aif", 766 .dai_type = SOF_SDW_DAI_TYPE_AMP, 767 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 768 .init = sof_sdw_rt_amp_init, 769 .exit = sof_sdw_rt_amp_exit, 770 }, 771 }, 772 .dai_num = 1, 773 .ops = &sof_sdw_rt1308_i2s_ops, 774 }, 775 { 776 .part_id = 0x1316, 777 .dais = { 778 { 779 .direction = {true, true}, 780 .dai_name = "rt1316-aif", 781 .dai_type = SOF_SDW_DAI_TYPE_AMP, 782 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 783 .init = sof_sdw_rt_amp_init, 784 .exit = sof_sdw_rt_amp_exit, 785 }, 786 }, 787 .dai_num = 1, 788 }, 789 { 790 .part_id = 0x1318, 791 .dais = { 792 { 793 .direction = {true, true}, 794 .dai_name = "rt1318-aif", 795 .dai_type = SOF_SDW_DAI_TYPE_AMP, 796 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 797 .init = sof_sdw_rt_amp_init, 798 .exit = sof_sdw_rt_amp_exit, 799 }, 800 }, 801 .dai_num = 1, 802 }, 803 { 804 .part_id = 0x714, 805 .version_id = 3, 806 .ignore_pch_dmic = true, 807 .dais = { 808 { 809 .direction = {false, true}, 810 .dai_name = "rt715-aif2", 811 .dai_type = SOF_SDW_DAI_TYPE_MIC, 812 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 813 .init = sof_sdw_rt715_sdca_init, 814 }, 815 }, 816 .dai_num = 1, 817 }, 818 { 819 .part_id = 0x715, 820 .version_id = 3, 821 .ignore_pch_dmic = true, 822 .dais = { 823 { 824 .direction = {false, true}, 825 .dai_name = "rt715-aif2", 826 .dai_type = SOF_SDW_DAI_TYPE_MIC, 827 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 828 .init = sof_sdw_rt715_sdca_init, 829 }, 830 }, 831 .dai_num = 1, 832 }, 833 { 834 .part_id = 0x714, 835 .version_id = 2, 836 .ignore_pch_dmic = true, 837 .dais = { 838 { 839 .direction = {false, true}, 840 .dai_name = "rt715-aif2", 841 .dai_type = SOF_SDW_DAI_TYPE_MIC, 842 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 843 .init = sof_sdw_rt715_init, 844 }, 845 }, 846 .dai_num = 1, 847 }, 848 { 849 .part_id = 0x715, 850 .version_id = 2, 851 .ignore_pch_dmic = true, 852 .dais = { 853 { 854 .direction = {false, true}, 855 .dai_name = "rt715-aif2", 856 .dai_type = SOF_SDW_DAI_TYPE_MIC, 857 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 858 .init = sof_sdw_rt715_init, 859 }, 860 }, 861 .dai_num = 1, 862 }, 863 { 864 .part_id = 0x8373, 865 .dais = { 866 { 867 .direction = {true, true}, 868 .dai_name = "max98373-aif1", 869 .dai_type = SOF_SDW_DAI_TYPE_AMP, 870 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 871 .init = sof_sdw_maxim_init, 872 }, 873 }, 874 .dai_num = 1, 875 }, 876 { 877 .part_id = 0x8363, 878 .dais = { 879 { 880 .direction = {true, false}, 881 .dai_name = "max98363-aif1", 882 .dai_type = SOF_SDW_DAI_TYPE_AMP, 883 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 884 .init = sof_sdw_maxim_init, 885 }, 886 }, 887 .dai_num = 1, 888 }, 889 { 890 .part_id = 0x5682, 891 .dais = { 892 { 893 .direction = {true, true}, 894 .dai_name = "rt5682-sdw", 895 .dai_type = SOF_SDW_DAI_TYPE_JACK, 896 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 897 .init = sof_sdw_rt5682_init, 898 }, 899 }, 900 .dai_num = 1, 901 }, 902 { 903 .part_id = 0x3556, 904 .dais = { 905 { 906 .direction = {true, true}, 907 .dai_name = "cs35l56-sdw1", 908 .dai_type = SOF_SDW_DAI_TYPE_AMP, 909 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 910 .init = sof_sdw_cs_amp_init, 911 }, 912 }, 913 .dai_num = 1, 914 }, 915 { 916 .part_id = 0x4242, 917 .dais = { 918 { 919 .direction = {true, true}, 920 .dai_name = "cs42l42-sdw", 921 .dai_type = SOF_SDW_DAI_TYPE_JACK, 922 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 923 .init = sof_sdw_cs42l42_init, 924 }, 925 }, 926 .dai_num = 1, 927 }, 928 { 929 .part_id = 0x4243, 930 .codec_name = "cs42l43-codec", 931 .dais = { 932 { 933 .direction = {true, false}, 934 .dai_name = "cs42l43-dp5", 935 .dai_type = SOF_SDW_DAI_TYPE_JACK, 936 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 937 .init = sof_sdw_cs42l43_hs_init, 938 }, 939 { 940 .direction = {false, true}, 941 .dai_name = "cs42l43-dp1", 942 .dai_type = SOF_SDW_DAI_TYPE_MIC, 943 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 944 .init = sof_sdw_cs42l43_dmic_init, 945 }, 946 { 947 .direction = {false, true}, 948 .dai_name = "cs42l43-dp2", 949 .dai_type = SOF_SDW_DAI_TYPE_JACK, 950 .dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID}, 951 }, 952 }, 953 .dai_num = 3, 954 }, 955 { 956 .part_id = 0xaaaa, /* generic codec mockup */ 957 .version_id = 0, 958 .dais = { 959 { 960 .direction = {true, true}, 961 .dai_name = "sdw-mockup-aif1", 962 .dai_type = SOF_SDW_DAI_TYPE_JACK, 963 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 964 .init = NULL, 965 }, 966 }, 967 .dai_num = 1, 968 }, 969 { 970 .part_id = 0xaa55, /* headset codec mockup */ 971 .version_id = 0, 972 .dais = { 973 { 974 .direction = {true, true}, 975 .dai_name = "sdw-mockup-aif1", 976 .dai_type = SOF_SDW_DAI_TYPE_JACK, 977 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 978 .init = NULL, 979 }, 980 }, 981 .dai_num = 1, 982 }, 983 { 984 .part_id = 0x55aa, /* amplifier mockup */ 985 .version_id = 0, 986 .dais = { 987 { 988 .direction = {true, true}, 989 .dai_name = "sdw-mockup-aif1", 990 .dai_type = SOF_SDW_DAI_TYPE_AMP, 991 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 992 .init = NULL, 993 }, 994 }, 995 .dai_num = 1, 996 }, 997 { 998 .part_id = 0x5555, 999 .version_id = 0, 1000 .dais = { 1001 { 1002 .dai_name = "sdw-mockup-aif1", 1003 .direction = {false, true}, 1004 .dai_type = SOF_SDW_DAI_TYPE_MIC, 1005 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 1006 .init = NULL, 1007 }, 1008 }, 1009 .dai_num = 1, 1010 }, 1011 }; 1012 1013 static inline int find_codec_info_part(const u64 adr) 1014 { 1015 unsigned int part_id, sdw_version; 1016 int i; 1017 1018 part_id = SDW_PART_ID(adr); 1019 sdw_version = SDW_VERSION(adr); 1020 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1021 /* 1022 * A codec info is for all sdw version with the part id if 1023 * version_id is not specified in the codec info. 1024 */ 1025 if (part_id == codec_info_list[i].part_id && 1026 (!codec_info_list[i].version_id || 1027 sdw_version == codec_info_list[i].version_id)) 1028 return i; 1029 1030 return -EINVAL; 1031 1032 } 1033 1034 static inline int find_codec_info_acpi(const u8 *acpi_id) 1035 { 1036 int i; 1037 1038 if (!acpi_id[0]) 1039 return -EINVAL; 1040 1041 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1042 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) 1043 return i; 1044 1045 return -EINVAL; 1046 } 1047 1048 /* 1049 * get BE dailink number and CPU DAI number based on sdw link adr. 1050 * Since some sdw slaves may be aggregated, the CPU DAI number 1051 * may be larger than the number of BE dailinks. 1052 */ 1053 static int get_dailink_info(struct device *dev, 1054 const struct snd_soc_acpi_link_adr *adr_link, 1055 int *sdw_be_num, int *codecs_num) 1056 { 1057 bool group_visited[SDW_MAX_GROUPS]; 1058 bool no_aggregation; 1059 int i; 1060 int j; 1061 1062 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1063 *sdw_be_num = 0; 1064 1065 if (!adr_link) 1066 return -EINVAL; 1067 1068 for (i = 0; i < SDW_MAX_GROUPS; i++) 1069 group_visited[i] = false; 1070 1071 for (; adr_link->num_adr; adr_link++) { 1072 const struct snd_soc_acpi_endpoint *endpoint; 1073 struct sof_sdw_codec_info *codec_info; 1074 int codec_index; 1075 int stream; 1076 u64 adr; 1077 1078 /* make sure the link mask has a single bit set */ 1079 if (!is_power_of_2(adr_link->mask)) 1080 return -EINVAL; 1081 1082 for (i = 0; i < adr_link->num_adr; i++) { 1083 adr = adr_link->adr_d[i].adr; 1084 codec_index = find_codec_info_part(adr); 1085 if (codec_index < 0) 1086 return codec_index; 1087 1088 codec_info = &codec_info_list[codec_index]; 1089 1090 *codecs_num += codec_info->dai_num; 1091 1092 if (!adr_link->adr_d[i].name_prefix) { 1093 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1094 adr_link->adr_d[i].adr); 1095 return -EINVAL; 1096 } 1097 1098 endpoint = adr_link->adr_d[i].endpoints; 1099 if (endpoint->aggregated && !endpoint->group_id) { 1100 dev_err(dev, "invalid group id on link %x\n", 1101 adr_link->mask); 1102 return -EINVAL; 1103 } 1104 1105 for (j = 0; j < codec_info->dai_num; j++) { 1106 /* count DAI number for playback and capture */ 1107 for_each_pcm_streams(stream) { 1108 if (!codec_info->dais[j].direction[stream]) 1109 continue; 1110 1111 /* count BE for each non-aggregated slave or group */ 1112 if (!endpoint->aggregated || no_aggregation || 1113 !group_visited[endpoint->group_id]) 1114 (*sdw_be_num)++; 1115 } 1116 } 1117 1118 if (endpoint->aggregated) 1119 group_visited[endpoint->group_id] = true; 1120 } 1121 } 1122 1123 return 0; 1124 } 1125 1126 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 1127 int *be_id, char *name, int playback, int capture, 1128 struct snd_soc_dai_link_component *cpus, int cpus_num, 1129 struct snd_soc_dai_link_component *codecs, int codecs_num, 1130 int (*init)(struct snd_soc_pcm_runtime *rtd), 1131 const struct snd_soc_ops *ops) 1132 { 1133 dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id); 1134 dai_links->id = (*be_id)++; 1135 dai_links->name = name; 1136 dai_links->platforms = platform_component; 1137 dai_links->num_platforms = ARRAY_SIZE(platform_component); 1138 dai_links->no_pcm = 1; 1139 dai_links->cpus = cpus; 1140 dai_links->num_cpus = cpus_num; 1141 dai_links->codecs = codecs; 1142 dai_links->num_codecs = codecs_num; 1143 dai_links->dpcm_playback = playback; 1144 dai_links->dpcm_capture = capture; 1145 dai_links->init = init; 1146 dai_links->ops = ops; 1147 } 1148 1149 static int init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 1150 int *be_id, char *name, int playback, int capture, 1151 const char *cpu_dai_name, 1152 const char *codec_name, const char *codec_dai_name, 1153 int (*init)(struct snd_soc_pcm_runtime *rtd), 1154 const struct snd_soc_ops *ops) 1155 { 1156 struct snd_soc_dai_link_component *dlc; 1157 1158 /* Allocate two DLCs one for the CPU, one for the CODEC */ 1159 dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL); 1160 if (!dlc || !name || !cpu_dai_name || !codec_name || !codec_dai_name) 1161 return -ENOMEM; 1162 1163 dlc[0].dai_name = cpu_dai_name; 1164 1165 dlc[1].name = codec_name; 1166 dlc[1].dai_name = codec_dai_name; 1167 1168 init_dai_link(dev, dai_links, be_id, name, playback, capture, 1169 &dlc[0], 1, &dlc[1], 1, init, ops); 1170 1171 return 0; 1172 } 1173 1174 static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, 1175 unsigned int sdw_version, 1176 unsigned int mfg_id, 1177 unsigned int part_id, 1178 unsigned int class_id, 1179 int index_in_link) 1180 { 1181 int i; 1182 1183 for (i = 0; i < adr_link->num_adr; i++) { 1184 unsigned int sdw1_version, mfg1_id, part1_id, class1_id; 1185 u64 adr; 1186 1187 /* skip itself */ 1188 if (i == index_in_link) 1189 continue; 1190 1191 adr = adr_link->adr_d[i].adr; 1192 1193 sdw1_version = SDW_VERSION(adr); 1194 mfg1_id = SDW_MFG_ID(adr); 1195 part1_id = SDW_PART_ID(adr); 1196 class1_id = SDW_CLASS_ID(adr); 1197 1198 if (sdw_version == sdw1_version && 1199 mfg_id == mfg1_id && 1200 part_id == part1_id && 1201 class_id == class1_id) 1202 return false; 1203 } 1204 1205 return true; 1206 } 1207 1208 static int fill_sdw_codec_dlc(struct device *dev, 1209 const struct snd_soc_acpi_link_adr *adr_link, 1210 struct snd_soc_dai_link_component *codec, 1211 int adr_index, int dai_index) 1212 { 1213 unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; 1214 u64 adr = adr_link->adr_d[adr_index].adr; 1215 int codec_index; 1216 1217 codec_index = find_codec_info_part(adr); 1218 if (codec_index < 0) 1219 return codec_index; 1220 1221 sdw_version = SDW_VERSION(adr); 1222 link_id = SDW_DISCO_LINK_ID(adr); 1223 unique_id = SDW_UNIQUE_ID(adr); 1224 mfg_id = SDW_MFG_ID(adr); 1225 part_id = SDW_PART_ID(adr); 1226 class_id = SDW_CLASS_ID(adr); 1227 1228 if (codec_info_list[codec_index].codec_name) 1229 codec->name = devm_kstrdup(dev, 1230 codec_info_list[codec_index].codec_name, 1231 GFP_KERNEL); 1232 else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, 1233 class_id, adr_index)) 1234 codec->name = devm_kasprintf(dev, GFP_KERNEL, 1235 "sdw:%01x:%04x:%04x:%02x", link_id, 1236 mfg_id, part_id, class_id); 1237 else 1238 codec->name = devm_kasprintf(dev, GFP_KERNEL, 1239 "sdw:%01x:%04x:%04x:%02x:%01x", link_id, 1240 mfg_id, part_id, class_id, unique_id); 1241 1242 if (!codec->name) 1243 return -ENOMEM; 1244 1245 codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name; 1246 1247 return 0; 1248 } 1249 1250 static int set_codec_init_func(struct snd_soc_card *card, 1251 const struct snd_soc_acpi_link_adr *adr_link, 1252 struct snd_soc_dai_link *dai_links, 1253 bool playback, int group_id, int adr_index, int dai_index) 1254 { 1255 int i = adr_index; 1256 1257 do { 1258 /* 1259 * Initialize the codec. If codec is part of an aggregated 1260 * group (group_id>0), initialize all codecs belonging to 1261 * same group. 1262 * The first link should start with adr_link->adr_d[adr_index] 1263 * because that is the device that we want to initialize and 1264 * we should end immediately if it is not aggregated (group_id=0) 1265 */ 1266 for ( ; i < adr_link->num_adr; i++) { 1267 int codec_index; 1268 1269 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1270 if (codec_index < 0) 1271 return codec_index; 1272 1273 /* The group_id is > 0 iff the codec is aggregated */ 1274 if (adr_link->adr_d[i].endpoints->group_id != group_id) 1275 continue; 1276 1277 if (codec_info_list[codec_index].dais[dai_index].init) 1278 codec_info_list[codec_index].dais[dai_index].init(card, 1279 adr_link, 1280 dai_links, 1281 &codec_info_list[codec_index], 1282 playback); 1283 if (!group_id) 1284 return 0; 1285 } 1286 1287 i = 0; 1288 adr_link++; 1289 } while (adr_link->mask); 1290 1291 return 0; 1292 } 1293 1294 /* 1295 * check endpoint status in slaves and gather link ID for all slaves in 1296 * the same group to generate different CPU DAI. Now only support 1297 * one sdw link with all slaves set with only single group id. 1298 * 1299 * one slave on one sdw link with aggregated = 0 1300 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 1301 * 1302 * two or more slaves on one sdw link with aggregated = 0 1303 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 1304 * 1305 * multiple links with multiple slaves with aggregated = 1 1306 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 1307 */ 1308 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 1309 struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 1310 int *codec_num, unsigned int *group_id, 1311 int adr_index) 1312 { 1313 bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1314 int i; 1315 1316 if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) { 1317 cpu_dai_id[0] = ffs(adr_link->mask) - 1; 1318 *cpu_dai_num = 1; 1319 *codec_num = 1; 1320 *group_id = 0; 1321 return 0; 1322 } 1323 1324 *codec_num = 0; 1325 *cpu_dai_num = 0; 1326 *group_id = adr_link->adr_d[adr_index].endpoints->group_id; 1327 1328 /* Count endpoints with the same group_id in the adr_link */ 1329 for (; adr_link && adr_link->num_adr; adr_link++) { 1330 unsigned int link_codecs = 0; 1331 1332 for (i = 0; i < adr_link->num_adr; i++) { 1333 if (adr_link->adr_d[i].endpoints->aggregated && 1334 adr_link->adr_d[i].endpoints->group_id == *group_id) 1335 link_codecs++; 1336 } 1337 1338 if (link_codecs) { 1339 *codec_num += link_codecs; 1340 1341 if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) { 1342 dev_err(dev, "cpu_dai_id array overflowed\n"); 1343 return -EINVAL; 1344 } 1345 1346 cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; 1347 } 1348 } 1349 1350 return 0; 1351 } 1352 1353 static void set_dailink_map(struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps, 1354 int codec_num, int cpu_num) 1355 { 1356 int step; 1357 int i; 1358 1359 step = codec_num / cpu_num; 1360 for (i = 0; i < codec_num; i++) 1361 sdw_codec_ch_maps[i].connected_cpu_id = i / step; 1362 } 1363 1364 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 1365 1366 static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, 1367 struct snd_soc_dai_link *dai_links, int sdw_be_num, 1368 const struct snd_soc_acpi_link_adr *adr_link, 1369 struct snd_soc_codec_conf *codec_conf, 1370 int codec_count, int *be_id, 1371 int *codec_conf_index, 1372 bool *ignore_pch_dmic, 1373 bool append_dai_type, 1374 int adr_index, 1375 int dai_index) 1376 { 1377 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1378 struct device *dev = card->dev; 1379 const struct snd_soc_acpi_link_adr *adr_link_next; 1380 struct snd_soc_dai_link_component *codecs; 1381 struct snd_soc_dai_link_component *cpus; 1382 struct sof_sdw_codec_info *codec_info; 1383 int cpu_dai_id[SDW_MAX_CPU_DAIS]; 1384 int cpu_dai_num; 1385 unsigned int group_id; 1386 int codec_dlc_index = 0; 1387 int codec_index; 1388 int codec_num; 1389 int stream; 1390 int i = 0; 1391 int j, k; 1392 int ret; 1393 1394 ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 1395 &group_id, adr_index); 1396 if (ret) 1397 return ret; 1398 1399 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 1400 if (!codecs) 1401 return -ENOMEM; 1402 1403 /* generate codec name on different links in the same group */ 1404 j = adr_index; 1405 for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && 1406 i < cpu_dai_num; adr_link_next++) { 1407 /* skip the link excluded by this processed group */ 1408 if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) 1409 continue; 1410 1411 /* j reset after loop, adr_index only applies to first link */ 1412 for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) { 1413 const struct snd_soc_acpi_endpoint *endpoints; 1414 1415 endpoints = adr_link_next->adr_d[j].endpoints; 1416 1417 if (group_id && (!endpoints->aggregated || 1418 endpoints->group_id != group_id)) 1419 continue; 1420 1421 /* sanity check */ 1422 if (*codec_conf_index >= codec_count) { 1423 dev_err(dev, "codec_conf array overflowed\n"); 1424 return -EINVAL; 1425 } 1426 1427 ret = fill_sdw_codec_dlc(dev, adr_link_next, 1428 &codecs[codec_dlc_index], 1429 j, dai_index); 1430 if (ret) 1431 return ret; 1432 1433 codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index]; 1434 codec_conf[*codec_conf_index].name_prefix = 1435 adr_link_next->adr_d[j].name_prefix; 1436 1437 codec_dlc_index++; 1438 (*codec_conf_index)++; 1439 } 1440 j = 0; 1441 1442 /* check next link to create codec dai in the processed group */ 1443 i++; 1444 } 1445 1446 /* find codec info to create BE DAI */ 1447 codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr); 1448 if (codec_index < 0) 1449 return codec_index; 1450 codec_info = &codec_info_list[codec_index]; 1451 1452 if (codec_info->ignore_pch_dmic) 1453 *ignore_pch_dmic = true; 1454 1455 for_each_pcm_streams(stream) { 1456 struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps; 1457 char *name, *cpu_name; 1458 int playback, capture; 1459 static const char * const sdw_stream_name[] = { 1460 "SDW%d-Playback", 1461 "SDW%d-Capture", 1462 "SDW%d-Playback-%s", 1463 "SDW%d-Capture-%s", 1464 }; 1465 1466 if (!codec_info->dais[dai_index].direction[stream]) 1467 continue; 1468 1469 *be_id = codec_info->dais[dai_index].dailink[stream]; 1470 if (*be_id < 0) { 1471 dev_err(dev, "Invalid dailink id %d\n", *be_id); 1472 return -EINVAL; 1473 } 1474 1475 sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, 1476 sizeof(*sdw_codec_ch_maps), GFP_KERNEL); 1477 if (!sdw_codec_ch_maps) 1478 return -ENOMEM; 1479 1480 /* create stream name according to first link id */ 1481 if (append_dai_type) { 1482 name = devm_kasprintf(dev, GFP_KERNEL, 1483 sdw_stream_name[stream + 2], cpu_dai_id[0], 1484 type_strings[codec_info->dais[dai_index].dai_type]); 1485 } else { 1486 name = devm_kasprintf(dev, GFP_KERNEL, 1487 sdw_stream_name[stream], cpu_dai_id[0]); 1488 } 1489 if (!name) 1490 return -ENOMEM; 1491 1492 cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL); 1493 if (!cpus) 1494 return -ENOMEM; 1495 1496 /* 1497 * generate CPU DAI name base on the sdw link ID and 1498 * PIN ID with offset of 2 according to sdw dai driver. 1499 */ 1500 for (k = 0; k < cpu_dai_num; k++) { 1501 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1502 "SDW%d Pin%d", cpu_dai_id[k], 1503 ctx->sdw_pin_index[cpu_dai_id[k]]++); 1504 if (!cpu_name) 1505 return -ENOMEM; 1506 1507 cpus[k].dai_name = cpu_name; 1508 } 1509 1510 /* 1511 * We create sdw dai links at first stage, so link index should 1512 * not be larger than sdw_be_num 1513 */ 1514 if (*link_index >= sdw_be_num) { 1515 dev_err(dev, "invalid dai link index %d\n", *link_index); 1516 return -EINVAL; 1517 } 1518 1519 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 1520 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 1521 1522 init_dai_link(dev, dai_links + *link_index, be_id, name, 1523 playback, capture, cpus, cpu_dai_num, codecs, codec_num, 1524 NULL, &sdw_ops); 1525 1526 /* 1527 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 1528 * based on wait_for_completion(), tag them as 'nonatomic'. 1529 */ 1530 dai_links[*link_index].nonatomic = true; 1531 1532 set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num); 1533 dai_links[*link_index].codec_ch_maps = sdw_codec_ch_maps; 1534 ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, 1535 playback, group_id, adr_index, dai_index); 1536 if (ret < 0) { 1537 dev_err(dev, "failed to init codec %d\n", codec_index); 1538 return ret; 1539 } 1540 } 1541 1542 return 0; 1543 } 1544 1545 static int sof_card_dai_links_create(struct snd_soc_card *card) 1546 { 1547 struct device *dev = card->dev; 1548 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 1549 int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, hdmi_num = 0, bt_num = 0; 1550 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1551 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1552 const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; 1553 bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); 1554 struct snd_soc_codec_conf *codec_conf; 1555 bool append_dai_type = false; 1556 bool ignore_pch_dmic = false; 1557 int codec_conf_num = 0; 1558 int codec_conf_index = 0; 1559 bool group_generated[SDW_MAX_GROUPS] = { }; 1560 int ssp_codec_index, ssp_mask; 1561 struct snd_soc_dai_link *dai_links; 1562 int num_links, link_index = 0; 1563 char *name, *cpu_dai_name; 1564 char *codec_name, *codec_dai_name; 1565 int i, j, be_id = 0; 1566 int codec_index; 1567 int ret; 1568 1569 ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); 1570 if (ret < 0) { 1571 dev_err(dev, "failed to get sdw link info %d\n", ret); 1572 return ret; 1573 } 1574 1575 /* 1576 * on generic tgl platform, I2S or sdw mode is supported 1577 * based on board rework. A ACPI device is registered in 1578 * system only when I2S mode is supported, not sdw mode. 1579 * Here check ACPI ID to confirm I2S is supported. 1580 */ 1581 ssp_codec_index = find_codec_info_acpi(mach->id); 1582 if (ssp_codec_index >= 0) { 1583 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1584 ssp_num = hweight_long(ssp_mask); 1585 } 1586 1587 if (mach_params->codec_mask & IDISP_CODEC_MASK) { 1588 ctx->hdmi.idisp_codec = true; 1589 1590 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1591 hdmi_num = SOF_TGL_HDMI_COUNT; 1592 else 1593 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1594 } 1595 1596 /* enable dmic01 & dmic16k */ 1597 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) 1598 dmic_num = 2; 1599 1600 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 1601 bt_num = 1; 1602 1603 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", 1604 sdw_be_num, ssp_num, dmic_num, hdmi_num, bt_num); 1605 1606 /* allocate BE dailinks */ 1607 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; 1608 dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 1609 if (!dai_links) 1610 return -ENOMEM; 1611 1612 /* allocate codec conf, will be populated when dailinks are created */ 1613 codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), 1614 GFP_KERNEL); 1615 if (!codec_conf) 1616 return -ENOMEM; 1617 1618 /* SDW */ 1619 if (!sdw_be_num) 1620 goto SSP; 1621 1622 for (i = 0; i < SDW_MAX_LINKS; i++) 1623 ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; 1624 1625 for (; adr_link->num_adr; adr_link++) { 1626 /* 1627 * If there are two or more different devices on the same sdw link, we have to 1628 * append the codec type to the dai link name to prevent duplicated dai link name. 1629 * The same type devices on the same sdw link will be in the same 1630 * snd_soc_acpi_adr_device array. They won't be described in different adr_links. 1631 */ 1632 for (i = 0; i < adr_link->num_adr; i++) { 1633 /* find codec info to get dai_num */ 1634 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1635 if (codec_index < 0) 1636 return codec_index; 1637 if (codec_info_list[codec_index].dai_num > 1) { 1638 append_dai_type = true; 1639 goto out; 1640 } 1641 for (j = 0; j < i; j++) { 1642 if ((SDW_PART_ID(adr_link->adr_d[i].adr) != 1643 SDW_PART_ID(adr_link->adr_d[j].adr)) || 1644 (SDW_MFG_ID(adr_link->adr_d[i].adr) != 1645 SDW_MFG_ID(adr_link->adr_d[j].adr))) { 1646 append_dai_type = true; 1647 goto out; 1648 } 1649 } 1650 } 1651 } 1652 out: 1653 1654 /* generate DAI links by each sdw link */ 1655 for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { 1656 for (i = 0; i < adr_link->num_adr; i++) { 1657 const struct snd_soc_acpi_endpoint *endpoint; 1658 1659 endpoint = adr_link->adr_d[i].endpoints; 1660 1661 /* this group has been generated */ 1662 if (endpoint->aggregated && 1663 group_generated[endpoint->group_id]) 1664 continue; 1665 1666 /* find codec info to get dai_num */ 1667 codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1668 if (codec_index < 0) 1669 return codec_index; 1670 1671 for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) { 1672 ret = create_sdw_dailink(card, &link_index, dai_links, 1673 sdw_be_num, adr_link, 1674 codec_conf, codec_conf_num, 1675 &be_id, &codec_conf_index, 1676 &ignore_pch_dmic, append_dai_type, i, j); 1677 if (ret < 0) { 1678 dev_err(dev, "failed to create dai link %d\n", link_index); 1679 return ret; 1680 } 1681 } 1682 1683 if (aggregation && endpoint->aggregated) 1684 group_generated[endpoint->group_id] = true; 1685 } 1686 } 1687 1688 SSP: 1689 /* SSP */ 1690 if (!ssp_num) 1691 goto DMIC; 1692 1693 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1694 struct sof_sdw_codec_info *info; 1695 int playback, capture; 1696 1697 if (!(ssp_mask & 0x1)) 1698 continue; 1699 1700 info = &codec_info_list[ssp_codec_index]; 1701 1702 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); 1703 cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1704 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1705 info->acpi_id, j++); 1706 1707 playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 1708 capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 1709 1710 ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1711 playback, capture, cpu_dai_name, 1712 codec_name, info->dais[0].dai_name, 1713 NULL, info->ops); 1714 if (ret) 1715 return ret; 1716 1717 ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0); 1718 if (ret < 0) 1719 return ret; 1720 1721 link_index++; 1722 } 1723 1724 DMIC: 1725 /* dmic */ 1726 if (dmic_num > 0) { 1727 if (ignore_pch_dmic) { 1728 dev_warn(dev, "Ignoring PCH DMIC\n"); 1729 goto HDMI; 1730 } 1731 1732 ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic01", 1733 0, 1, // DMIC only supports capture 1734 "DMIC01 Pin", "dmic-codec", "dmic-hifi", 1735 sof_sdw_dmic_init, NULL); 1736 if (ret) 1737 return ret; 1738 1739 link_index++; 1740 1741 ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic16k", 1742 0, 1, // DMIC only supports capture 1743 "DMIC16k Pin", "dmic-codec", "dmic-hifi", 1744 /* don't call sof_sdw_dmic_init() twice */ 1745 NULL, NULL); 1746 if (ret) 1747 return ret; 1748 1749 link_index++; 1750 } 1751 1752 HDMI: 1753 /* HDMI */ 1754 for (i = 0; i < hdmi_num; i++) { 1755 name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); 1756 cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); 1757 1758 if (ctx->hdmi.idisp_codec) { 1759 codec_name = "ehdaudio0D2"; 1760 codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, 1761 "intel-hdmi-hifi%d", i + 1); 1762 } else { 1763 codec_name = "snd-soc-dummy"; 1764 codec_dai_name = "snd-soc-dummy-dai"; 1765 } 1766 1767 ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1768 1, 0, // HDMI only supports playback 1769 cpu_dai_name, codec_name, codec_dai_name, 1770 i == 0 ? sof_sdw_hdmi_init : NULL, NULL); 1771 if (ret) 1772 return ret; 1773 1774 link_index++; 1775 } 1776 1777 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1778 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1779 SOF_BT_OFFLOAD_SSP_SHIFT; 1780 1781 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1782 cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1783 1784 ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1785 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, 1786 snd_soc_dummy_dlc.dai_name, NULL, NULL); 1787 if (ret) 1788 return ret; 1789 } 1790 1791 card->dai_link = dai_links; 1792 card->num_links = num_links; 1793 1794 card->codec_conf = codec_conf; 1795 card->num_configs = codec_conf_num; 1796 1797 return 0; 1798 } 1799 1800 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1801 { 1802 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1803 int ret = 0; 1804 int i; 1805 1806 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1807 if (codec_info_list[i].codec_card_late_probe) { 1808 ret = codec_info_list[i].codec_card_late_probe(card); 1809 1810 if (ret < 0) 1811 return ret; 1812 } 1813 } 1814 1815 if (ctx->hdmi.idisp_codec) 1816 ret = sof_sdw_hdmi_card_late_probe(card); 1817 1818 return ret; 1819 } 1820 1821 /* SoC card */ 1822 static const char sdw_card_long_name[] = "Intel Soundwire SOF"; 1823 1824 static struct snd_soc_card card_sof_sdw = { 1825 .name = "soundwire", 1826 .owner = THIS_MODULE, 1827 .late_probe = sof_sdw_card_late_probe, 1828 }; 1829 1830 /* helper to get the link that the codec DAI is used */ 1831 static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card, 1832 const char *dai_name) 1833 { 1834 struct snd_soc_dai_link *dai_link; 1835 int i; 1836 int j; 1837 1838 for_each_card_prelinks(card, i, dai_link) { 1839 for (j = 0; j < dai_link->num_codecs; j++) { 1840 /* Check each codec in a link */ 1841 if (!strcmp(dai_link->codecs[j].dai_name, dai_name)) 1842 return dai_link; 1843 } 1844 } 1845 return NULL; 1846 } 1847 1848 static void mc_dailink_exit_loop(struct snd_soc_card *card) 1849 { 1850 struct snd_soc_dai_link *dai_link; 1851 int ret; 1852 int i, j; 1853 1854 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1855 for (j = 0; j < codec_info_list[i].dai_num; j++) { 1856 /* Check each dai in codec_info_lis to see if it is used in the link */ 1857 if (!codec_info_list[i].dais[j].exit) 1858 continue; 1859 /* 1860 * We don't need to call .exit function if there is no matched 1861 * dai link found. 1862 */ 1863 dai_link = mc_find_codec_dai_used(card, 1864 codec_info_list[i].dais[j].dai_name); 1865 if (dai_link) { 1866 /* Do the .exit function if the codec dai is used in the link */ 1867 ret = codec_info_list[i].dais[j].exit(card, dai_link); 1868 if (ret) 1869 dev_warn(card->dev, 1870 "codec exit failed %d\n", 1871 ret); 1872 break; 1873 } 1874 } 1875 } 1876 } 1877 1878 static int mc_probe(struct platform_device *pdev) 1879 { 1880 struct snd_soc_card *card = &card_sof_sdw; 1881 struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); 1882 struct mc_private *ctx; 1883 int amp_num = 0, i; 1884 int ret; 1885 1886 card->dev = &pdev->dev; 1887 1888 dev_dbg(card->dev, "Entry\n"); 1889 1890 ctx = devm_kzalloc(card->dev, sizeof(*ctx), GFP_KERNEL); 1891 if (!ctx) 1892 return -ENOMEM; 1893 1894 snd_soc_card_set_drvdata(card, ctx); 1895 1896 dmi_check_system(sof_sdw_quirk_table); 1897 1898 if (quirk_override != -1) { 1899 dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", 1900 sof_sdw_quirk, quirk_override); 1901 sof_sdw_quirk = quirk_override; 1902 } 1903 1904 log_quirks(card->dev); 1905 1906 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 1907 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1908 codec_info_list[i].amp_num = 0; 1909 1910 if (mach->mach_params.subsystem_id_set) { 1911 snd_soc_card_set_pci_ssid(card, 1912 mach->mach_params.subsystem_vendor, 1913 mach->mach_params.subsystem_device); 1914 } 1915 1916 ret = sof_card_dai_links_create(card); 1917 if (ret < 0) 1918 return ret; 1919 1920 /* 1921 * the default amp_num is zero for each codec and 1922 * amp_num will only be increased for active amp 1923 * codecs on used platform 1924 */ 1925 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1926 amp_num += codec_info_list[i].amp_num; 1927 1928 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1929 "cfg-spk:%d cfg-amp:%d", 1930 (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 1931 ? 4 : 2, amp_num); 1932 if (!card->components) 1933 return -ENOMEM; 1934 1935 if (mach->mach_params.dmic_num) { 1936 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1937 "%s mic:dmic cfg-mics:%d", 1938 card->components, 1939 mach->mach_params.dmic_num); 1940 if (!card->components) 1941 return -ENOMEM; 1942 } 1943 1944 card->long_name = sdw_card_long_name; 1945 1946 /* Register the card */ 1947 ret = devm_snd_soc_register_card(card->dev, card); 1948 if (ret) { 1949 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); 1950 mc_dailink_exit_loop(card); 1951 return ret; 1952 } 1953 1954 platform_set_drvdata(pdev, card); 1955 1956 return ret; 1957 } 1958 1959 static void mc_remove(struct platform_device *pdev) 1960 { 1961 struct snd_soc_card *card = platform_get_drvdata(pdev); 1962 1963 mc_dailink_exit_loop(card); 1964 } 1965 1966 static const struct platform_device_id mc_id_table[] = { 1967 { "sof_sdw", }, 1968 {} 1969 }; 1970 MODULE_DEVICE_TABLE(platform, mc_id_table); 1971 1972 static struct platform_driver sof_sdw_driver = { 1973 .driver = { 1974 .name = "sof_sdw", 1975 .pm = &snd_soc_pm_ops, 1976 }, 1977 .probe = mc_probe, 1978 .remove_new = mc_remove, 1979 .id_table = mc_id_table, 1980 }; 1981 1982 module_platform_driver(sof_sdw_driver); 1983 1984 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1985 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1986 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1987 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1988 MODULE_LICENSE("GPL v2"); 1989 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 1990 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 1991