Lines Matching +full:fixed +full:- +full:links

1 // SPDX-License-Identifier: GPL-2.0-only
5 * sof_sdw - ASOC Machine driver for Intel SoundWire platforms
14 #include <sound/soc-acpi.h>
19 static int quirk_override = -1;
21 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
28 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", in log_quirks()
45 sof_sdw_quirk = (unsigned long)id->driver_data; in sof_sdw_quirk_cb()
183 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
216 /* TigerLake-SDCA devices */
353 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
371 .name = "dmic-codec",
372 .dai_name = "dmic-hifi",
398 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); in sdw_prepare()
401 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); in sdw_prepare()
418 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); in sdw_trigger()
421 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); in sdw_trigger()
438 ret = -EINVAL; in sdw_trigger()
443 dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret); in sdw_trigger()
457 sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); in sdw_hw_free()
460 dev_err(rtd->dev, "no stream found for DAI %s", dai->name); in sdw_hw_free()
484 .dai_name = "rt700-aif1",
492 .dai_name = "rt711-sdca-aif1",
501 .dai_name = "rt711-aif1",
510 .dai_name = "rt1308-aif",
518 .dai_name = "rt1316-aif",
527 .dai_name = "rt715-aif2",
536 .dai_name = "rt715-aif2",
545 .dai_name = "rt715-aif2",
554 .dai_name = "rt715-aif2",
561 .dai_name = "max98373-aif1",
569 .dai_name = "rt5682-sdw",
577 .dai_name = "sdw-mockup-aif1",
585 .dai_name = "sdw-mockup-aif1",
593 .dai_name = "sdw-mockup-aif1",
601 .dai_name = "sdw-mockup-aif1",
623 return -EINVAL; in find_codec_info_part()
632 return -EINVAL; in find_codec_info_acpi()
640 return -EINVAL; in find_codec_info_acpi()
650 static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_link_adr *links, in get_sdw_dailink_info() argument
663 if (!links) in get_sdw_dailink_info()
664 return -EINVAL; in get_sdw_dailink_info()
669 for (link = links; link->num_adr; link++) { in get_sdw_dailink_info()
675 adr = link->adr_d->adr; in get_sdw_dailink_info()
682 "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); in get_sdw_dailink_info()
686 endpoint = link->adr_d->endpoints; in get_sdw_dailink_info()
695 /* count BE for each non-aggregated slave or group */ in get_sdw_dailink_info()
696 if (!endpoint->aggregated || no_aggregation || in get_sdw_dailink_info()
697 !group_visited[endpoint->group_id]) in get_sdw_dailink_info()
701 if (endpoint->aggregated) in get_sdw_dailink_info()
702 group_visited[endpoint->group_id] = true; in get_sdw_dailink_info()
716 dai_links->id = be_id; in init_dai_link()
717 dai_links->name = name; in init_dai_link()
718 dai_links->platforms = platform_component; in init_dai_link()
719 dai_links->num_platforms = ARRAY_SIZE(platform_component); in init_dai_link()
720 dai_links->no_pcm = 1; in init_dai_link()
721 dai_links->cpus = cpus; in init_dai_link()
722 dai_links->num_cpus = cpus_num; in init_dai_link()
723 dai_links->codecs = codecs; in init_dai_link()
724 dai_links->num_codecs = codecs_num; in init_dai_link()
725 dai_links->dpcm_playback = playback; in init_dai_link()
726 dai_links->dpcm_capture = capture; in init_dai_link()
727 dai_links->init = init; in init_dai_link()
728 dai_links->ops = ops; in init_dai_link()
741 for (i = 0; i < link->num_adr; i++) { in is_unique_device()
749 adr = link->adr_d[i].adr; in is_unique_device()
777 if (*codec_conf_index + link->num_adr > codec_count) { in create_codec_dai_name()
778 dev_err(dev, "codec_conf: out-of-bounds access requested\n"); in create_codec_dai_name()
779 return -EINVAL; in create_codec_dai_name()
782 for (i = 0; i < link->num_adr; i++) { in create_codec_dai_name()
789 adr = link->adr_d[i].adr; in create_codec_dai_name()
815 return -ENOMEM; in create_codec_dai_name()
825 codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix; in create_codec_dai_name()
846 for (i = 0; i < link->num_adr; i++) { in set_codec_init_func()
849 codec_index = find_codec_info_part(link->adr_d[i].adr); in set_codec_init_func()
854 if (link->adr_d[i].endpoints->group_id != group_id) in set_codec_init_func()
864 } while (link->mask && group_id); in set_codec_init_func()
875 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
878 * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs
880 * multiple links with multiple slaves with aggregated = 1
881 * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
894 *codec_num = adr_link->num_adr; in get_slave_info()
895 adr_d = adr_link->adr_d; in get_slave_info()
898 if (!is_power_of_2(adr_link->mask)) in get_slave_info()
899 return -EINVAL; in get_slave_info()
901 cpu_dai_id[index++] = ffs(adr_link->mask) - 1; in get_slave_info()
902 if (!adr_d->endpoints->aggregated || no_aggregation) { in get_slave_info()
908 *group_id = adr_d->endpoints->group_id; in get_slave_info()
911 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; in get_slave_info()
915 endpoint = adr_next->adr_d->endpoints; in get_slave_info()
916 if (!endpoint->aggregated || in get_slave_info()
917 endpoint->group_id != *group_id) in get_slave_info()
921 if (!is_power_of_2(adr_next->mask)) in get_slave_info()
922 return -EINVAL; in get_slave_info()
926 return -EINVAL; in get_slave_info()
929 cpu_dai_id[index++] = ffs(adr_next->mask) - 1; in get_slave_info()
930 *codec_num += adr_next->num_adr; in get_slave_info()
975 return -ENOMEM; in create_sdw_dailink()
977 /* generate codec name on different links in the same group */ in create_sdw_dailink()
978 for (link_next = link; link_next && link_next->num_adr && in create_sdw_dailink()
982 endpoints = link_next->adr_d->endpoints; in create_sdw_dailink()
983 if (group_id && (!endpoints->aggregated || in create_sdw_dailink()
984 endpoints->group_id != group_id)) in create_sdw_dailink()
988 if (cpu_dai_id[i] != ffs(link_next->mask) - 1) in create_sdw_dailink()
998 codec_idx += link_next->num_adr; in create_sdw_dailink()
1002 codec_index = find_codec_info_part(link->adr_d[0].adr); in create_sdw_dailink()
1015 * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to in create_sdw_dailink()
1027 "SDW%d-Playback", in create_sdw_dailink()
1028 "SDW%d-Capture", in create_sdw_dailink()
1038 return -ENOMEM; in create_sdw_dailink()
1049 return -ENOMEM; in create_sdw_dailink()
1054 return -EINVAL; in create_sdw_dailink()
1061 * We create sdw dai links at first stage, so link index should in create_sdw_dailink()
1066 return -EINVAL; in create_sdw_dailink()
1071 return -EINVAL; in create_sdw_dailink()
1114 adr_link = mach_params->links; in sof_card_codec_conf_alloc()
1116 return -EINVAL; in sof_card_codec_conf_alloc()
1118 /* generate DAI links by each sdw link */ in sof_card_codec_conf_alloc()
1119 for (; adr_link->num_adr; adr_link++) { in sof_card_codec_conf_alloc()
1120 for (i = 0; i < adr_link->num_adr; i++) { in sof_card_codec_conf_alloc()
1121 if (!adr_link->adr_d[i].name_prefix) { in sof_card_codec_conf_alloc()
1123 adr_link->adr_d[i].adr); in sof_card_codec_conf_alloc()
1124 return -EINVAL; in sof_card_codec_conf_alloc()
1127 num_codecs += adr_link->num_adr; in sof_card_codec_conf_alloc()
1132 return -ENOMEM; in sof_card_codec_conf_alloc()
1157 struct snd_soc_dai_link *links; in sof_card_dai_links_create() local
1167 mach_params = &mach->mach_params; in sof_card_dai_links_create()
1178 if (mach_params->codec_mask & IDISP_CODEC_MASK) { in sof_card_dai_links_create()
1179 ctx->idisp_codec = true; in sof_card_dai_links_create()
1194 ssp_codec_index = find_codec_info_acpi(mach->id); in sof_card_dai_links_create()
1198 ret = get_sdw_dailink_info(dev, mach_params->links, in sof_card_dai_links_create()
1206 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; in sof_card_dai_links_create()
1213 dmic_num, ctx->idisp_codec ? hdmi_num : 0); in sof_card_dai_links_create()
1217 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL); in sof_card_dai_links_create()
1224 if (!links || !cpus) in sof_card_dai_links_create()
1225 return -ENOMEM; in sof_card_dai_links_create()
1231 adr_link = mach_params->links; in sof_card_dai_links_create()
1233 return -EINVAL; in sof_card_dai_links_create()
1237 * located on different hardware links. Clear array to indicate in sof_card_dai_links_create()
1243 /* generate DAI links by each sdw link */ in sof_card_dai_links_create()
1244 for (; adr_link->num_adr; adr_link++) { in sof_card_dai_links_create()
1247 endpoint = adr_link->adr_d->endpoints; in sof_card_dai_links_create()
1248 if (endpoint->aggregated && !endpoint->group_id) { in sof_card_dai_links_create()
1250 adr_link->mask); in sof_card_dai_links_create()
1255 if (endpoint->aggregated && in sof_card_dai_links_create()
1256 group_generated[endpoint->group_id]) in sof_card_dai_links_create()
1259 ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, in sof_card_dai_links_create()
1285 "SSP%d-Codec", i); in sof_card_dai_links_create()
1287 return -ENOMEM; in sof_card_dai_links_create()
1291 return -ENOMEM; in sof_card_dai_links_create()
1296 return -ENOMEM; in sof_card_dai_links_create()
1299 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", in sof_card_dai_links_create()
1300 info->acpi_id, j++); in sof_card_dai_links_create()
1302 return -ENOMEM; in sof_card_dai_links_create()
1304 ssp_components->name = codec_name; in sof_card_dai_links_create()
1305 ssp_components->dai_name = info->dai_name; in sof_card_dai_links_create()
1308 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; in sof_card_dai_links_create()
1309 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; in sof_card_dai_links_create()
1310 init_dai_link(dev, links + link_index, be_id, name, in sof_card_dai_links_create()
1314 NULL, info->ops); in sof_card_dai_links_create()
1316 ret = info->init(card, NULL, links + link_index, info, 0); in sof_card_dai_links_create()
1331 init_dai_link(dev, links + link_index, be_id, "dmic01", in sof_card_dai_links_create()
1339 init_dai_link(dev, links + link_index, be_id, "dmic16k", in sof_card_dai_links_create()
1355 return -ENOMEM; in sof_card_dai_links_create()
1362 return -ENOMEM; in sof_card_dai_links_create()
1364 if (ctx->idisp_codec) { in sof_card_dai_links_create()
1368 "intel-hdmi-hifi%d", in sof_card_dai_links_create()
1371 return -ENOMEM; in sof_card_dai_links_create()
1373 idisp_components[i].name = "snd-soc-dummy"; in sof_card_dai_links_create()
1374 idisp_components[i].dai_name = "snd-soc-dummy-dai"; in sof_card_dai_links_create()
1380 return -ENOMEM; in sof_card_dai_links_create()
1383 init_dai_link(dev, links + link_index, be_id, name, in sof_card_dai_links_create()
1395 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); in sof_card_dai_links_create()
1397 return -ENOMEM; in sof_card_dai_links_create()
1402 return -ENOMEM; in sof_card_dai_links_create()
1404 ssp_components->name = "snd-soc-dummy"; in sof_card_dai_links_create()
1405 ssp_components->dai_name = "snd-soc-dummy-dai"; in sof_card_dai_links_create()
1409 return -ENOMEM; in sof_card_dai_links_create()
1412 init_dai_link(dev, links + link_index, be_id, name, 1, 1, in sof_card_dai_links_create()
1416 card->dai_link = links; in sof_card_dai_links_create()
1417 card->num_links = num_links; in sof_card_dai_links_create()
1419 card->codec_conf = codec_conf; in sof_card_dai_links_create()
1420 card->num_configs = codec_conf_count; in sof_card_dai_links_create()
1440 if (ctx->idisp_codec) in sof_sdw_card_late_probe()
1469 if (!strcmp(link->codecs[0].dai_name, in mc_dailink_exit_loop()
1473 dev_warn(card->dev, in mc_dailink_exit_loop()
1490 dev_dbg(&pdev->dev, "Entry\n"); in mc_probe()
1492 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); in mc_probe()
1494 return -ENOMEM; in mc_probe()
1498 if (quirk_override != -1) { in mc_probe()
1499 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", in mc_probe()
1503 log_quirks(&pdev->dev); in mc_probe()
1505 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); in mc_probe()
1507 card->dev = &pdev->dev; in mc_probe()
1510 mach = pdev->dev.platform_data; in mc_probe()
1511 ret = sof_card_dai_links_create(&pdev->dev, mach, in mc_probe()
1524 card->components = devm_kasprintf(card->dev, GFP_KERNEL, in mc_probe()
1525 "cfg-spk:%d cfg-amp:%d", in mc_probe()
1528 if (!card->components) in mc_probe()
1529 return -ENOMEM; in mc_probe()
1531 if (mach->mach_params.dmic_num) { in mc_probe()
1532 card->components = devm_kasprintf(card->dev, GFP_KERNEL, in mc_probe()
1533 "%s mic:dmic cfg-mics:%d", in mc_probe()
1534 card->components, in mc_probe()
1535 mach->mach_params.dmic_num); in mc_probe()
1536 if (!card->components) in mc_probe()
1537 return -ENOMEM; in mc_probe()
1540 card->long_name = sdw_card_long_name; in mc_probe()
1543 ret = devm_snd_soc_register_card(&pdev->dev, card); in mc_probe()
1545 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); in mc_probe()
1576 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1578 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");