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