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 17 unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1; 18 static int quirk_override = -1; 19 module_param_named(quirk, quirk_override, int, 0444); 20 MODULE_PARM_DESC(quirk, "Board-specific quirk override"); 21 22 #define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0) 23 24 static void log_quirks(struct device *dev) 25 { 26 if (SOF_RT711_JDSRC(sof_sdw_quirk)) 27 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", 28 SOF_RT711_JDSRC(sof_sdw_quirk)); 29 if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 30 dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); 31 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 32 dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); 33 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) 34 dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); 35 if (SOF_SSP_GET_PORT(sof_sdw_quirk)) 36 dev_dbg(dev, "SSP port %ld\n", 37 SOF_SSP_GET_PORT(sof_sdw_quirk)); 38 if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) 39 dev_dbg(dev, "quirk SOF_RT715_DAI_ID_FIX enabled\n"); 40 if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) 41 dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); 42 } 43 44 static int sof_sdw_quirk_cb(const struct dmi_system_id *id) 45 { 46 sof_sdw_quirk = (unsigned long)id->driver_data; 47 return 1; 48 } 49 50 static const struct dmi_system_id sof_sdw_quirk_table[] = { 51 /* CometLake devices */ 52 { 53 .callback = sof_sdw_quirk_cb, 54 .matches = { 55 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 56 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), 57 }, 58 .driver_data = (void *)SOF_SDW_PCH_DMIC, 59 }, 60 { 61 .callback = sof_sdw_quirk_cb, 62 .matches = { 63 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 64 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 65 }, 66 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | 67 SOF_RT715_DAI_ID_FIX), 68 }, 69 { 70 /* early version of SKU 09C6 */ 71 .callback = sof_sdw_quirk_cb, 72 .matches = { 73 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 74 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 75 }, 76 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | 77 SOF_RT715_DAI_ID_FIX), 78 }, 79 { 80 .callback = sof_sdw_quirk_cb, 81 .matches = { 82 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 83 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 84 }, 85 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | 86 SOF_RT715_DAI_ID_FIX | 87 SOF_SDW_FOUR_SPK), 88 }, 89 { 90 .callback = sof_sdw_quirk_cb, 91 .matches = { 92 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 93 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 94 }, 95 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | 96 SOF_RT715_DAI_ID_FIX | 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 SOF_RT711_JD_SRC_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 SOF_RT711_JD_SRC_JD2 | 129 SOF_RT715_DAI_ID_FIX), 130 }, 131 { 132 .callback = sof_sdw_quirk_cb, 133 .matches = { 134 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 135 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") 136 }, 137 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 138 SOF_RT711_JD_SRC_JD2 | 139 SOF_RT715_DAI_ID_FIX | 140 SOF_SDW_FOUR_SPK), 141 }, 142 { 143 .callback = sof_sdw_quirk_cb, 144 .matches = { 145 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 146 DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), 147 }, 148 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 149 SOF_SDW_PCH_DMIC | 150 SOF_SDW_FOUR_SPK | 151 SOF_BT_OFFLOAD_SSP(2) | 152 SOF_SSP_BT_OFFLOAD_PRESENT), 153 }, 154 { 155 .callback = sof_sdw_quirk_cb, 156 .matches = { 157 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 158 DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), 159 }, 160 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 161 SOF_SDW_PCH_DMIC | 162 SOF_SDW_FOUR_SPK), 163 }, 164 { 165 /* 166 * this entry covers multiple HP SKUs. The family name 167 * does not seem robust enough, so we use a partial 168 * match that ignores the product name suffix 169 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) 170 */ 171 .callback = sof_sdw_quirk_cb, 172 .matches = { 173 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 174 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"), 175 }, 176 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 177 SOF_SDW_PCH_DMIC | 178 SOF_RT711_JD_SRC_JD2), 179 }, 180 /* TigerLake-SDCA devices */ 181 { 182 .callback = sof_sdw_quirk_cb, 183 .matches = { 184 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 185 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") 186 }, 187 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 188 SOF_RT711_JD_SRC_JD2 | 189 SOF_RT715_DAI_ID_FIX | 190 SOF_SDW_FOUR_SPK), 191 }, 192 /* AlderLake devices */ 193 { 194 .callback = sof_sdw_quirk_cb, 195 .matches = { 196 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 197 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), 198 }, 199 .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | 200 SOF_SDW_TGL_HDMI | 201 SOF_RT715_DAI_ID_FIX | 202 SOF_SDW_PCH_DMIC | 203 SOF_BT_OFFLOAD_SSP(2) | 204 SOF_SSP_BT_OFFLOAD_PRESENT), 205 }, 206 { 207 .callback = sof_sdw_quirk_cb, 208 .matches = { 209 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 210 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), 211 }, 212 .driver_data = (void *)(SOF_SDW_TGL_HDMI | 213 SOF_SDW_PCH_DMIC | 214 SOF_SDW_FOUR_SPK | 215 SOF_BT_OFFLOAD_SSP(2) | 216 SOF_SSP_BT_OFFLOAD_PRESENT), 217 }, 218 {} 219 }; 220 221 static struct snd_soc_dai_link_component dmic_component[] = { 222 { 223 .name = "dmic-codec", 224 .dai_name = "dmic-hifi", 225 } 226 }; 227 228 static struct snd_soc_dai_link_component platform_component[] = { 229 { 230 /* name might be overridden during probe */ 231 .name = "0000:00:1f.3" 232 } 233 }; 234 235 /* these wrappers are only needed to avoid typecast compilation errors */ 236 int sdw_startup(struct snd_pcm_substream *substream) 237 { 238 return sdw_startup_stream(substream); 239 } 240 241 int sdw_prepare(struct snd_pcm_substream *substream) 242 { 243 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 244 struct sdw_stream_runtime *sdw_stream; 245 struct snd_soc_dai *dai; 246 247 /* Find stream from first CPU DAI */ 248 dai = asoc_rtd_to_cpu(rtd, 0); 249 250 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); 251 252 if (IS_ERR(sdw_stream)) { 253 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 254 return PTR_ERR(sdw_stream); 255 } 256 257 return sdw_prepare_stream(sdw_stream); 258 } 259 260 int sdw_trigger(struct snd_pcm_substream *substream, int cmd) 261 { 262 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 263 struct sdw_stream_runtime *sdw_stream; 264 struct snd_soc_dai *dai; 265 int ret; 266 267 /* Find stream from first CPU DAI */ 268 dai = asoc_rtd_to_cpu(rtd, 0); 269 270 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); 271 272 if (IS_ERR(sdw_stream)) { 273 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 274 return PTR_ERR(sdw_stream); 275 } 276 277 switch (cmd) { 278 case SNDRV_PCM_TRIGGER_START: 279 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 280 case SNDRV_PCM_TRIGGER_RESUME: 281 ret = sdw_enable_stream(sdw_stream); 282 break; 283 284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 285 case SNDRV_PCM_TRIGGER_SUSPEND: 286 case SNDRV_PCM_TRIGGER_STOP: 287 ret = sdw_disable_stream(sdw_stream); 288 break; 289 default: 290 ret = -EINVAL; 291 break; 292 } 293 294 if (ret) 295 dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret); 296 297 return ret; 298 } 299 300 int sdw_hw_free(struct snd_pcm_substream *substream) 301 { 302 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 303 struct sdw_stream_runtime *sdw_stream; 304 struct snd_soc_dai *dai; 305 306 /* Find stream from first CPU DAI */ 307 dai = asoc_rtd_to_cpu(rtd, 0); 308 309 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream); 310 311 if (IS_ERR(sdw_stream)) { 312 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); 313 return PTR_ERR(sdw_stream); 314 } 315 316 return sdw_deprepare_stream(sdw_stream); 317 } 318 319 void sdw_shutdown(struct snd_pcm_substream *substream) 320 { 321 sdw_shutdown_stream(substream); 322 } 323 324 static const struct snd_soc_ops sdw_ops = { 325 .startup = sdw_startup, 326 .prepare = sdw_prepare, 327 .trigger = sdw_trigger, 328 .hw_free = sdw_hw_free, 329 .shutdown = sdw_shutdown, 330 }; 331 332 static struct sof_sdw_codec_info codec_info_list[] = { 333 { 334 .part_id = 0x700, 335 .direction = {true, true}, 336 .dai_name = "rt700-aif1", 337 .init = sof_sdw_rt700_init, 338 }, 339 { 340 .part_id = 0x711, 341 .version_id = 3, 342 .direction = {true, true}, 343 .dai_name = "rt711-sdca-aif1", 344 .init = sof_sdw_rt711_sdca_init, 345 .exit = sof_sdw_rt711_sdca_exit, 346 }, 347 { 348 .part_id = 0x711, 349 .version_id = 2, 350 .direction = {true, true}, 351 .dai_name = "rt711-aif1", 352 .init = sof_sdw_rt711_init, 353 .exit = sof_sdw_rt711_exit, 354 }, 355 { 356 .part_id = 0x1308, 357 .acpi_id = "10EC1308", 358 .direction = {true, false}, 359 .dai_name = "rt1308-aif", 360 .ops = &sof_sdw_rt1308_i2s_ops, 361 .init = sof_sdw_rt1308_init, 362 }, 363 { 364 .part_id = 0x1316, 365 .direction = {true, true}, 366 .dai_name = "rt1316-aif", 367 .init = sof_sdw_rt1316_init, 368 }, 369 { 370 .part_id = 0x714, 371 .version_id = 3, 372 .direction = {false, true}, 373 .ignore_pch_dmic = true, 374 .dai_name = "rt715-aif2", 375 .init = sof_sdw_rt715_sdca_init, 376 }, 377 { 378 .part_id = 0x715, 379 .version_id = 3, 380 .direction = {false, true}, 381 .ignore_pch_dmic = true, 382 .dai_name = "rt715-aif2", 383 .init = sof_sdw_rt715_sdca_init, 384 }, 385 { 386 .part_id = 0x714, 387 .version_id = 2, 388 .direction = {false, true}, 389 .ignore_pch_dmic = true, 390 .dai_name = "rt715-aif2", 391 .init = sof_sdw_rt715_init, 392 }, 393 { 394 .part_id = 0x715, 395 .version_id = 2, 396 .direction = {false, true}, 397 .ignore_pch_dmic = true, 398 .dai_name = "rt715-aif2", 399 .init = sof_sdw_rt715_init, 400 }, 401 { 402 .part_id = 0x8373, 403 .direction = {true, true}, 404 .dai_name = "max98373-aif1", 405 .init = sof_sdw_mx8373_init, 406 .codec_card_late_probe = sof_sdw_mx8373_late_probe, 407 }, 408 { 409 .part_id = 0x5682, 410 .direction = {true, true}, 411 .dai_name = "rt5682-sdw", 412 .init = sof_sdw_rt5682_init, 413 }, 414 }; 415 416 static inline int find_codec_info_part(u64 adr) 417 { 418 unsigned int part_id, sdw_version; 419 int i; 420 421 part_id = SDW_PART_ID(adr); 422 sdw_version = SDW_VERSION(adr); 423 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 424 /* 425 * A codec info is for all sdw version with the part id if 426 * version_id is not specified in the codec info. 427 */ 428 if (part_id == codec_info_list[i].part_id && 429 (!codec_info_list[i].version_id || 430 sdw_version == codec_info_list[i].version_id)) 431 return i; 432 433 return -EINVAL; 434 435 } 436 437 static inline int find_codec_info_acpi(const u8 *acpi_id) 438 { 439 int i; 440 441 if (!acpi_id[0]) 442 return -EINVAL; 443 444 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 445 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, 446 ACPI_ID_LEN)) 447 break; 448 449 if (i == ARRAY_SIZE(codec_info_list)) 450 return -EINVAL; 451 452 return i; 453 } 454 455 /* 456 * get BE dailink number and CPU DAI number based on sdw link adr. 457 * Since some sdw slaves may be aggregated, the CPU DAI number 458 * may be larger than the number of BE dailinks. 459 */ 460 static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, 461 int *sdw_be_num, int *sdw_cpu_dai_num) 462 { 463 const struct snd_soc_acpi_link_adr *link; 464 bool group_visited[SDW_MAX_GROUPS]; 465 bool no_aggregation; 466 int i; 467 468 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 469 *sdw_cpu_dai_num = 0; 470 *sdw_be_num = 0; 471 472 if (!links) 473 return -EINVAL; 474 475 for (i = 0; i < SDW_MAX_GROUPS; i++) 476 group_visited[i] = false; 477 478 for (link = links; link->num_adr; link++) { 479 const struct snd_soc_acpi_endpoint *endpoint; 480 int codec_index; 481 int stream; 482 u64 adr; 483 484 adr = link->adr_d->adr; 485 codec_index = find_codec_info_part(adr); 486 if (codec_index < 0) 487 return codec_index; 488 489 endpoint = link->adr_d->endpoints; 490 491 /* count DAI number for playback and capture */ 492 for_each_pcm_streams(stream) { 493 if (!codec_info_list[codec_index].direction[stream]) 494 continue; 495 496 (*sdw_cpu_dai_num)++; 497 498 /* count BE for each non-aggregated slave or group */ 499 if (!endpoint->aggregated || no_aggregation || 500 !group_visited[endpoint->group_id]) 501 (*sdw_be_num)++; 502 } 503 504 if (endpoint->aggregated) 505 group_visited[endpoint->group_id] = true; 506 } 507 508 return 0; 509 } 510 511 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, 512 int be_id, char *name, int playback, int capture, 513 struct snd_soc_dai_link_component *cpus, int cpus_num, 514 struct snd_soc_dai_link_component *codecs, int codecs_num, 515 int (*init)(struct snd_soc_pcm_runtime *rtd), 516 const struct snd_soc_ops *ops) 517 { 518 dev_dbg(dev, "create dai link %s, id %d\n", name, be_id); 519 dai_links->id = be_id; 520 dai_links->name = name; 521 dai_links->platforms = platform_component; 522 dai_links->num_platforms = ARRAY_SIZE(platform_component); 523 dai_links->no_pcm = 1; 524 dai_links->cpus = cpus; 525 dai_links->num_cpus = cpus_num; 526 dai_links->codecs = codecs; 527 dai_links->num_codecs = codecs_num; 528 dai_links->dpcm_playback = playback; 529 dai_links->dpcm_capture = capture; 530 dai_links->init = init; 531 dai_links->ops = ops; 532 } 533 534 static bool is_unique_device(const struct snd_soc_acpi_link_adr *link, 535 unsigned int sdw_version, 536 unsigned int mfg_id, 537 unsigned int part_id, 538 unsigned int class_id, 539 int index_in_link 540 ) 541 { 542 int i; 543 544 for (i = 0; i < link->num_adr; i++) { 545 unsigned int sdw1_version, mfg1_id, part1_id, class1_id; 546 u64 adr; 547 548 /* skip itself */ 549 if (i == index_in_link) 550 continue; 551 552 adr = link->adr_d[i].adr; 553 554 sdw1_version = SDW_VERSION(adr); 555 mfg1_id = SDW_MFG_ID(adr); 556 part1_id = SDW_PART_ID(adr); 557 class1_id = SDW_CLASS_ID(adr); 558 559 if (sdw_version == sdw1_version && 560 mfg_id == mfg1_id && 561 part_id == part1_id && 562 class_id == class1_id) 563 return false; 564 } 565 566 return true; 567 } 568 569 static int create_codec_dai_name(struct device *dev, 570 const struct snd_soc_acpi_link_adr *link, 571 struct snd_soc_dai_link_component *codec, 572 int offset, 573 struct snd_soc_codec_conf *codec_conf, 574 int codec_count, 575 int *codec_conf_index) 576 { 577 int i; 578 579 /* sanity check */ 580 if (*codec_conf_index + link->num_adr > codec_count) { 581 dev_err(dev, "codec_conf: out-of-bounds access requested\n"); 582 return -EINVAL; 583 } 584 585 for (i = 0; i < link->num_adr; i++) { 586 unsigned int sdw_version, unique_id, mfg_id; 587 unsigned int link_id, part_id, class_id; 588 int codec_index, comp_index; 589 char *codec_str; 590 u64 adr; 591 592 adr = link->adr_d[i].adr; 593 594 sdw_version = SDW_VERSION(adr); 595 link_id = SDW_DISCO_LINK_ID(adr); 596 unique_id = SDW_UNIQUE_ID(adr); 597 mfg_id = SDW_MFG_ID(adr); 598 part_id = SDW_PART_ID(adr); 599 class_id = SDW_CLASS_ID(adr); 600 601 comp_index = i + offset; 602 if (is_unique_device(link, sdw_version, mfg_id, part_id, 603 class_id, i)) { 604 codec_str = "sdw:%x:%x:%x:%x"; 605 codec[comp_index].name = 606 devm_kasprintf(dev, GFP_KERNEL, codec_str, 607 link_id, mfg_id, part_id, 608 class_id); 609 } else { 610 codec_str = "sdw:%x:%x:%x:%x:%x"; 611 codec[comp_index].name = 612 devm_kasprintf(dev, GFP_KERNEL, codec_str, 613 link_id, mfg_id, part_id, 614 class_id, unique_id); 615 } 616 617 if (!codec[comp_index].name) 618 return -ENOMEM; 619 620 codec_index = find_codec_info_part(adr); 621 if (codec_index < 0) 622 return codec_index; 623 624 codec[comp_index].dai_name = 625 codec_info_list[codec_index].dai_name; 626 627 codec_conf[*codec_conf_index].dlc = codec[comp_index]; 628 codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix; 629 630 ++*codec_conf_index; 631 } 632 633 return 0; 634 } 635 636 static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, 637 struct snd_soc_dai_link *dai_links, 638 bool playback, int group_id) 639 { 640 int i; 641 642 do { 643 /* 644 * Initialize the codec. If codec is part of an aggregated 645 * group (group_id>0), initialize all codecs belonging to 646 * same group. 647 */ 648 for (i = 0; i < link->num_adr; i++) { 649 int codec_index; 650 651 codec_index = find_codec_info_part(link->adr_d[i].adr); 652 653 if (codec_index < 0) 654 return codec_index; 655 /* The group_id is > 0 iff the codec is aggregated */ 656 if (link->adr_d[i].endpoints->group_id != group_id) 657 continue; 658 if (codec_info_list[codec_index].init) 659 codec_info_list[codec_index].init(link, 660 dai_links, 661 &codec_info_list[codec_index], 662 playback); 663 } 664 link++; 665 } while (link->mask && group_id); 666 667 return 0; 668 } 669 670 /* 671 * check endpoint status in slaves and gather link ID for all slaves in 672 * the same group to generate different CPU DAI. Now only support 673 * one sdw link with all slaves set with only single group id. 674 * 675 * one slave on one sdw link with aggregated = 0 676 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 677 * 678 * two or more slaves on one sdw link with aggregated = 0 679 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 680 * 681 * multiple links with multiple slaves with aggregated = 1 682 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 683 */ 684 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 685 struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 686 int *codec_num, int *group_id, 687 bool *group_generated) 688 { 689 const struct snd_soc_acpi_adr_device *adr_d; 690 const struct snd_soc_acpi_link_adr *adr_next; 691 bool no_aggregation; 692 int index = 0; 693 694 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 695 *codec_num = adr_link->num_adr; 696 adr_d = adr_link->adr_d; 697 698 /* make sure the link mask has a single bit set */ 699 if (!is_power_of_2(adr_link->mask)) 700 return -EINVAL; 701 702 cpu_dai_id[index++] = ffs(adr_link->mask) - 1; 703 if (!adr_d->endpoints->aggregated || no_aggregation) { 704 *cpu_dai_num = 1; 705 *group_id = 0; 706 return 0; 707 } 708 709 *group_id = adr_d->endpoints->group_id; 710 711 /* gather other link ID of slaves in the same group */ 712 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; 713 adr_next++) { 714 const struct snd_soc_acpi_endpoint *endpoint; 715 716 endpoint = adr_next->adr_d->endpoints; 717 if (!endpoint->aggregated || 718 endpoint->group_id != *group_id) 719 continue; 720 721 /* make sure the link mask has a single bit set */ 722 if (!is_power_of_2(adr_next->mask)) 723 return -EINVAL; 724 725 if (index >= SDW_MAX_CPU_DAIS) { 726 dev_err(dev, " cpu_dai_id array overflows"); 727 return -EINVAL; 728 } 729 730 cpu_dai_id[index++] = ffs(adr_next->mask) - 1; 731 *codec_num += adr_next->num_adr; 732 } 733 734 /* 735 * indicate CPU DAIs for this group have been generated 736 * to avoid generating CPU DAIs for this group again. 737 */ 738 group_generated[*group_id] = true; 739 *cpu_dai_num = index; 740 741 return 0; 742 } 743 744 static int create_sdw_dailink(struct device *dev, int *be_index, 745 struct snd_soc_dai_link *dai_links, 746 int sdw_be_num, int sdw_cpu_dai_num, 747 struct snd_soc_dai_link_component *cpus, 748 const struct snd_soc_acpi_link_adr *link, 749 int *cpu_id, bool *group_generated, 750 struct snd_soc_codec_conf *codec_conf, 751 int codec_count, 752 int *codec_conf_index, 753 bool *ignore_pch_dmic) 754 { 755 const struct snd_soc_acpi_link_adr *link_next; 756 struct snd_soc_dai_link_component *codecs; 757 int cpu_dai_id[SDW_MAX_CPU_DAIS]; 758 int cpu_dai_num, cpu_dai_index; 759 unsigned int group_id; 760 int codec_idx = 0; 761 int i = 0, j = 0; 762 int codec_index; 763 int codec_num; 764 int stream; 765 int ret; 766 int k; 767 768 ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 769 &group_id, group_generated); 770 if (ret) 771 return ret; 772 773 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 774 if (!codecs) 775 return -ENOMEM; 776 777 /* generate codec name on different links in the same group */ 778 for (link_next = link; link_next && link_next->num_adr && 779 i < cpu_dai_num; link_next++) { 780 const struct snd_soc_acpi_endpoint *endpoints; 781 782 endpoints = link_next->adr_d->endpoints; 783 if (group_id && (!endpoints->aggregated || 784 endpoints->group_id != group_id)) 785 continue; 786 787 /* skip the link excluded by this processed group */ 788 if (cpu_dai_id[i] != ffs(link_next->mask) - 1) 789 continue; 790 791 ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, 792 codec_conf, codec_count, codec_conf_index); 793 if (ret < 0) 794 return ret; 795 796 /* check next link to create codec dai in the processed group */ 797 i++; 798 codec_idx += link_next->num_adr; 799 } 800 801 /* find codec info to create BE DAI */ 802 codec_index = find_codec_info_part(link->adr_d[0].adr); 803 if (codec_index < 0) 804 return codec_index; 805 806 if (codec_info_list[codec_index].ignore_pch_dmic) 807 *ignore_pch_dmic = true; 808 809 cpu_dai_index = *cpu_id; 810 for_each_pcm_streams(stream) { 811 char *name, *cpu_name; 812 int playback, capture; 813 static const char * const sdw_stream_name[] = { 814 "SDW%d-Playback", 815 "SDW%d-Capture", 816 }; 817 818 if (!codec_info_list[codec_index].direction[stream]) 819 continue; 820 821 /* create stream name according to first link id */ 822 name = devm_kasprintf(dev, GFP_KERNEL, 823 sdw_stream_name[stream], cpu_dai_id[0]); 824 if (!name) 825 return -ENOMEM; 826 827 /* 828 * generate CPU DAI name base on the sdw link ID and 829 * PIN ID with offset of 2 according to sdw dai driver. 830 */ 831 for (k = 0; k < cpu_dai_num; k++) { 832 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 833 "SDW%d Pin%d", cpu_dai_id[k], 834 j + SDW_INTEL_BIDIR_PDI_BASE); 835 if (!cpu_name) 836 return -ENOMEM; 837 838 if (cpu_dai_index >= sdw_cpu_dai_num) { 839 dev_err(dev, "invalid cpu dai index %d", 840 cpu_dai_index); 841 return -EINVAL; 842 } 843 844 cpus[cpu_dai_index++].dai_name = cpu_name; 845 } 846 847 if (*be_index >= sdw_be_num) { 848 dev_err(dev, " invalid be dai index %d", *be_index); 849 return -EINVAL; 850 } 851 852 if (*cpu_id >= sdw_cpu_dai_num) { 853 dev_err(dev, " invalid cpu dai index %d", *cpu_id); 854 return -EINVAL; 855 } 856 857 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 858 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 859 init_dai_link(dev, dai_links + *be_index, *be_index, name, 860 playback, capture, 861 cpus + *cpu_id, cpu_dai_num, 862 codecs, codec_num, 863 NULL, &sdw_ops); 864 865 ret = set_codec_init_func(link, dai_links + (*be_index)++, 866 playback, group_id); 867 if (ret < 0) { 868 dev_err(dev, "failed to init codec %d", codec_index); 869 return ret; 870 } 871 872 *cpu_id += cpu_dai_num; 873 j++; 874 } 875 876 return 0; 877 } 878 879 /* 880 * DAI link ID of SSP & DMIC & HDMI are based on last 881 * link ID used by sdw link. Since be_id may be changed 882 * in init func of sdw codec, it is not equal to be_id 883 */ 884 static inline int get_next_be_id(struct snd_soc_dai_link *links, 885 int be_id) 886 { 887 return links[be_id - 1].id + 1; 888 } 889 890 #define IDISP_CODEC_MASK 0x4 891 892 static int sof_card_codec_conf_alloc(struct device *dev, 893 struct snd_soc_acpi_mach_params *mach_params, 894 struct snd_soc_codec_conf **codec_conf, 895 int *codec_conf_count) 896 { 897 const struct snd_soc_acpi_link_adr *adr_link; 898 struct snd_soc_codec_conf *c_conf; 899 int num_codecs = 0; 900 int i; 901 902 adr_link = mach_params->links; 903 if (!adr_link) 904 return -EINVAL; 905 906 /* generate DAI links by each sdw link */ 907 for (; adr_link->num_adr; adr_link++) { 908 for (i = 0; i < adr_link->num_adr; i++) { 909 if (!adr_link->adr_d[i].name_prefix) { 910 dev_err(dev, "codec 0x%llx does not have a name prefix\n", 911 adr_link->adr_d[i].adr); 912 return -EINVAL; 913 } 914 } 915 num_codecs += adr_link->num_adr; 916 } 917 918 c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL); 919 if (!c_conf) 920 return -ENOMEM; 921 922 *codec_conf = c_conf; 923 *codec_conf_count = num_codecs; 924 925 return 0; 926 } 927 928 static int sof_card_dai_links_create(struct device *dev, 929 struct snd_soc_acpi_mach *mach, 930 struct snd_soc_card *card) 931 { 932 int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; 933 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 934 struct snd_soc_dai_link_component *idisp_components; 935 struct snd_soc_dai_link_component *ssp_components; 936 struct snd_soc_acpi_mach_params *mach_params; 937 const struct snd_soc_acpi_link_adr *adr_link; 938 struct snd_soc_dai_link_component *cpus; 939 struct snd_soc_codec_conf *codec_conf; 940 bool ignore_pch_dmic = false; 941 int codec_conf_count; 942 int codec_conf_index = 0; 943 bool group_generated[SDW_MAX_GROUPS]; 944 int ssp_codec_index, ssp_mask; 945 struct snd_soc_dai_link *links; 946 int num_links, link_id = 0; 947 char *name, *cpu_name; 948 int total_cpu_dai_num; 949 int sdw_cpu_dai_num; 950 int i, j, be_id = 0; 951 int cpu_id = 0; 952 int comp_num; 953 int ret; 954 955 mach_params = &mach->mach_params; 956 957 /* allocate codec conf, will be populated when dailinks are created */ 958 ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count); 959 if (ret < 0) 960 return ret; 961 962 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 963 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 964 codec_info_list[i].amp_num = 0; 965 966 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 967 hdmi_num = SOF_TGL_HDMI_COUNT; 968 else 969 hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 970 971 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 972 /* 973 * on generic tgl platform, I2S or sdw mode is supported 974 * based on board rework. A ACPI device is registered in 975 * system only when I2S mode is supported, not sdw mode. 976 * Here check ACPI ID to confirm I2S is supported. 977 */ 978 ssp_codec_index = find_codec_info_acpi(mach->id); 979 ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0; 980 comp_num = hdmi_num + ssp_num; 981 982 ret = get_sdw_dailink_info(mach_params->links, 983 &sdw_be_num, &sdw_cpu_dai_num); 984 if (ret < 0) { 985 dev_err(dev, "failed to get sdw link info %d", ret); 986 return ret; 987 } 988 989 if (mach_params->codec_mask & IDISP_CODEC_MASK) 990 ctx->idisp_codec = true; 991 992 /* enable dmic01 & dmic16k */ 993 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; 994 comp_num += dmic_num; 995 996 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) 997 comp_num++; 998 999 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, 1000 dmic_num, ctx->idisp_codec ? hdmi_num : 0); 1001 1002 /* allocate BE dailinks */ 1003 num_links = comp_num + sdw_be_num; 1004 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL); 1005 1006 /* allocated CPU DAIs */ 1007 total_cpu_dai_num = comp_num + sdw_cpu_dai_num; 1008 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus), 1009 GFP_KERNEL); 1010 1011 if (!links || !cpus) 1012 return -ENOMEM; 1013 1014 /* SDW */ 1015 if (!sdw_be_num) 1016 goto SSP; 1017 1018 adr_link = mach_params->links; 1019 if (!adr_link) 1020 return -EINVAL; 1021 1022 /* 1023 * SoundWire Slaves aggregated in the same group may be 1024 * located on different hardware links. Clear array to indicate 1025 * CPU DAIs for this group have not been generated. 1026 */ 1027 for (i = 0; i < SDW_MAX_GROUPS; i++) 1028 group_generated[i] = false; 1029 1030 /* generate DAI links by each sdw link */ 1031 for (; adr_link->num_adr; adr_link++) { 1032 const struct snd_soc_acpi_endpoint *endpoint; 1033 1034 endpoint = adr_link->adr_d->endpoints; 1035 if (endpoint->aggregated && !endpoint->group_id) { 1036 dev_err(dev, "invalid group id on link %x", 1037 adr_link->mask); 1038 continue; 1039 } 1040 1041 /* this group has been generated */ 1042 if (endpoint->aggregated && 1043 group_generated[endpoint->group_id]) 1044 continue; 1045 1046 ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num, 1047 sdw_cpu_dai_num, cpus, adr_link, 1048 &cpu_id, group_generated, 1049 codec_conf, codec_conf_count, 1050 &codec_conf_index, 1051 &ignore_pch_dmic); 1052 if (ret < 0) { 1053 dev_err(dev, "failed to create dai link %d", be_id); 1054 return -ENOMEM; 1055 } 1056 } 1057 1058 /* non-sdw DAI follows sdw DAI */ 1059 link_id = be_id; 1060 1061 /* get BE ID for non-sdw DAI */ 1062 be_id = get_next_be_id(links, be_id); 1063 1064 SSP: 1065 /* SSP */ 1066 if (!ssp_num) 1067 goto DMIC; 1068 1069 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1070 struct sof_sdw_codec_info *info; 1071 int playback, capture; 1072 char *codec_name; 1073 1074 if (!(ssp_mask & 0x1)) 1075 continue; 1076 1077 name = devm_kasprintf(dev, GFP_KERNEL, 1078 "SSP%d-Codec", i); 1079 if (!name) 1080 return -ENOMEM; 1081 1082 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1083 if (!cpu_name) 1084 return -ENOMEM; 1085 1086 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1087 GFP_KERNEL); 1088 if (!ssp_components) 1089 return -ENOMEM; 1090 1091 info = &codec_info_list[ssp_codec_index]; 1092 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1093 info->acpi_id, j++); 1094 if (!codec_name) 1095 return -ENOMEM; 1096 1097 ssp_components->name = codec_name; 1098 ssp_components->dai_name = info->dai_name; 1099 cpus[cpu_id].dai_name = cpu_name; 1100 1101 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; 1102 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; 1103 init_dai_link(dev, links + link_id, be_id, name, 1104 playback, capture, 1105 cpus + cpu_id, 1, 1106 ssp_components, 1, 1107 NULL, info->ops); 1108 1109 ret = info->init(NULL, links + link_id, info, 0); 1110 if (ret < 0) 1111 return ret; 1112 1113 INC_ID(be_id, cpu_id, link_id); 1114 } 1115 1116 DMIC: 1117 /* dmic */ 1118 if (dmic_num > 0) { 1119 if (ignore_pch_dmic) { 1120 dev_warn(dev, "Ignoring PCH DMIC\n"); 1121 goto HDMI; 1122 } 1123 cpus[cpu_id].dai_name = "DMIC01 Pin"; 1124 init_dai_link(dev, links + link_id, be_id, "dmic01", 1125 0, 1, // DMIC only supports capture 1126 cpus + cpu_id, 1, 1127 dmic_component, 1, 1128 sof_sdw_dmic_init, NULL); 1129 INC_ID(be_id, cpu_id, link_id); 1130 1131 cpus[cpu_id].dai_name = "DMIC16k Pin"; 1132 init_dai_link(dev, links + link_id, be_id, "dmic16k", 1133 0, 1, // DMIC only supports capture 1134 cpus + cpu_id, 1, 1135 dmic_component, 1, 1136 /* don't call sof_sdw_dmic_init() twice */ 1137 NULL, NULL); 1138 INC_ID(be_id, cpu_id, link_id); 1139 } 1140 1141 HDMI: 1142 /* HDMI */ 1143 if (hdmi_num > 0) { 1144 idisp_components = devm_kcalloc(dev, hdmi_num, 1145 sizeof(*idisp_components), 1146 GFP_KERNEL); 1147 if (!idisp_components) 1148 return -ENOMEM; 1149 } 1150 1151 for (i = 0; i < hdmi_num; i++) { 1152 name = devm_kasprintf(dev, GFP_KERNEL, 1153 "iDisp%d", i + 1); 1154 if (!name) 1155 return -ENOMEM; 1156 1157 if (ctx->idisp_codec) { 1158 idisp_components[i].name = "ehdaudio0D2"; 1159 idisp_components[i].dai_name = devm_kasprintf(dev, 1160 GFP_KERNEL, 1161 "intel-hdmi-hifi%d", 1162 i + 1); 1163 if (!idisp_components[i].dai_name) 1164 return -ENOMEM; 1165 } else { 1166 idisp_components[i].name = "snd-soc-dummy"; 1167 idisp_components[i].dai_name = "snd-soc-dummy-dai"; 1168 } 1169 1170 cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1171 "iDisp%d Pin", i + 1); 1172 if (!cpu_name) 1173 return -ENOMEM; 1174 1175 cpus[cpu_id].dai_name = cpu_name; 1176 init_dai_link(dev, links + link_id, be_id, name, 1177 1, 0, // HDMI only supports playback 1178 cpus + cpu_id, 1, 1179 idisp_components + i, 1, 1180 sof_sdw_hdmi_init, NULL); 1181 INC_ID(be_id, cpu_id, link_id); 1182 } 1183 1184 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1185 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1186 SOF_BT_OFFLOAD_SSP_SHIFT; 1187 1188 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1189 if (!name) 1190 return -ENOMEM; 1191 1192 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), 1193 GFP_KERNEL); 1194 if (!ssp_components) 1195 return -ENOMEM; 1196 1197 ssp_components->name = "snd-soc-dummy"; 1198 ssp_components->dai_name = "snd-soc-dummy-dai"; 1199 1200 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1201 if (!cpu_name) 1202 return -ENOMEM; 1203 1204 cpus[cpu_id].dai_name = cpu_name; 1205 init_dai_link(dev, links + link_id, be_id, name, 1, 1, 1206 cpus + cpu_id, 1, ssp_components, 1, NULL, NULL); 1207 } 1208 1209 card->dai_link = links; 1210 card->num_links = num_links; 1211 1212 card->codec_conf = codec_conf; 1213 card->num_configs = codec_conf_count; 1214 1215 return 0; 1216 } 1217 1218 static int sof_sdw_card_late_probe(struct snd_soc_card *card) 1219 { 1220 int i, ret; 1221 1222 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1223 if (!codec_info_list[i].late_probe) 1224 continue; 1225 1226 ret = codec_info_list[i].codec_card_late_probe(card); 1227 if (ret < 0) 1228 return ret; 1229 } 1230 1231 return sof_sdw_hdmi_card_late_probe(card); 1232 } 1233 1234 /* SoC card */ 1235 static const char sdw_card_long_name[] = "Intel Soundwire SOF"; 1236 1237 static struct snd_soc_card card_sof_sdw = { 1238 .name = "soundwire", 1239 .owner = THIS_MODULE, 1240 .late_probe = sof_sdw_card_late_probe, 1241 }; 1242 1243 static int mc_probe(struct platform_device *pdev) 1244 { 1245 struct snd_soc_card *card = &card_sof_sdw; 1246 struct snd_soc_acpi_mach *mach; 1247 struct mc_private *ctx; 1248 int amp_num = 0, i; 1249 int ret; 1250 1251 dev_dbg(&pdev->dev, "Entry %s\n", __func__); 1252 1253 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1254 if (!ctx) 1255 return -ENOMEM; 1256 1257 dmi_check_system(sof_sdw_quirk_table); 1258 1259 if (quirk_override != -1) { 1260 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", 1261 sof_sdw_quirk, quirk_override); 1262 sof_sdw_quirk = quirk_override; 1263 } 1264 log_quirks(&pdev->dev); 1265 1266 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 1267 1268 card->dev = &pdev->dev; 1269 snd_soc_card_set_drvdata(card, ctx); 1270 1271 mach = pdev->dev.platform_data; 1272 ret = sof_card_dai_links_create(&pdev->dev, mach, 1273 card); 1274 if (ret < 0) 1275 return ret; 1276 1277 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; 1278 1279 /* 1280 * the default amp_num is zero for each codec and 1281 * amp_num will only be increased for active amp 1282 * codecs on used platform 1283 */ 1284 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1285 amp_num += codec_info_list[i].amp_num; 1286 1287 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1288 "cfg-spk:%d cfg-amp:%d", 1289 (sof_sdw_quirk & SOF_SDW_FOUR_SPK) 1290 ? 4 : 2, amp_num); 1291 if (!card->components) 1292 return -ENOMEM; 1293 1294 if (mach->mach_params.dmic_num) { 1295 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 1296 "%s mic:dmic cfg-mics:%d", 1297 card->components, 1298 mach->mach_params.dmic_num); 1299 if (!card->components) 1300 return -ENOMEM; 1301 } 1302 1303 card->long_name = sdw_card_long_name; 1304 1305 /* Register the card */ 1306 ret = devm_snd_soc_register_card(&pdev->dev, card); 1307 if (ret) { 1308 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); 1309 return ret; 1310 } 1311 1312 platform_set_drvdata(pdev, card); 1313 1314 return ret; 1315 } 1316 1317 static int mc_remove(struct platform_device *pdev) 1318 { 1319 struct snd_soc_card *card = platform_get_drvdata(pdev); 1320 struct snd_soc_dai_link *link; 1321 int ret; 1322 int i, j; 1323 1324 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1325 if (!codec_info_list[i].exit) 1326 continue; 1327 /* 1328 * We don't need to call .exit function if there is no matched 1329 * dai link found. 1330 */ 1331 for_each_card_prelinks(card, j, link) { 1332 if (!strcmp(link->codecs[0].dai_name, 1333 codec_info_list[i].dai_name)) { 1334 ret = codec_info_list[i].exit(&pdev->dev, link); 1335 if (ret) 1336 dev_warn(&pdev->dev, 1337 "codec exit failed %d\n", 1338 ret); 1339 break; 1340 } 1341 } 1342 } 1343 1344 return 0; 1345 } 1346 1347 static struct platform_driver sof_sdw_driver = { 1348 .driver = { 1349 .name = "sof_sdw", 1350 .pm = &snd_soc_pm_ops, 1351 }, 1352 .probe = mc_probe, 1353 .remove = mc_remove, 1354 }; 1355 1356 module_platform_driver(sof_sdw_driver); 1357 1358 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); 1359 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); 1360 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); 1361 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 1362 MODULE_LICENSE("GPL v2"); 1363 MODULE_ALIAS("platform:sof_sdw"); 1364 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 1365 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 1366