From 087777347bea060f82fa97827e7d1f625c0f9376 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:56 -0500 Subject: [PATCH 01/34] ASoC: intel: sof_sdw: Make find_codec_info_part() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 79 +++++++++++++++----------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 08f330ed5c2e..08b19a32cf9c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1055,7 +1055,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { }, }; -static inline int find_codec_info_part(const u64 adr) +static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) { unsigned int part_id, sdw_version; int i; @@ -1070,9 +1070,9 @@ static inline int find_codec_info_part(const u64 adr) if (part_id == codec_info_list[i].part_id && (!codec_info_list[i].version_id || sdw_version == codec_info_list[i].version_id)) - return i; + return &codec_info_list[i]; - return -EINVAL; + return NULL; } @@ -1116,7 +1116,6 @@ static int get_dailink_info(struct device *dev, for (; adr_link->num_adr; adr_link++) { const struct snd_soc_acpi_endpoint *endpoint; struct sof_sdw_codec_info *codec_info; - int codec_index; int stream; u64 adr; @@ -1126,11 +1125,9 @@ static int get_dailink_info(struct device *dev, for (i = 0; i < adr_link->num_adr; i++) { adr = adr_link->adr_d[i].adr; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; - - codec_info = &codec_info_list[codec_index]; + codec_info = find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; *codecs_num += codec_info->dai_num; @@ -1257,11 +1254,11 @@ static int fill_sdw_codec_dlc(struct device *dev, { unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; u64 adr = adr_link->adr_d[adr_index].adr; - int codec_index; + struct sof_sdw_codec_info *codec_info; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; sdw_version = SDW_VERSION(adr); link_id = SDW_DISCO_LINK_ID(adr); @@ -1270,10 +1267,8 @@ static int fill_sdw_codec_dlc(struct device *dev, part_id = SDW_PART_ID(adr); class_id = SDW_CLASS_ID(adr); - if (codec_info_list[codec_index].codec_name) - codec->name = devm_kstrdup(dev, - codec_info_list[codec_index].codec_name, - GFP_KERNEL); + if (codec_info->codec_name) + codec->name = devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, class_id, adr_index)) codec->name = devm_kasprintf(dev, GFP_KERNEL, @@ -1287,7 +1282,7 @@ static int fill_sdw_codec_dlc(struct device *dev, if (!codec->name) return -ENOMEM; - codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name; + codec->dai_name = codec_info->dais[dai_index].dai_name; return 0; } @@ -1309,22 +1304,22 @@ static int set_codec_init_func(struct snd_soc_card *card, * we should end immediately if it is not aggregated (group_id=0) */ for ( ; i < adr_link->num_adr; i++) { - int codec_index; + struct sof_sdw_codec_info *codec_info; - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; /* The group_id is > 0 iff the codec is aggregated */ if (adr_link->adr_d[i].endpoints->group_id != group_id) continue; - if (codec_info_list[codec_index].dais[dai_index].init) - codec_info_list[codec_index].dais[dai_index].init(card, - adr_link, - dai_links, - &codec_info_list[codec_index], - playback); + if (codec_info->dais[dai_index].init) + codec_info->dais[dai_index].init(card, + adr_link, + dai_links, + codec_info, + playback); if (!group_id) return 0; } @@ -1481,7 +1476,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, int cpu_dai_num; unsigned int group_id; int codec_dlc_index = 0; - int codec_index; int codec_num; int stream; int i = 0; @@ -1541,10 +1535,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr); - if (codec_index < 0) - return codec_index; - codec_info = &codec_info_list[codec_index]; + codec_info = find_codec_info_part(adr_link->adr_d[adr_index].adr); + if (!codec_info) + return -EINVAL; if (codec_info->ignore_pch_dmic) *ignore_pch_dmic = true; @@ -1631,7 +1624,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, playback, group_id, adr_index, dai_index); if (ret < 0) { - dev_err(dev, "failed to init codec %d\n", codec_index); + dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); return ret; } } @@ -1649,6 +1642,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; + struct sof_sdw_codec_info *codec_info; bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; @@ -1660,7 +1654,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; - int codec_index; int hdmi_num; int ret; @@ -1729,10 +1722,10 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) */ for (i = 0; i < adr_link->num_adr; i++) { /* find codec info to get dai_num */ - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; - if (codec_info_list[codec_index].dai_num > 1) { + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; + if (codec_info->dai_num > 1) { append_dai_type = true; goto out; } @@ -1762,11 +1755,11 @@ out: continue; /* find codec info to get dai_num */ - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; - for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) { + for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; ret = create_sdw_dailink(card, &link_index, dai_links, From c2c7a8b3848127f3355109d72c865b7741af9f0c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:57 -0500 Subject: [PATCH 02/34] ASoC: intel: sof_sdw: Make find_codec_info_acpi() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 08b19a32cf9c..517ff44de1f0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1076,18 +1076,18 @@ static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) } -static inline int find_codec_info_acpi(const u8 *acpi_id) +static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) { int i; if (!acpi_id[0]) - return -EINVAL; + return NULL; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) - return i; + return &codec_info_list[i]; - return -EINVAL; + return NULL; } /* @@ -1643,18 +1643,19 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; + struct sof_sdw_codec_info *ssp_info; bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS] = { }; - int ssp_codec_index, ssp_mask; struct snd_soc_dai_link *dai_links; int num_links, link_index = 0; char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; + int ssp_mask; int ret; ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); @@ -1669,8 +1670,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) * system only when I2S mode is supported, not sdw mode. * Here check ACPI ID to confirm I2S is supported. */ - ssp_codec_index = find_codec_info_acpi(mach->id); - if (ssp_codec_index >= 0) { + ssp_info = find_codec_info_acpi(mach->id); + if (ssp_info) { ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); ssp_num = hweight_long(ssp_mask); } @@ -1788,30 +1789,28 @@ SSP: goto DMIC; for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { - struct sof_sdw_codec_info *info; int playback, capture; if (!(ssp_mask & 0x1)) continue; - info = &codec_info_list[ssp_codec_index]; - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", - info->acpi_id, j++); + ssp_info->acpi_id, j++); - playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; - capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; + playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; + capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, playback, capture, cpu_dai_name, - codec_name, info->dais[0].dai_name, - NULL, info->ops); + codec_name, ssp_info->dais[0].dai_name, + NULL, ssp_info->ops); if (ret) return ret; - ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0); + ret = ssp_info->dais[0].init(card, NULL, dai_links + link_index, + ssp_info, 0); if (ret < 0) return ret; From 1329f5b0d9d0b26021b6bd469a41139b9ccef58a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:58 -0500 Subject: [PATCH 03/34] ASoC: intel: sof_sdw: Make find_codec_info_dai() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. And move the function such that it is located with the other find_codec_info_*() functions. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 517ff44de1f0..4bd9f62c48fc 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1090,6 +1090,23 @@ static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) return NULL; } +static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, + int *dai_index) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + for (j = 0; j < codec_info_list[i].dai_num; j++) { + if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { + *dai_index = j; + return &codec_info_list[i]; + } + } + } + + return NULL; +} + /* * get BE dailink number and CPU DAI number based on sdw link adr. * Since some sdw slaves may be aggregated, the CPU DAI number @@ -1403,37 +1420,19 @@ static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps, } } -static inline int find_codec_info_dai(const char *dai_name, int *dai_index) -{ - int i, j; - - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - for (j = 0; j < codec_info_list[i].dai_num; j++) { - if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { - *dai_index = j; - return i; - } - } - } - - return -EINVAL; -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; struct snd_soc_dai *dai; - int codec_index; int dai_index; int ret; int i; for_each_rtd_codec_dais(rtd, i, dai) { - codec_index = find_codec_info_dai(dai->name, &dai_index); - if (codec_index < 0) + codec_info = find_codec_info_dai(dai->name, &dai_index); + if (!codec_info) return -EINVAL; - codec_info = &codec_info_list[codec_index]; /* * A codec dai can be connected to different dai links for capture and playback, * but we only need to call the rtd_init function once. From 961e694749fb8ddb8591512216e2fa6b4e3f42e2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:59 -0500 Subject: [PATCH 04/34] ASoC: intel: sof_sdw: Only pass codec_conf pointer around Rather than passing around a pointer to the codec_conf array, an index into it and a size, simply pass around a pointer to the current codec_conf. This reduces the amount of state moving around. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 4bd9f62c48fc..7b61d45df5da 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1457,10 +1457,8 @@ static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic" static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct snd_soc_dai_link *dai_links, int sdw_be_num, const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_codec_conf *codec_conf, - int codec_count, int *be_id, - int *codec_conf_index, - bool *ignore_pch_dmic, + struct snd_soc_codec_conf **codec_conf, + int *be_id, bool *ignore_pch_dmic, bool append_dai_type, int adr_index, int dai_index) @@ -1509,7 +1507,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, continue; /* sanity check */ - if (*codec_conf_index >= codec_count) { + if (*codec_conf >= card->codec_conf + card->num_configs) { dev_err(dev, "codec_conf array overflowed\n"); return -EINVAL; } @@ -1520,12 +1518,11 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (ret) return ret; - codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index]; - codec_conf[*codec_conf_index].name_prefix = - adr_link_next->adr_d[j].name_prefix; + (*codec_conf)->dlc = codecs[codec_dlc_index]; + (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; codec_dlc_index++; - (*codec_conf_index)++; + (*codec_conf)++; } j = 0; @@ -1646,7 +1643,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; - int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links, link_index = 0; @@ -1706,6 +1702,9 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_conf) return -ENOMEM; + card->codec_conf = codec_conf; + card->num_configs = codec_conf_num; + /* SDW */ if (!sdw_be_num) goto SSP; @@ -1764,9 +1763,9 @@ out: ret = create_sdw_dailink(card, &link_index, dai_links, sdw_be_num, adr_link, - codec_conf, codec_conf_num, - ¤t_be_id, &codec_conf_index, - &ignore_pch_dmic, append_dai_type, i, j); + &codec_conf, ¤t_be_id, + &ignore_pch_dmic, + append_dai_type, i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d\n", link_index); return ret; @@ -1886,9 +1885,6 @@ HDMI: card->dai_link = dai_links; card->num_links = num_links; - card->codec_conf = codec_conf; - card->num_configs = codec_conf_num; - return 0; } From 634ffef9cbc41b9db2b45974969dda06219ffce1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:00 -0500 Subject: [PATCH 05/34] ASoC: intel: sof_sdw: Set channel map directly from endpoints The current code evenly distributes the CODEC DAIs across the CPU DAIs in the DAI link, but this is just an assumption about how the devices are connected to the host. All the information about which CODEC is connected to which CPU DAI is contained in the endpoints datastructures and those structures are already parsed to work out which CODECs to include in the DAI link. Simply fill in the mapping from CPUs -> CODECs as we parse through the endpoints structures, this will ensure that mapping matches the physical layout. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7b61d45df5da..e2c1822b185f 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1407,19 +1407,6 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } -static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps, - int codec_num, int cpu_num) -{ - int step; - int i; - - step = codec_num / cpu_num; - for (i = 0; i < codec_num; i++) { - sdw_codec_ch_maps[i].cpu = i / step; - sdw_codec_ch_maps[i].codec = i; - } -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; @@ -1466,6 +1453,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; const struct snd_soc_acpi_link_adr *adr_link_next; + struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; struct snd_soc_dai_link_component *codecs; struct snd_soc_dai_link_component *cpus; struct sof_sdw_codec_info *codec_info; @@ -1488,6 +1476,11 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (!codecs) return -ENOMEM; + sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, + sizeof(*sdw_codec_ch_maps), GFP_KERNEL); + if (!sdw_codec_ch_maps) + return -ENOMEM; + /* generate codec name on different links in the same group */ j = adr_index; for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && @@ -1521,6 +1514,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, (*codec_conf)->dlc = codecs[codec_dlc_index]; (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; + sdw_codec_ch_maps[codec_dlc_index].cpu = i; + sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; + codec_dlc_index++; (*codec_conf)++; } @@ -1539,7 +1535,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, *ignore_pch_dmic = true; for_each_pcm_streams(stream) { - struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; char *name, *cpu_name; int playback, capture; static const char * const sdw_stream_name[] = { @@ -1558,11 +1553,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, return -EINVAL; } - sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, - sizeof(*sdw_codec_ch_maps), GFP_KERNEL); - if (!sdw_codec_ch_maps) - return -ENOMEM; - /* create stream name according to first link id */ if (append_dai_type) { name = devm_kasprintf(dev, GFP_KERNEL, @@ -1614,9 +1604,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, * based on wait_for_completion(), tag them as 'nonatomic'. */ dai_links[*link_index].nonatomic = true; - - set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num); dai_links[*link_index].ch_maps = sdw_codec_ch_maps; + ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, playback, group_id, adr_index, dai_index); if (ret < 0) { From 0703329606a237c3604230603d58254a8bdf4b81 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:01 -0500 Subject: [PATCH 06/34] ASoC: Intel: sof_sdw: Move get_codec_dai_by_name() into sof_sdw itself Currently sof_sdw relies on sof_board_helpers to provide get_codec_dai_by_name(), but that is the only function from sof_board_helpers it uses and no other machine driver requires that function. There is no reason for sof_sdw to select SSP_COMMON but more and more functions in sof_board_helpers are gaining dependencies on functions that would require stubs for sof_sdw to build without it. Firstly it was sof_ssp_get_codec_name(), as was fixed in commit c1469c3a8a30 ("ASoC: Intel: ssp-common: Add stub for sof_ssp_get_codec_name"), now it is: ERROR: modpost: "sof_ssp_detect_amp_type" [sound/soc/intel/boards/snd-soc-intel-sof-board-helpers.ko] undefined! ERROR: modpost: "sof_ssp_detect_codec_type" [sound/soc/intel/boards/snd-soc-intel-sof-board-helpers.ko] undefined! Rather than adding more stubs, simply move the affected function to the sof_sdw machine driver itself and no longer select SND_SOC_INTEL_SOF_BOARD_HELPERS at all. This should allow work on SSP_COMMON to progress without affecting sof_sdw. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 - sound/soc/intel/boards/sof_board_helpers.c | 18 ------------------ sound/soc/intel/boards/sof_board_helpers.h | 3 --- sound/soc/intel/boards/sof_sdw.c | 18 ++++++++++++++++++ sound/soc/intel/boards/sof_sdw_common.h | 4 ++++ sound/soc/intel/boards/sof_sdw_cs42l42.c | 1 - sound/soc/intel/boards/sof_sdw_rt5682.c | 1 - sound/soc/intel/boards/sof_sdw_rt700.c | 1 - sound/soc/intel/boards/sof_sdw_rt711.c | 1 - sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 1 - .../intel/boards/sof_sdw_rt_sdca_jack_common.c | 1 - sound/soc/intel/boards/sof_ssp_common.h | 7 ------- 12 files changed, 22 insertions(+), 35 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index e5df64fec319..b7a6ac4b6c0c 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -678,7 +678,6 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE - select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_MAX98363 select SND_SOC_MAX98373_I2C select SND_SOC_MAX98373_SDW diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index a5135be94f32..586600680e84 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -630,24 +630,6 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) } EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); -struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, - const char * const dai_name[], int num_dais) -{ - struct snd_soc_dai *dai; - int index; - int i; - - for (index = 0; index < num_dais; index++) - for_each_rtd_codec_dais(rtd, i, dai) - if (strstr(dai->name, dai_name[index])) { - dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); - return dai; - } - - return NULL; -} -EXPORT_SYMBOL_NS(get_codec_dai_by_name, SND_SOC_INTEL_SOF_BOARD_HELPERS); - MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 2f27ad8726f8..b6a83ca14fa8 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -167,7 +167,4 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, struct sof_card_private * sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk); -struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, - const char * const dai_name[], int num_dais); - #endif /* __SOF_INTEL_BOARD_HELPERS_H */ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e2c1822b185f..45732884e310 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -514,6 +514,24 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; +struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, + const char * const dai_name[], + int num_dais) +{ + struct snd_soc_dai *dai; + int index; + int i; + + for (index = 0; index < num_dais; index++) + for_each_rtd_codec_dais(rtd, i, dai) + if (strstr(dai->name, dai_name[index])) { + dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); + return dai; + } + + return NULL; +} + /* these wrappers are only needed to avoid typecast compilation errors */ int sdw_startup(struct snd_pcm_substream *substream) { diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index b1d57034361c..a04cbab9bc70 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -107,6 +107,10 @@ struct mc_private { extern unsigned long sof_sdw_quirk; +struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, + const char * const dai_name[], + int num_dais); + int sdw_startup(struct snd_pcm_substream *substream); int sdw_prepare(struct snd_pcm_substream *substream); int sdw_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c index 0dc297f7de01..b999f4e7901a 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget cs42l42_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 6b008a5a343b..f812aea64322 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt5682_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 88e785a54b16..a2648c900e74 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -13,7 +13,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt700_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index cdd1587b246c..9762c48ba7a9 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" /* diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index ebb4b58c198b..9c898c7286af 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -13,7 +13,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt712_spk_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 5253d8332780..fe59a144efef 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" /* diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/sound/soc/intel/boards/sof_ssp_common.h index d24888bc99fd..ff84154ce60a 100644 --- a/sound/soc/intel/boards/sof_ssp_common.h +++ b/sound/soc/intel/boards/sof_ssp_common.h @@ -68,13 +68,6 @@ enum sof_ssp_codec { enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); -#else -static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) -{ - return NULL; -} -#endif #endif /* __SOF_SSP_COMMON_H */ From d36bfa329ae6d94e435d11960936023c03df0d64 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:02 -0500 Subject: [PATCH 07/34] ASoC: Intel: sof_sdw: Move flags to private struct Move the flags ignore_pch_dmic and append_dai_type into the drivers private structure rather than passing them around between functions. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 21 +++++++-------------- sound/soc/intel/boards/sof_sdw_common.h | 2 ++ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 45732884e310..5557db68a002 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1463,10 +1463,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct snd_soc_dai_link *dai_links, int sdw_be_num, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_codec_conf **codec_conf, - int *be_id, bool *ignore_pch_dmic, - bool append_dai_type, - int adr_index, - int dai_index) + int *be_id, int adr_index, int dai_index) { struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; @@ -1549,8 +1546,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (!codec_info) return -EINVAL; - if (codec_info->ignore_pch_dmic) - *ignore_pch_dmic = true; + ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; for_each_pcm_streams(stream) { char *name, *cpu_name; @@ -1572,7 +1568,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, } /* create stream name according to first link id */ - if (append_dai_type) { + if (ctx->append_dai_type) { name = devm_kasprintf(dev, GFP_KERNEL, sdw_stream_name[stream + 2], cpu_dai_id[0], type_strings[codec_info->dais[dai_index].dai_type]); @@ -1647,8 +1643,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; - bool append_dai_type = false; - bool ignore_pch_dmic = false; int codec_conf_num = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; @@ -1732,7 +1726,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_info) return -EINVAL; if (codec_info->dai_num > 1) { - append_dai_type = true; + ctx->append_dai_type = true; goto out; } for (j = 0; j < i; j++) { @@ -1740,7 +1734,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) SDW_PART_ID(adr_link->adr_d[j].adr)) || (SDW_MFG_ID(adr_link->adr_d[i].adr) != SDW_MFG_ID(adr_link->adr_d[j].adr))) { - append_dai_type = true; + ctx->append_dai_type = true; goto out; } } @@ -1771,8 +1765,7 @@ out: ret = create_sdw_dailink(card, &link_index, dai_links, sdw_be_num, adr_link, &codec_conf, ¤t_be_id, - &ignore_pch_dmic, - append_dai_type, i, j); + i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d\n", link_index); return ret; @@ -1825,7 +1818,7 @@ SSP: DMIC: /* dmic */ if (dmic_num > 0) { - if (ignore_pch_dmic) { + if (ctx->ignore_pch_dmic) { dev_warn(dev, "Ignoring PCH DMIC\n"); goto HDMI; } diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index a04cbab9bc70..1daf98a5849f 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -103,6 +103,8 @@ struct mc_private { struct device *amp_dev1, *amp_dev2; /* To store SDW Pin index for each SoundWire link */ unsigned int sdw_pin_index[SDW_MAX_LINKS]; + bool append_dai_type; + bool ignore_pch_dmic; }; extern unsigned long sof_sdw_quirk; From c577b747b9a0ad32047dcfa01d0ea7e2441cf590 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:03 -0500 Subject: [PATCH 08/34] ASoC: Intel: sof_sdw: Only pass dai_link pointer around Rather than passing around a pointer to the dai_link array and an index into this array, simply pass a pointer to the current dai_link. Also move the DAI link pointer sanity check to the end of the DAI link creation, and change it to a warn on. This check should only be hit if there is a serious bug in the machine driver, so checking it on each iteration is excessive. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 62 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5557db68a002..0ffa6e36dbed 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1459,8 +1459,8 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; -static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, - struct snd_soc_dai_link *dai_links, int sdw_be_num, +static int create_sdw_dailink(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_codec_conf **codec_conf, int *be_id, int adr_index, int dai_index) @@ -1597,35 +1597,28 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, cpus[k].dai_name = cpu_name; } - /* - * We create sdw dai links at first stage, so link index should - * not be larger than sdw_be_num - */ - if (*link_index >= sdw_be_num) { - dev_err(dev, "invalid dai link index %d\n", *link_index); - return -EINVAL; - } - playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); - init_dai_link(dev, dai_links + *link_index, be_id, name, - playback, capture, cpus, cpu_dai_num, codecs, codec_num, + init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, cpu_dai_num, codecs, codec_num, sof_sdw_rtd_init, &sdw_ops); /* * SoundWire DAILINKs use 'stream' functions and Bank Switch operations * based on wait_for_completion(), tag them as 'nonatomic'. */ - dai_links[*link_index].nonatomic = true; - dai_links[*link_index].ch_maps = sdw_codec_ch_maps; + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = sdw_codec_ch_maps; - ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, + ret = set_codec_init_func(card, adr_link, *dai_links, playback, group_id, adr_index, dai_index); if (ret < 0) { dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); return ret; } + + (*dai_links)++; } return 0; @@ -1646,7 +1639,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int codec_conf_num = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; - int num_links, link_index = 0; + int num_links; char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; @@ -1703,6 +1696,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_conf) return -ENOMEM; + card->dai_link = dai_links; + card->num_links = num_links; card->codec_conf = codec_conf; card->num_configs = codec_conf_num; @@ -1762,12 +1757,13 @@ out: for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; - ret = create_sdw_dailink(card, &link_index, dai_links, - sdw_be_num, adr_link, + ret = create_sdw_dailink(card, &dai_links, adr_link, &codec_conf, ¤t_be_id, i, j); if (ret < 0) { - dev_err(dev, "failed to create dai link %d\n", link_index); + dev_err(dev, + "failed to create dai link %d on 0x%x\n", + j, codec_info->part_id); return ret; } @@ -1800,19 +1796,18 @@ SSP: playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, playback, capture, cpu_dai_name, codec_name, ssp_info->dais[0].dai_name, NULL, ssp_info->ops); if (ret) return ret; - ret = ssp_info->dais[0].init(card, NULL, dai_links + link_index, - ssp_info, 0); + ret = ssp_info->dais[0].init(card, NULL, dai_links, ssp_info, 0); if (ret < 0) return ret; - link_index++; + dai_links++; } DMIC: @@ -1823,16 +1818,16 @@ DMIC: goto HDMI; } - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic01", + ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic01", 0, 1, // DMIC only supports capture "DMIC01 Pin", "dmic-codec", "dmic-hifi", sof_sdw_dmic_init, NULL); if (ret) return ret; - link_index++; + dai_links++; - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic16k", + ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic16k", 0, 1, // DMIC only supports capture "DMIC16k Pin", "dmic-codec", "dmic-hifi", /* don't call sof_sdw_dmic_init() twice */ @@ -1840,7 +1835,7 @@ DMIC: if (ret) return ret; - link_index++; + dai_links++; } HDMI: @@ -1858,14 +1853,14 @@ HDMI: codec_dai_name = "snd-soc-dummy-dai"; } - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, 1, 0, // HDMI only supports playback cpu_dai_name, codec_name, codec_dai_name, i == 0 ? sof_sdw_hdmi_init : NULL, NULL); if (ret) return ret; - link_index++; + dai_links++; } if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { @@ -1875,15 +1870,16 @@ HDMI: name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, NULL, NULL); if (ret) return ret; + + dai_links++; } - card->dai_link = dai_links; - card->num_links = num_links; + WARN_ON(dai_links != card->dai_link + card->num_links); return 0; } From 2132dbc1a99480bddb995170abaa3c3e1cf8681d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:04 -0500 Subject: [PATCH 09/34] ASoC: Intel: sof_sdw: Use for_each_set_bit Rather than open coding a loop to process each bit use for_each_set_bit. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0ffa6e36dbed..a12283d3e1cc 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -5,6 +5,7 @@ * sof_sdw - ASOC Machine driver for Intel SoundWire platforms */ +#include #include #include #include @@ -1644,7 +1645,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; - int ssp_mask; + unsigned long ssp_mask; int ret; ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); @@ -1782,12 +1783,10 @@ SSP: if (!ssp_num) goto DMIC; - for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { + j = 0; + for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { int playback, capture; - if (!(ssp_mask & 0x1)) - continue; - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", From 4d96a7f000f04e8041606f074dec5cb21bb4824d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:05 -0500 Subject: [PATCH 10/34] ASoC: Intel: sof_sdw: Factor out SSP DAI creation Factor out the creation of the SSP DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 63 +++++++++++++++++++------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index a12283d3e1cc..9980652c901b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1625,6 +1625,40 @@ static int create_sdw_dailink(struct snd_soc_card *card, return 0; } +static int create_ssp_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct sof_sdw_codec_info *ssp_info, + unsigned long ssp_mask) +{ + struct device *dev = card->dev; + int i, j = 0; + int ret; + + for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); + char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", + ssp_info->acpi_id, j++); + int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; + int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + playback, capture, cpu_dai_name, + codec_name, ssp_info->dais[0].dai_name, + NULL, ssp_info->ops); + if (ret) + return ret; + + ret = ssp_info->dais[0].init(card, NULL, *dai_links, ssp_info, 0); + if (ret < 0) + return ret; + + (*dai_links)++; + } + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1780,36 +1814,13 @@ out: SSP: /* SSP */ - if (!ssp_num) - goto DMIC; - - j = 0; - for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { - int playback, capture; - - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); - codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", - ssp_info->acpi_id, j++); - - playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; - capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - playback, capture, cpu_dai_name, - codec_name, ssp_info->dais[0].dai_name, - NULL, ssp_info->ops); + if (ssp_num) { + ret = create_ssp_dailinks(card, &dai_links, &be_id, + ssp_info, ssp_mask); if (ret) return ret; - - ret = ssp_info->dais[0].init(card, NULL, dai_links, ssp_info, 0); - if (ret < 0) - return ret; - - dai_links++; } -DMIC: /* dmic */ if (dmic_num > 0) { if (ctx->ignore_pch_dmic) { From c2473a0e50f74b1ea9cc0070048d932d9b57c3ac Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:06 -0500 Subject: [PATCH 11/34] ASoC: Intel: sof_sdw: Factor out DMIC DAI creation. Factor out the creation of the DMIC DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 53 +++++++++++++++++++------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9980652c901b..5571c9e85dd7 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1659,6 +1659,34 @@ static int create_ssp_dailinks(struct snd_soc_card *card, return 0; } +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int ret; + + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01", + 0, 1, // DMIC only supports capture + "DMIC01 Pin", "dmic-codec", "dmic-hifi", + sof_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", + 0, 1, // DMIC only supports capture + "DMIC16k Pin", "dmic-codec", "dmic-hifi", + /* don't call sof_sdw_dmic_init() twice */ + NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1825,30 +1853,13 @@ SSP: if (dmic_num > 0) { if (ctx->ignore_pch_dmic) { dev_warn(dev, "Ignoring PCH DMIC\n"); - goto HDMI; + } else { + ret = create_dmic_dailinks(card, &dai_links, &be_id); + if (ret) + return ret; } - - ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic01", - 0, 1, // DMIC only supports capture - "DMIC01 Pin", "dmic-codec", "dmic-hifi", - sof_sdw_dmic_init, NULL); - if (ret) - return ret; - - dai_links++; - - ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic16k", - 0, 1, // DMIC only supports capture - "DMIC16k Pin", "dmic-codec", "dmic-hifi", - /* don't call sof_sdw_dmic_init() twice */ - NULL, NULL); - if (ret) - return ret; - - dai_links++; } -HDMI: /* HDMI */ for (i = 0; i < hdmi_num; i++) { name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); From 914c43ab50f49656f378e748f894f9532ed19a26 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:07 -0500 Subject: [PATCH 12/34] ASoC: Intel: sof_sdw: Factor out HDMI DAI creation Factor out the creation of the HDMI DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 61 ++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5571c9e85dd7..7dc3559bf988 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1687,6 +1687,41 @@ static int create_dmic_dailinks(struct snd_soc_card *card, return 0; } +static int create_hdmi_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + int hdmi_num) +{ + struct device *dev = card->dev; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + int i, ret; + + for (i = 0; i < hdmi_num; i++) { + char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); + char *codec_name, *codec_dai_name; + + if (ctx->hdmi.idisp_codec) { + codec_name = "ehdaudio0D2"; + codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, + "intel-hdmi-hifi%d", i + 1); + } else { + codec_name = "snd-soc-dummy"; + codec_dai_name = "snd-soc-dummy-dai"; + } + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 0, // HDMI only supports playback + cpu_dai_name, codec_name, codec_dai_name, + i == 0 ? sof_sdw_hdmi_init : NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + } + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1704,7 +1739,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_dai_link *dai_links; int num_links; char *name, *cpu_dai_name; - char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; unsigned long ssp_mask; @@ -1861,28 +1895,9 @@ SSP: } /* HDMI */ - for (i = 0; i < hdmi_num; i++) { - name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); - - if (ctx->hdmi.idisp_codec) { - codec_name = "ehdaudio0D2"; - codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "intel-hdmi-hifi%d", i + 1); - } else { - codec_name = "snd-soc-dummy"; - codec_dai_name = "snd-soc-dummy-dai"; - } - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - 1, 0, // HDMI only supports playback - cpu_dai_name, codec_name, codec_dai_name, - i == 0 ? sof_sdw_hdmi_init : NULL, NULL); - if (ret) - return ret; - - dai_links++; - } + ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); + if (ret) + return ret; if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> From 0e2c1dd08607de04912b963f5df470d6a6969496 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:08 -0500 Subject: [PATCH 13/34] ASoC: Intel: sof_sdw: Factor out BlueTooth DAI creation Factor out the creation of the BlueTooth DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7dc3559bf988..6e2e934e1246 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1722,6 +1722,27 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, return 0; } +static int create_bt_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> + SOF_BT_OFFLOAD_SSP_SHIFT; + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); + int ret; + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, + snd_soc_dummy_dlc.dai_name, NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1738,7 +1759,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; - char *name, *cpu_dai_name; int i, j, be_id = 0; int hdmi_num; unsigned long ssp_mask; @@ -1899,20 +1919,11 @@ SSP: if (ret) return ret; + /* BT */ if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { - int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, - snd_soc_dummy_dlc.dai_name, NULL, NULL); + ret = create_bt_dailinks(card, &dai_links, &be_id); if (ret) return ret; - - dai_links++; } WARN_ON(dai_links != card->dai_link + card->num_links); From b48f238585a49983ae51f77d6494bcfcaad8f217 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:09 -0500 Subject: [PATCH 14/34] ASoC: Intel: sof_sdw: Factor out codec name generation In preparation for future refactoring pull out a helper specifically for generating the codec name. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 47 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6e2e934e1246..1253a2dc33d2 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1283,12 +1283,37 @@ static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, return true; } +static const char *get_codec_name(struct device *dev, + const struct sof_sdw_codec_info *codec_info, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index) +{ + u64 adr = adr_link->adr_d[adr_index].adr; + unsigned int sdw_version = SDW_VERSION(adr); + unsigned int link_id = SDW_DISCO_LINK_ID(adr); + unsigned int unique_id = SDW_UNIQUE_ID(adr); + unsigned int mfg_id = SDW_MFG_ID(adr); + unsigned int part_id = SDW_PART_ID(adr); + unsigned int class_id = SDW_CLASS_ID(adr); + + if (codec_info->codec_name) + return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); + else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, + class_id, adr_index)) + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x", + link_id, mfg_id, part_id, class_id); + else + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x", + link_id, mfg_id, part_id, class_id, unique_id); + + return NULL; +} + static int fill_sdw_codec_dlc(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_dai_link_component *codec, int adr_index, int dai_index) { - unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; u64 adr = adr_link->adr_d[adr_index].adr; struct sof_sdw_codec_info *codec_info; @@ -1296,25 +1321,7 @@ static int fill_sdw_codec_dlc(struct device *dev, if (!codec_info) return -EINVAL; - sdw_version = SDW_VERSION(adr); - link_id = SDW_DISCO_LINK_ID(adr); - unique_id = SDW_UNIQUE_ID(adr); - mfg_id = SDW_MFG_ID(adr); - part_id = SDW_PART_ID(adr); - class_id = SDW_CLASS_ID(adr); - - if (codec_info->codec_name) - codec->name = devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); - else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, - class_id, adr_index)) - codec->name = devm_kasprintf(dev, GFP_KERNEL, - "sdw:0:%01x:%04x:%04x:%02x", link_id, - mfg_id, part_id, class_id); - else - codec->name = devm_kasprintf(dev, GFP_KERNEL, - "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id, - mfg_id, part_id, class_id, unique_id); - + codec->name = get_codec_name(dev, codec_info, adr_link, adr_index); if (!codec->name) return -ENOMEM; From aa238217d69b15edc709887248eec5c01370b453 Mon Sep 17 00:00:00 2001 From: Balamurugan C Date: Tue, 26 Mar 2024 11:04:10 -0500 Subject: [PATCH 15/34] ASoC: Intel: soc-acpi-intel-arl-match: Add rt711 sdca codec support Adding rt711 sdca codec support for arl boards. Reviewed-by: Bard Liao Reviewed-by: Chao Song Signed-off-by: Balamurugan C Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-arl-match.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c index e52797aae6e6..79d26e0f2c28 100644 --- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c @@ -24,6 +24,15 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + } +}; + static const struct snd_soc_acpi_link_adr arl_rvp[] = { { .mask = BIT(0), @@ -33,6 +42,15 @@ static const struct snd_soc_acpi_link_adr arl_rvp[] = { {} }; +static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[] = { {}, }; @@ -46,6 +64,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-arl-rt711.tplg", }, + { + .link_mask = 0x1, /* link0 required */ + .links = arl_sdca_rvp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-arl-rt711-l0.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_sdw_machines); From 17750bc6519f7fb4905e63e3855e4e32b01f9419 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:11 -0500 Subject: [PATCH 16/34] ASoC: Intel: sof_sdw: Remove no longer supported quirk The SOF_SDW_NO_AGGREGATION quirk is mostly for debug and no longer works correctly with the current state of the machine driver. Remove it from the code and add an error message if someone uses it. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 12 ++++-------- sound/soc/intel/boards/sof_sdw_common.h | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1253a2dc33d2..fdedc32291f0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -36,7 +36,7 @@ static void log_quirks(struct device *dev) dev_dbg(dev, "SSP port %ld\n", SOF_SSP_GET_PORT(sof_sdw_quirk)); if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) - dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); + dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -1136,11 +1136,9 @@ static int get_dailink_info(struct device *dev, int *sdw_be_num, int *codecs_num) { bool group_visited[SDW_MAX_GROUPS]; - bool no_aggregation; int i; int j; - no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; *sdw_be_num = 0; if (!adr_link) @@ -1187,7 +1185,7 @@ static int get_dailink_info(struct device *dev, continue; /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || no_aggregation || + if (!endpoint->aggregated || !group_visited[endpoint->group_id]) (*sdw_be_num)++; } @@ -1393,10 +1391,9 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, int *codec_num, unsigned int *group_id, int adr_index) { - bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; int i; - if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) { + if (!adr_link->adr_d[adr_index].endpoints->aggregated) { cpu_dai_id[0] = ffs(adr_link->mask) - 1; *cpu_dai_num = 1; *codec_num = 1; @@ -1758,7 +1755,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; - bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; @@ -1896,7 +1892,7 @@ out: be_id = current_be_id; } - if (aggregation && endpoint->aggregated) + if (endpoint->aggregated) group_generated[endpoint->group_id] = true; } } diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 1daf98a5849f..e21ef79126b2 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -50,6 +50,7 @@ enum { #define SOF_SDW_PCH_DMIC BIT(6) #define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7) #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) +/* Deprecated and no longer supported by the code */ #define SOF_SDW_NO_AGGREGATION BIT(14) /* BT audio offload: reserve 3 bits for future */ From 8166bdd2c560e59e9a6ec0c868b996294d8428d1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:12 -0500 Subject: [PATCH 17/34] ASoC: intel: soc-acpi: Add missing cs42l43 endpoints Currently the cs42l43 just specifies a single endpoint, as the current machine driver only looks at the first endpoint specified. Future refactoring will process all endpoints, as such proper specification should be added for all the cs42l43 endpoints. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-mtl-match.c | 25 +++++++++++++++++-- .../intel/common/soc-acpi-intel-tgl-match.c | 25 +++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index e9a5da079089..e06efc5b1457 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -338,11 +338,32 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = { {} }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { { .adr = 0x00003001FA424301ull, - .num_endpoints = 1, - .endpoints = &single_endpoint, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, .name_prefix = "cs42l43" } }; diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 0fba0a60d9c7..007f1ac2327a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -414,11 +414,32 @@ static const struct snd_soc_acpi_link_adr tgl_712_only[] = { {} }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = { { .adr = 0x00033001FA424301ull, - .num_endpoints = 1, - .endpoints = &single_endpoint, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, .name_prefix = "cs42l43" } }; From 27fd36aefa0013bea1cf6948e2e825e9b8cff97a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:13 -0500 Subject: [PATCH 18/34] ASoC: Intel: sof-sdw: Add new code for parsing the snd_soc_acpi structs The current machine driver code has a lot of loops parsing through the ACPI structs (snd_soc_acpi_link_adr, snd_soc_acpi_adr_device, snd_soc_acpi_endpoint), this makes it hard to understand exactly what information is being extracted and for what purposes. As well as being slightly inefficient, as the same information is looked up multiple times. There are also some issues with the handling of multiple endpoints on a single device, only the first of the snd_soc_acpi_endpoint structures is currently fully processed by the driver. This means doing things like aggregating the second endpoint on a device with another device are not currently possible. Add new parsing code that will count the devices and endpoints, parse them into an intermediate datastructure, and then use that to create the DAI links. This patch does not actually utilise the results of the parsing, items will be moved across in the following patches. This parsing is based around two new structures which are temporarily allocated whilst parsing. Firstly, sof_sdw_endpoint, which represents a specific endpoint for audio on a device and is more or less directly equivalent to snd_soc_acpi_endpoint. Secondly, sof_sdw_dailink which represents a DAI link and contains a linked list of one or more sof_sdw_endpoints. A single trip through the snd_soc_acpi data structures is used to populate these. One important point to note here is the use of the num field in snd_soc_acpi_endpoint to address sof_sdw_dai_info array in the sof_sdw_codec_info struct. This expects a one to one mapping between endpoints on a device and dai infos. It would be fine for a specific system to not specify an endpoint for all of the dai infos available, but two endpoints mapping to the same dai info would make not sense. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 220 +++++++++++++++++++++++++++++-- 1 file changed, 206 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index fdedc32291f0..15bf8fbb3be9 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1462,8 +1462,161 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } +struct sof_sdw_endpoint { + struct list_head list; + + u32 link_mask; + const char *codec_name; + + const struct snd_soc_acpi_link_adr *adr_link; + struct sof_sdw_codec_info *codec_info; + const struct sof_sdw_dai_info *dai_info; +}; + +struct sof_sdw_dailink { + bool initialised; + + u8 group_id; + u32 link_mask[SNDRV_PCM_STREAM_LAST + 1]; + int num_devs[SNDRV_PCM_STREAM_LAST + 1]; + struct list_head endpoints; +}; + static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; +static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + const struct snd_soc_acpi_link_adr *adr_link; + int i; + + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + *num_devs += adr_link->num_adr; + + for (i = 0; i < adr_link->num_adr; i++) + *num_ends += adr_link->adr_d[i].num_endpoints; + } + + dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends); + + return 0; +} + +static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks, + const struct snd_soc_acpi_endpoint *new) +{ + while (dailinks->initialised) { + if (new->aggregated && dailinks->group_id == new->group_id) + return dailinks; + + dailinks++; + } + + INIT_LIST_HEAD(&dailinks->endpoints); + dailinks->group_id = new->group_id; + dailinks->initialised = true; + + return dailinks; +} + +static int parse_sdw_endpoints(struct snd_soc_card *card, + struct sof_sdw_dailink *sof_dais, + struct sof_sdw_endpoint *sof_ends) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + const struct snd_soc_acpi_link_adr *adr_link; + struct sof_sdw_endpoint *sof_end = sof_ends; + int num_dais = 0; + int i, j; + + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + if (!is_power_of_2(adr_link->mask)) { + dev_err(dev, "link with multiple mask bits: 0x%x\n", + adr_link->mask); + return -EINVAL; + } + + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i]; + struct sof_sdw_codec_info *codec_info; + const char *codec_name; + + if (!adr_dev->name_prefix) { + dev_err(dev, "codec 0x%llx does not have a name prefix\n", + adr_dev->adr); + return -EINVAL; + } + + codec_info = find_codec_info_part(adr_dev->adr); + if (!codec_info) + return -EINVAL; + + codec_name = get_codec_name(dev, codec_info, adr_link, i); + if (!codec_name) + return -ENOMEM; + + for (j = 0; j < adr_dev->num_endpoints; j++) { + const struct snd_soc_acpi_endpoint *adr_end; + const struct sof_sdw_dai_info *dai_info; + struct sof_sdw_dailink *sof_dai; + int stream; + + adr_end = &adr_dev->endpoints[j]; + dai_info = &codec_info->dais[adr_end->num]; + sof_dai = find_dailink(sof_dais, adr_end); + + dev_dbg(dev, + "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", + ffs(adr_link->mask) - 1, adr_dev->adr, + adr_end->num, type_strings[dai_info->dai_type], + dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-', + dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-', + adr_end->aggregated ? "group" : "solo", + adr_end->group_id); + + if (adr_end->num >= codec_info->dai_num) { + dev_err(dev, + "%d is too many endpoints for codec: 0x%x\n", + adr_end->num, codec_info->part_id); + return -EINVAL; + } + + for_each_pcm_streams(stream) { + if (dai_info->direction[stream] && + dai_info->dailink[stream] < 0) { + dev_err(dev, + "Invalid dailink id %d for codec: 0x%x\n", + dai_info->dailink[stream], + codec_info->part_id); + return -EINVAL; + } + + if (dai_info->direction[stream]) { + num_dais += !sof_dai->num_devs[stream]; + sof_dai->num_devs[stream]++; + sof_dai->link_mask[stream] |= adr_link->mask; + } + } + + list_add_tail(&sof_end->list, &sof_dai->endpoints); + + sof_end->link_mask = adr_link->mask; + sof_end->codec_name = codec_name; + sof_end->adr_link = adr_link; + sof_end->codec_info = codec_info; + sof_end->dai_info = dai_info; + sof_end++; + } + } + } + + return num_dais; +} + static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, @@ -1758,7 +1911,11 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; + struct sof_sdw_endpoint *sof_ends; + struct sof_sdw_dailink *sof_dais; int codec_conf_num = 0; + int num_devs = 0; + int num_ends = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; @@ -1767,10 +1924,32 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) unsigned long ssp_mask; int ret; + ret = count_sdw_endpoints(card, &num_devs, &num_ends); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + /* One per DAI link, worst case is a DAI link for every endpoint */ + sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); + if (!sof_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); + if (!sof_ends) { + ret = -ENOMEM; + goto err_dai; + } + + ret = parse_sdw_endpoints(card, sof_dais, sof_ends); + if (ret < 0) + goto err_end; + ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); if (ret < 0) { dev_err(dev, "failed to get sdw link info %d\n", ret); - return ret; + goto err_end; } /* @@ -1807,14 +1986,18 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) /* allocate BE dailinks */ num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); - if (!dai_links) - return -ENOMEM; + if (!dai_links) { + ret = -ENOMEM; + goto err_end; + } /* allocate codec conf, will be populated when dailinks are created */ codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), GFP_KERNEL); - if (!codec_conf) - return -ENOMEM; + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } card->dai_link = dai_links; card->num_links = num_links; @@ -1838,8 +2021,10 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) for (i = 0; i < adr_link->num_adr; i++) { /* find codec info to get dai_num */ codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; + if (!codec_info) { + ret = -EINVAL; + goto err_end; + } if (codec_info->dai_num > 1) { ctx->append_dai_type = true; goto out; @@ -1871,8 +2056,10 @@ out: /* find codec info to get dai_num */ codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; + if (!codec_info) { + ret = -EINVAL; + goto err_end; + } for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; @@ -1903,7 +2090,7 @@ SSP: ret = create_ssp_dailinks(card, &dai_links, &be_id, ssp_info, ssp_mask); if (ret) - return ret; + goto err_end; } /* dmic */ @@ -1913,25 +2100,30 @@ SSP: } else { ret = create_dmic_dailinks(card, &dai_links, &be_id); if (ret) - return ret; + goto err_end; } } /* HDMI */ ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); if (ret) - return ret; + goto err_end; /* BT */ if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { ret = create_bt_dailinks(card, &dai_links, &be_id); if (ret) - return ret; + goto err_end; } WARN_ON(dai_links != card->dai_link + card->num_links); - return 0; +err_end: + kfree(sof_ends); +err_dai: + kfree(sof_dais); + + return ret; } static int sof_sdw_card_late_probe(struct snd_soc_card *card) From 0d7b9880db92e1eb07bdd4dc097e574512b894a9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:14 -0500 Subject: [PATCH 19/34] ASoC: Intel: sof_sdw: Move counting and codec_conf to new parsing Use the output of the new snd_soc_acpi struct parsing for the purposes of counting the number of SoundWire DAI links and physical devices attached to the SoundWire. These counts are already returned by the parser so those can just be used directly. But the population of the codec_conf structures, is moved from the old parsing code over to the new. As the two parsers currently co-exist it is better to not have them both attempt to modify the same structures. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 124 ++++++------------------------- 1 file changed, 22 insertions(+), 102 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 15bf8fbb3be9..0566ab843c2e 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1126,79 +1126,6 @@ static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, return NULL; } -/* - * get BE dailink number and CPU DAI number based on sdw link adr. - * Since some sdw slaves may be aggregated, the CPU DAI number - * may be larger than the number of BE dailinks. - */ -static int get_dailink_info(struct device *dev, - const struct snd_soc_acpi_link_adr *adr_link, - int *sdw_be_num, int *codecs_num) -{ - bool group_visited[SDW_MAX_GROUPS]; - int i; - int j; - - *sdw_be_num = 0; - - if (!adr_link) - return -EINVAL; - - for (i = 0; i < SDW_MAX_GROUPS; i++) - group_visited[i] = false; - - for (; adr_link->num_adr; adr_link++) { - const struct snd_soc_acpi_endpoint *endpoint; - struct sof_sdw_codec_info *codec_info; - int stream; - u64 adr; - - /* make sure the link mask has a single bit set */ - if (!is_power_of_2(adr_link->mask)) - return -EINVAL; - - for (i = 0; i < adr_link->num_adr; i++) { - adr = adr_link->adr_d[i].adr; - codec_info = find_codec_info_part(adr); - if (!codec_info) - return -EINVAL; - - *codecs_num += codec_info->dai_num; - - if (!adr_link->adr_d[i].name_prefix) { - dev_err(dev, "codec 0x%llx does not have a name prefix\n", - adr_link->adr_d[i].adr); - return -EINVAL; - } - - endpoint = adr_link->adr_d[i].endpoints; - if (endpoint->aggregated && !endpoint->group_id) { - dev_err(dev, "invalid group id on link %x\n", - adr_link->mask); - return -EINVAL; - } - - for (j = 0; j < codec_info->dai_num; j++) { - /* count DAI number for playback and capture */ - for_each_pcm_streams(stream) { - if (!codec_info->dais[j].direction[stream]) - continue; - - /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || - !group_visited[endpoint->group_id]) - (*sdw_be_num)++; - } - } - - if (endpoint->aggregated) - group_visited[endpoint->group_id] = true; - } - } - - return 0; -} - static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, int *be_id, char *name, int playback, int capture, struct snd_soc_dai_link_component *cpus, int cpus_num, @@ -1528,6 +1455,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct device *dev = card->dev; struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + struct snd_soc_codec_conf *codec_conf = card->codec_conf; const struct snd_soc_acpi_link_adr *adr_link; struct sof_sdw_endpoint *sof_end = sof_ends; int num_dais = 0; @@ -1559,6 +1487,13 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, if (!codec_name) return -ENOMEM; + codec_conf->dlc.name = codec_name; + codec_conf->name_prefix = adr_dev->name_prefix; + codec_conf++; + + dev_dbg(dev, "Adding prefix %s for %s\n", + adr_dev->name_prefix, codec_name); + for (j = 0; j < adr_dev->num_endpoints; j++) { const struct snd_soc_acpi_endpoint *adr_end; const struct sof_sdw_dai_info *dai_info; @@ -1614,13 +1549,14 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } } + WARN_ON(codec_conf != card->codec_conf + card->num_configs); + return num_dais; } static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_codec_conf **codec_conf, int *be_id, int adr_index, int dai_index) { struct mc_private *ctx = snd_soc_card_get_drvdata(card); @@ -1672,26 +1608,16 @@ static int create_sdw_dailink(struct snd_soc_card *card, endpoints->group_id != group_id)) continue; - /* sanity check */ - if (*codec_conf >= card->codec_conf + card->num_configs) { - dev_err(dev, "codec_conf array overflowed\n"); - return -EINVAL; - } - ret = fill_sdw_codec_dlc(dev, adr_link_next, &codecs[codec_dlc_index], j, dai_index); if (ret) return ret; - (*codec_conf)->dlc = codecs[codec_dlc_index]; - (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; - sdw_codec_ch_maps[codec_dlc_index].cpu = i; sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; codec_dlc_index++; - (*codec_conf)++; } j = 0; @@ -1913,7 +1839,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct sof_sdw_codec_info *ssp_info; struct sof_sdw_endpoint *sof_ends; struct sof_sdw_dailink *sof_dais; - int codec_conf_num = 0; int num_devs = 0; int num_ends = 0; bool group_generated[SDW_MAX_GROUPS] = { }; @@ -1942,15 +1867,21 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_dai; } + /* will be populated when acpi endpoints are parsed */ + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } + + card->codec_conf = codec_conf; + card->num_configs = num_devs; + ret = parse_sdw_endpoints(card, sof_dais, sof_ends); if (ret < 0) goto err_end; - ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); - if (ret < 0) { - dev_err(dev, "failed to get sdw link info %d\n", ret); - goto err_end; - } + sdw_be_num = ret; /* * on generic tgl platform, I2S or sdw mode is supported @@ -1991,18 +1922,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_end; } - /* allocate codec conf, will be populated when dailinks are created */ - codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), - GFP_KERNEL); - if (!codec_conf) { - ret = -ENOMEM; - goto err_end; - } - card->dai_link = dai_links; card->num_links = num_links; - card->codec_conf = codec_conf; - card->num_configs = codec_conf_num; /* SDW */ if (!sdw_be_num) @@ -2065,8 +1986,7 @@ out: int current_be_id; ret = create_sdw_dailink(card, &dai_links, adr_link, - &codec_conf, ¤t_be_id, - i, j); + ¤t_be_id, i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d on 0x%x\n", From 22f2a5e71030c5da938c4d3c50f2159582ee2362 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:15 -0500 Subject: [PATCH 20/34] ASoC: Intel: sof_sdw: Move ignore_pch_dmic to new parsing Trivial move of the handling of ignore_pch_dmic over to the new parsing code. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0566ab843c2e..cda759ee6345 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1453,6 +1453,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct sof_sdw_endpoint *sof_ends) { struct device *dev = card->dev; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; struct snd_soc_codec_conf *codec_conf = card->codec_conf; @@ -1483,6 +1484,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, if (!codec_info) return -EINVAL; + ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; + codec_name = get_codec_name(dev, codec_info, adr_link, i); if (!codec_name) return -ENOMEM; @@ -1630,8 +1633,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, if (!codec_info) return -EINVAL; - ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; - for_each_pcm_streams(stream) { char *name, *cpu_name; int playback, capture; From 13e698e8ee70cebfcaead8188e77d3e90f94498d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:16 -0500 Subject: [PATCH 21/34] ASoC: Intel: sof_sdw: Move append_dai_type to new parsing append_dai_type should be set to true in any situation that would result in multiple DAI links existing on a single SoundWire bus, because the legacy naming used only the bus number to make things unique. The current code handles this by looking for codecs with multiple dai_info structs and looking for buses that include multiple types of device on them. The first of these assumes that all DAIs on a given device would be in use. The second, with dissimilar aggregation now being supported, isn't really an accurate check either since those devices could be aggregated into a single DAI link. Move the handling for this flag over to the new parsing code and simplify things a little by looking directly for SoundWire links that will contain multiple DAI links to set the flag. These changes should not cause any change in behaviour for any currently supported systems. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 36 +++++--------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index cda759ee6345..89ce77961634 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1463,6 +1463,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, int i, j; for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + int num_link_dailinks = 0; + if (!is_power_of_2(adr_link->mask)) { dev_err(dev, "link with multiple mask bits: 0x%x\n", adr_link->mask); @@ -1540,6 +1542,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } } + num_link_dailinks += !!list_empty(&sof_dai->endpoints); list_add_tail(&sof_end->list, &sof_dai->endpoints); sof_end->link_mask = adr_link->mask; @@ -1550,6 +1553,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, sof_end++; } } + + ctx->append_dai_type |= (num_link_dailinks > 1); } WARN_ON(codec_conf != card->codec_conf + card->num_configs); @@ -1933,37 +1938,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) for (i = 0; i < SDW_MAX_LINKS; i++) ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; - for (; adr_link->num_adr; adr_link++) { - /* - * If there are two or more different devices on the same sdw link, we have to - * append the codec type to the dai link name to prevent duplicated dai link name. - * The same type devices on the same sdw link will be in the same - * snd_soc_acpi_adr_device array. They won't be described in different adr_links. - */ - for (i = 0; i < adr_link->num_adr; i++) { - /* find codec info to get dai_num */ - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) { - ret = -EINVAL; - goto err_end; - } - if (codec_info->dai_num > 1) { - ctx->append_dai_type = true; - goto out; - } - for (j = 0; j < i; j++) { - if ((SDW_PART_ID(adr_link->adr_d[i].adr) != - SDW_PART_ID(adr_link->adr_d[j].adr)) || - (SDW_MFG_ID(adr_link->adr_d[i].adr) != - SDW_MFG_ID(adr_link->adr_d[j].adr))) { - ctx->append_dai_type = true; - goto out; - } - } - } - } -out: - /* generate DAI links by each sdw link */ for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { for (i = 0; i < adr_link->num_adr; i++) { From 5f14d70b7f6e9deb97893d5c09dd0986e92b7021 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:17 -0500 Subject: [PATCH 22/34] ASoC: Intel: sof_sdw: Move generation of DAI links to new parsing The only part left using the old parsing code is now the generation of the actual DAI links. Move this generation over to being based on the new parsing, which allows the removal of the last of the old parsing code. The new DAI link generation is a simple matter of creating a new DAI link for each sof_sdw_dailink struct, and adding a cpu, a codec, and a mapping for each sof_sdw_endpoint contained in that sof_sdw_dailink. Note that the CPUs can be inferred as the endpoint list is iterated, because the endpoints were added into the list sorted by link. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 338 +++++++------------------------ 1 file changed, 77 insertions(+), 261 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 89ce77961634..9f1c49df9cd2 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1234,129 +1234,6 @@ static const char *get_codec_name(struct device *dev, return NULL; } -static int fill_sdw_codec_dlc(struct device *dev, - const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_dai_link_component *codec, - int adr_index, int dai_index) -{ - u64 adr = adr_link->adr_d[adr_index].adr; - struct sof_sdw_codec_info *codec_info; - - codec_info = find_codec_info_part(adr); - if (!codec_info) - return -EINVAL; - - codec->name = get_codec_name(dev, codec_info, adr_link, adr_index); - if (!codec->name) - return -ENOMEM; - - codec->dai_name = codec_info->dais[dai_index].dai_name; - - return 0; -} - -static int set_codec_init_func(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_dai_link *dai_links, - bool playback, int group_id, int adr_index, int dai_index) -{ - int i = adr_index; - - do { - /* - * Initialize the codec. If codec is part of an aggregated - * group (group_id>0), initialize all codecs belonging to - * same group. - * The first link should start with adr_link->adr_d[adr_index] - * because that is the device that we want to initialize and - * we should end immediately if it is not aggregated (group_id=0) - */ - for ( ; i < adr_link->num_adr; i++) { - struct sof_sdw_codec_info *codec_info; - - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; - - /* The group_id is > 0 iff the codec is aggregated */ - if (adr_link->adr_d[i].endpoints->group_id != group_id) - continue; - - if (codec_info->dais[dai_index].init) - codec_info->dais[dai_index].init(card, - adr_link, - dai_links, - codec_info, - playback); - if (!group_id) - return 0; - } - - i = 0; - adr_link++; - } while (adr_link->mask); - - return 0; -} - -/* - * check endpoint status in slaves and gather link ID for all slaves in - * the same group to generate different CPU DAI. Now only support - * one sdw link with all slaves set with only single group id. - * - * one slave on one sdw link with aggregated = 0 - * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI - * - * two or more slaves on one sdw link with aggregated = 0 - * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs - * - * multiple links with multiple slaves with aggregated = 1 - * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs - */ -static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, - struct device *dev, int *cpu_dai_id, int *cpu_dai_num, - int *codec_num, unsigned int *group_id, - int adr_index) -{ - int i; - - if (!adr_link->adr_d[adr_index].endpoints->aggregated) { - cpu_dai_id[0] = ffs(adr_link->mask) - 1; - *cpu_dai_num = 1; - *codec_num = 1; - *group_id = 0; - return 0; - } - - *codec_num = 0; - *cpu_dai_num = 0; - *group_id = adr_link->adr_d[adr_index].endpoints->group_id; - - /* Count endpoints with the same group_id in the adr_link */ - for (; adr_link && adr_link->num_adr; adr_link++) { - unsigned int link_codecs = 0; - - for (i = 0; i < adr_link->num_adr; i++) { - if (adr_link->adr_d[i].endpoints->aggregated && - adr_link->adr_d[i].endpoints->group_id == *group_id) - link_codecs++; - } - - if (link_codecs) { - *codec_num += link_codecs; - - if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) { - dev_err(dev, "cpu_dai_id array overflowed\n"); - return -EINVAL; - } - - cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; - } - } - - return 0; -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; @@ -1563,135 +1440,102 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } static int create_sdw_dailink(struct snd_soc_card *card, + struct sof_sdw_dailink *sof_dai, struct snd_soc_dai_link **dai_links, - const struct snd_soc_acpi_link_adr *adr_link, - int *be_id, int adr_index, int dai_index) + int *be_id) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; - const struct snd_soc_acpi_link_adr *adr_link_next; - struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; - struct snd_soc_dai_link_component *codecs; - struct snd_soc_dai_link_component *cpus; - struct sof_sdw_codec_info *codec_info; - int cpu_dai_id[SDW_MAX_CPU_DAIS]; - int cpu_dai_num; - unsigned int group_id; - int codec_dlc_index = 0; - int codec_num; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_sdw_endpoint *sof_end; int stream; - int i = 0; - int j, k; - int ret; - - ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, - &group_id, adr_index); - if (ret) - return ret; - - codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); - if (!codecs) - return -ENOMEM; - - sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, - sizeof(*sdw_codec_ch_maps), GFP_KERNEL); - if (!sdw_codec_ch_maps) - return -ENOMEM; - - /* generate codec name on different links in the same group */ - j = adr_index; - for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && - i < cpu_dai_num; adr_link_next++) { - /* skip the link excluded by this processed group */ - if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) - continue; - - /* j reset after loop, adr_index only applies to first link */ - for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) { - const struct snd_soc_acpi_endpoint *endpoints; - - endpoints = adr_link_next->adr_d[j].endpoints; - - if (group_id && (!endpoints->aggregated || - endpoints->group_id != group_id)) - continue; - - ret = fill_sdw_codec_dlc(dev, adr_link_next, - &codecs[codec_dlc_index], - j, dai_index); - if (ret) - return ret; - - sdw_codec_ch_maps[codec_dlc_index].cpu = i; - sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; - - codec_dlc_index++; - } - j = 0; - - /* check next link to create codec dai in the processed group */ - i++; - } - - /* find codec info to create BE DAI */ - codec_info = find_codec_info_part(adr_link->adr_d[adr_index].adr); - if (!codec_info) - return -EINVAL; for_each_pcm_streams(stream) { - char *name, *cpu_name; - int playback, capture; static const char * const sdw_stream_name[] = { "SDW%d-Playback", "SDW%d-Capture", "SDW%d-Playback-%s", "SDW%d-Capture-%s", }; + struct snd_soc_dai_link_ch_map *codec_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + int num_cpus = hweight32(sof_dai->link_mask[stream]); + int num_codecs = sof_dai->num_devs[stream]; + int playback, capture; + int cur_link = 0; + int i = 0, j = 0; + char *name; - if (!codec_info->dais[dai_index].direction[stream]) + if (!sof_dai->num_devs[stream]) continue; - *be_id = codec_info->dais[dai_index].dailink[stream]; + sof_end = list_first_entry(&sof_dai->endpoints, + struct sof_sdw_endpoint, list); + + *be_id = sof_end->dai_info->dailink[stream]; if (*be_id < 0) { dev_err(dev, "Invalid dailink id %d\n", *be_id); return -EINVAL; } /* create stream name according to first link id */ - if (ctx->append_dai_type) { + if (ctx->append_dai_type) name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream + 2], cpu_dai_id[0], - type_strings[codec_info->dais[dai_index].dai_type]); - } else { + sdw_stream_name[stream + 2], + ffs(sof_end->link_mask) - 1, + type_strings[sof_end->dai_info->dai_type]); + else name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], cpu_dai_id[0]); - } + sdw_stream_name[stream], + ffs(sof_end->link_mask) - 1); if (!name) return -ENOMEM; - cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL); + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); if (!cpus) return -ENOMEM; - /* - * generate CPU DAI name base on the sdw link ID and - * PIN ID with offset of 2 according to sdw dai driver. - */ - for (k = 0; k < cpu_dai_num; k++) { - cpu_name = devm_kasprintf(dev, GFP_KERNEL, - "SDW%d Pin%d", cpu_dai_id[k], - ctx->sdw_pin_index[cpu_dai_id[k]]++); - if (!cpu_name) - return -ENOMEM; + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; - cpus[k].dai_name = cpu_name; + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); + if (!codec_maps) + return -ENOMEM; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (!sof_end->dai_info->direction[stream]) + continue; + + if (cur_link != sof_end->link_mask) { + int link_num = ffs(sof_end->link_mask) - 1; + int pin_num = ctx->sdw_pin_index[link_num]++; + + cur_link = sof_end->link_mask; + + cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", + link_num, pin_num); + if (!cpus[i].dai_name) + return -ENOMEM; + i++; + } + + codec_maps[j].cpu = i - 1; + codec_maps[j].codec = j; + + codecs[j].name = sof_end->codec_name; + codecs[j].dai_name = sof_end->dai_info->dai_name; + j++; } + WARN_ON(i != num_cpus || j != num_codecs); + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); init_dai_link(dev, *dai_links, be_id, name, playback, capture, - cpus, cpu_dai_num, codecs, codec_num, + cpus, num_cpus, codecs, num_codecs, sof_sdw_rtd_init, &sdw_ops); /* @@ -1699,13 +1543,14 @@ static int create_sdw_dailink(struct snd_soc_card *card, * based on wait_for_completion(), tag them as 'nonatomic'. */ (*dai_links)->nonatomic = true; - (*dai_links)->ch_maps = sdw_codec_ch_maps; + (*dai_links)->ch_maps = codec_maps; - ret = set_codec_init_func(card, adr_link, *dai_links, - playback, group_id, adr_index, dai_index); - if (ret < 0) { - dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); - return ret; + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (sof_end->dai_info->init) + sof_end->dai_info->init(card, sof_end->adr_link, + *dai_links, + sof_end->codec_info, + playback); } (*dai_links)++; @@ -1839,18 +1684,15 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; - const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; struct snd_soc_codec_conf *codec_conf; - struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; struct sof_sdw_endpoint *sof_ends; struct sof_sdw_dailink *sof_dais; int num_devs = 0; int num_ends = 0; - bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; - int i, j, be_id = 0; + int i, be_id = 0; int hdmi_num; unsigned long ssp_mask; int ret; @@ -1939,44 +1781,18 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; /* generate DAI links by each sdw link */ - for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { - for (i = 0; i < adr_link->num_adr; i++) { - const struct snd_soc_acpi_endpoint *endpoint; + while (sof_dais->initialised) { + int current_be_id; - endpoint = adr_link->adr_d[i].endpoints; + ret = create_sdw_dailink(card, sof_dais, &dai_links, ¤t_be_id); + if (ret) + goto err_end; - /* this group has been generated */ - if (endpoint->aggregated && - group_generated[endpoint->group_id]) - continue; + /* Update the be_id to match the highest ID used for SDW link */ + if (be_id < current_be_id) + be_id = current_be_id; - /* find codec info to get dai_num */ - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) { - ret = -EINVAL; - goto err_end; - } - - for (j = 0; j < codec_info->dai_num ; j++) { - int current_be_id; - - ret = create_sdw_dailink(card, &dai_links, adr_link, - ¤t_be_id, i, j); - if (ret < 0) { - dev_err(dev, - "failed to create dai link %d on 0x%x\n", - j, codec_info->part_id); - return ret; - } - - /* Update the be_id to match the highest ID used for SDW link */ - if (be_id < current_be_id) - be_id = current_be_id; - } - - if (endpoint->aggregated) - group_generated[endpoint->group_id] = true; - } + sof_dais++; } SSP: From 59bf457d80551003a06d32f5c3d1da7f64a3d420 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:18 -0500 Subject: [PATCH 23/34] ASoC: intel: sof_sdw: Factor out SoundWire DAI creation Factor out the creation of the SoundWire DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 50 ++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9f1c49df9cd2..3e6a758c98ab 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1559,6 +1559,34 @@ static int create_sdw_dailink(struct snd_soc_card *card, return 0; } +static int create_sdw_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct sof_sdw_dailink *sof_dais) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + int ret, i; + + for (i = 0; i < SDW_MAX_LINKS; i++) + ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; + + /* generate DAI links by each sdw link */ + while (sof_dais->initialised) { + int current_be_id; + + ret = create_sdw_dailink(card, sof_dais, dai_links, ¤t_be_id); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + sof_dais++; + } + + return 0; +} + static int create_ssp_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, struct sof_sdw_codec_info *ssp_info, @@ -1692,7 +1720,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int num_ends = 0; struct snd_soc_dai_link *dai_links; int num_links; - int i, be_id = 0; + int be_id = 0; int hdmi_num; unsigned long ssp_mask; int ret; @@ -1774,28 +1802,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) card->num_links = num_links; /* SDW */ - if (!sdw_be_num) - goto SSP; - - for (i = 0; i < SDW_MAX_LINKS; i++) - ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; - - /* generate DAI links by each sdw link */ - while (sof_dais->initialised) { - int current_be_id; - - ret = create_sdw_dailink(card, sof_dais, &dai_links, ¤t_be_id); + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais); if (ret) goto err_end; - - /* Update the be_id to match the highest ID used for SDW link */ - if (be_id < current_be_id) - be_id = current_be_id; - - sof_dais++; } -SSP: /* SSP */ if (ssp_num) { ret = create_ssp_dailinks(card, &dai_links, &be_id, From bee2fe44679f1e6a5332d7f78587ccca4109919f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:19 -0500 Subject: [PATCH 24/34] ASoC: Intel: sof_sdw: use generic rtd_init function for Realtek SDW DMICs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only thing that the rt_xxx_rtd_init() functions do is to set card->components. And we can set card->components with name_prefix as rt712_sdca_dmic_rtd_init() does. And sof_sdw_rtd_init() will always select the first dai with the given dai->name from codec_info_list[]. Unfortunately, we have different codecs with the same dai name. For example, dai name of rt715 and rt715-sdca are both "rt715-aif2". Using a generic rtd_init allow sof_sdw_rtd_init() run the rtd_init() callback from a similar codec dai. Fixes: 8266c73126b7 ("ASoC: Intel: sof_sdw: add common sdw dai link init") Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-25-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 1 + sound/soc/intel/boards/sof_sdw.c | 12 +++--- sound/soc/intel/boards/sof_sdw_common.h | 1 + sound/soc/intel/boards/sof_sdw_rt_dmic.c | 52 ++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 sound/soc/intel/boards/sof_sdw_rt_dmic.c diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index bbf796a5f7ba..08cfd4baecdd 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -42,6 +42,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ + sof_sdw_rt_dmic.o \ sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ sof_sdw_cs_amp.o \ sof_sdw_dmic.o \ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 3e6a758c98ab..0e376cb0ce0b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -749,7 +749,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt712-sdca-dmic-aif1", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt712_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -779,7 +779,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt712-sdca-dmic-aif1", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt712_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -841,7 +841,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_sdca_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -856,7 +856,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_sdca_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -871,7 +871,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -886,7 +886,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index e21ef79126b2..decaed97fa74 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -197,6 +197,7 @@ int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c new file mode 100644 index 000000000000..9091f5b5c648 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2024 Intel Corporation + +/* + * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver + */ + +#include +#include +#include +#include +#include "sof_board_helpers.h" +#include "sof_sdw_common.h" + +static const char * const dmics[] = { + "rt715", + "rt712-sdca-dmic", +}; + +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_component *component; + struct snd_soc_dai *codec_dai; + char *mic_name; + + codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); + if (!codec_dai) + return -EINVAL; + + component = codec_dai->component; + + /* + * rt715-sdca (aka rt714) is a special case that uses different name in card->components + * and component->name_prefix. + */ + if (!strcmp(component->name_prefix, "rt714")) + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca"); + else + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix); + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:%s", card->components, + mic_name); + if (!card->components) + return -ENOMEM; + + dev_dbg(card->dev, "card->components: %s\n", card->components); + + return 0; +} +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); From 45bbc14fb94698b43636ec18d0df2440934139e7 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:20 -0500 Subject: [PATCH 25/34] ASoC: Intel: sof_sdw: remove unused rt dmic rtd_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Realtek SDW DMIC codecs use the generic rt_dmic_rtd_init callback now. Remove unused rtd_init callbacks. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-26-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 3 +-- sound/soc/intel/boards/sof_sdw_common.h | 3 --- sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 24 ------------------- sound/soc/intel/boards/sof_sdw_rt715.c | 26 --------------------- sound/soc/intel/boards/sof_sdw_rt715_sdca.c | 26 --------------------- 5 files changed, 1 insertion(+), 81 deletions(-) delete mode 100644 sound/soc/intel/boards/sof_sdw_rt715.c delete mode 100644 sound/soc/intel/boards/sof_sdw_rt715_sdca.c diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 08cfd4baecdd..8f711be46c43 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -40,8 +40,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_maxim.o sof_sdw_rt_amp.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ - sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ - sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ + sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \ sof_sdw_rt_dmic.o \ sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ sof_sdw_cs_amp.o \ diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index decaed97fa74..84715d9ca942 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -193,10 +193,7 @@ int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index 9c898c7286af..0c4cd4cdbd45 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -66,27 +66,3 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static const char * const dmics[] = { - "rt712-sdca-dmic" -}; - -int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai; - struct snd_soc_component *component; - - codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); - if (!codec_dai) - return -EINVAL; - - component = codec_dai->component; - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:%s", - card->components, component->name_prefix); - if (!card->components) - return -ENOMEM; - - return 0; -} -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c deleted file mode 100644 index b5a886cd595d..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt715.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt715 - Helpers to handle RT715 from generic machine driver - */ - -#include -#include -#include -#include -#include "sof_sdw_common.h" - -int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:rt715", - card->components); - if (!card->components) - return -ENOMEM; - - return 0; -} - diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c deleted file mode 100644 index 4b37a8a6dd2e..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA from generic machine driver - */ - -#include -#include -#include -#include -#include "sof_sdw_common.h" - -int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:rt715-sdca", - card->components); - if (!card->components) - return -ENOMEM; - - return 0; -} - From 266c9b27cb0a2c11de5956ee4bd7e1266d0baa36 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:21 -0500 Subject: [PATCH 26/34] ASoC: Intel: sof_sdw_rt722_sdca: set rtd_init in codec_info_list[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add rt722 into rt_sdca_jack_rtd_init() supported list, and set rtd_init callback directly in codec_info_list[]. No need to use a init callback to set the rtd_init callback. Besides, sof_sdw_rt_sdca_jack_init() doesn't set .rtd_init anymore. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-27-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 ++-- sound/soc/intel/boards/sof_sdw_common.h | 14 ++-------- sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 26 ++----------------- .../boards/sof_sdw_rt_sdca_jack_common.c | 2 +- 4 files changed, 8 insertions(+), 39 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0e376cb0ce0b..bb8429a83467 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -902,6 +902,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, + .rtd_init = rt_sdca_jack_rtd_init, }, { .direction = {true, false}, @@ -909,14 +910,14 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_AMP, /* No feedback capability is provided by rt722-sdca codec driver*/ .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_rt722_spk_init, + .rtd_init = rt722_spk_rtd_init, }, { .direction = {false, true}, .dai_name = "rt722-sdca-aif3", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .init = sof_sdw_rt722_sdca_dmic_init, + .rtd_init = rt722_sdca_dmic_rtd_init, }, }, .dai_num = 3, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 84715d9ca942..315b2a298195 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -157,18 +157,6 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card, bool playback); int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); -/* RT722-SDCA support */ -int sof_sdw_rt722_spk_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - /* MAXIM codec support */ int sof_sdw_maxim_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, @@ -194,6 +182,8 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index fe3a2bff95bc..4947d16c70db 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -27,7 +27,7 @@ static const struct snd_kcontrol_new rt722_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; -static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd) +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int ret; @@ -59,18 +59,7 @@ static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt722_spk_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - dai_links->init = rt722_spk_init; - - return 0; -} - -static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); @@ -84,14 +73,3 @@ static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } - -int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - dai_links->init = rt722_sdca_dmic_rtd_init; - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index fe59a144efef..006771485486 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -85,7 +85,7 @@ static struct snd_soc_jack_pin rt_sdca_jack_pins[] = { }; static const char * const jack_codecs[] = { - "rt711", "rt712", "rt713" + "rt711", "rt712", "rt713", "rt722" }; int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) From df19c6cd0fd0418b779f9c627b159d7ab77bff71 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:22 -0500 Subject: [PATCH 27/34] ASoC: Intel: sof_sdw_rt722_sdca: use rt_dmic_rtd_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rt_dmic_rtd_init() can be used for rt722 dmic, too. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-28-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/intel/boards/sof_sdw_common.h | 1 - sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 14 -------------- sound/soc/intel/boards/sof_sdw_rt_dmic.c | 1 + 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index bb8429a83467..3874da8d7fe4 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -917,7 +917,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt722-sdca-aif3", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt722_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 3, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 315b2a298195..2132d3fc42f8 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -183,7 +183,6 @@ int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index 4947d16c70db..e5c2a36e400b 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -59,17 +59,3 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct snd_soc_component *component = codec_dai->component; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:%s", - card->components, component->name_prefix); - if (!card->components) - return -ENOMEM; - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c index 9091f5b5c648..5aec8422656c 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -15,6 +15,7 @@ static const char * const dmics[] = { "rt715", "rt712-sdca-dmic", + "rt722-sdca", }; int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) From 13112a34d83e0b3c925ff9818e0819ad2fe97e42 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:23 -0500 Subject: [PATCH 28/34] ASoC: rt715-sdca: rename dai name with rt715-sdca prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dai name are the same as rt715 codec. Rename them with rt715-sdca prefix allow machine driver to distinguish rt715 and rt715-sdca from dai name. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-29-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 4533eedd7e18..cee46db79d73 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -933,7 +933,7 @@ static const struct snd_soc_dai_ops rt715_sdca_ops = { static struct snd_soc_dai_driver rt715_sdca_dai[] = { { - .name = "rt715-aif1", + .name = "rt715-sdca-aif1", .id = RT715_AIF1, .capture = { .stream_name = "DP6 Capture", @@ -945,7 +945,7 @@ static struct snd_soc_dai_driver rt715_sdca_dai[] = { .ops = &rt715_sdca_ops, }, { - .name = "rt715-aif2", + .name = "rt715-sdca-aif2", .id = RT715_AIF2, .capture = { .stream_name = "DP4 Capture", From a2e620e4ac87c80e0987bd74c0c345b0da02b33e Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:24 -0500 Subject: [PATCH 29/34] ASoC: Intel: sof_sdw: change rt715-sdca dai name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As rt715-sdca dai name has been changed in codec driver, we should change it in machine driver, too. Changing the dai name in codec_info_list[] also help sof_sdw_rtd_init() to run .rtd_init() from the same codec. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-30-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 4 ++-- sound/soc/intel/boards/sof_sdw_rt_dmic.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 3874da8d7fe4..1816ec5dd580 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -838,7 +838,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dais = { { .direction = {false, true}, - .dai_name = "rt715-aif2", + .dai_name = "rt715-sdca-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, .rtd_init = rt_dmic_rtd_init, @@ -853,7 +853,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dais = { { .direction = {false, true}, - .dai_name = "rt715-aif2", + .dai_name = "rt715-sdca-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, .rtd_init = rt_dmic_rtd_init, diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c index 5aec8422656c..2f7ed9b31e79 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -14,6 +14,7 @@ static const char * const dmics[] = { "rt715", + "rt715-sdca", "rt712-sdca-dmic", "rt722-sdca", }; From aac976aa3c6a37175eec9d3eb912cd92aa8c3a0b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:25 -0500 Subject: [PATCH 30/34] ASoC: Intel: change cs35l56 name_prefix To use sequential amp numbers. I,e, AMP1, AMP2, AMP3, AMP4 Reviewed-by: Chao Song Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-31-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 4 ++-- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index e06efc5b1457..7e53266d831d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -373,13 +373,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = { .adr = 0x00013701FA355601ull, .num_endpoints = 1, .endpoints = &spk_r_endpoint, - .name_prefix = "AMP8" + .name_prefix = "AMP3" }, { .adr = 0x00013601FA355601ull, .num_endpoints = 1, .endpoints = &spk_3_endpoint, - .name_prefix = "AMP7" + .name_prefix = "AMP4" } }; diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 007f1ac2327a..0cef3d788a5b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -464,13 +464,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = { .adr = 0x00013701FA355601ull, .num_endpoints = 1, .endpoints = &spk_l_endpoint, - .name_prefix = "AMP8" + .name_prefix = "AMP3" }, { .adr = 0x00013601FA355601ull, .num_endpoints = 1, .endpoints = &spk_2_endpoint, - .name_prefix = "AMP7" + .name_prefix = "AMP4" } }; From 84aa440e02f3b44e927e274b9946b4c79608de43 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:26 -0500 Subject: [PATCH 31/34] ASoC: Intel: sof_sdw: Don't pass acpi_link_adr to init functions There is no need to pass the snd_soc_acpi_link_adr structure to the init functions, it conveys no specific information about the codec. Remove this parameter from the callbacks Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-32-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 7 ++----- sound/soc/intel/boards/sof_sdw_common.h | 6 ------ sound/soc/intel/boards/sof_sdw_cs_amp.c | 1 - sound/soc/intel/boards/sof_sdw_maxim.c | 1 - sound/soc/intel/boards/sof_sdw_rt711.c | 1 - sound/soc/intel/boards/sof_sdw_rt_amp.c | 1 - sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 1 - 7 files changed, 2 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1816ec5dd580..f3167e3498e0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1273,7 +1273,6 @@ struct sof_sdw_endpoint { u32 link_mask; const char *codec_name; - const struct snd_soc_acpi_link_adr *adr_link; struct sof_sdw_codec_info *codec_info; const struct sof_sdw_dai_info *dai_info; }; @@ -1425,7 +1424,6 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, sof_end->link_mask = adr_link->mask; sof_end->codec_name = codec_name; - sof_end->adr_link = adr_link; sof_end->codec_info = codec_info; sof_end->dai_info = dai_info; sof_end++; @@ -1548,8 +1546,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, list_for_each_entry(sof_end, &sof_dai->endpoints, list) { if (sof_end->dai_info->init) - sof_end->dai_info->init(card, sof_end->adr_link, - *dai_links, + sof_end->dai_info->init(card, *dai_links, sof_end->codec_info, playback); } @@ -1612,7 +1609,7 @@ static int create_ssp_dailinks(struct snd_soc_card *card, if (ret) return ret; - ret = ssp_info->dais[0].init(card, NULL, *dai_links, ssp_info, 0); + ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0); if (ret < 0) return ret; diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 2132d3fc42f8..8d8c2ca68a7f 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -74,7 +74,6 @@ struct sof_sdw_dai_info { const int dai_type; const int dailink[2]; /* dailink id for each direction */ int (*init)(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -132,7 +131,6 @@ int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); /* RT711 support */ int sof_sdw_rt711_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -140,7 +138,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l /* RT711-SDCA support */ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -151,7 +148,6 @@ extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; /* generic amp support */ int sof_sdw_rt_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -159,14 +155,12 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_ /* MAXIM codec support */ int sof_sdw_maxim_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* CS AMP support */ int sof_sdw_cs_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index 56cf75bc6cc4..e29a586ce7c0 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -57,7 +57,6 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) } int sof_sdw_cs_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c index 034730432671..432e5112415a 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/intel/boards/sof_sdw_maxim.c @@ -139,7 +139,6 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card) } int sof_sdw_maxim_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 9762c48ba7a9..7e54fc5cbe09 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -158,7 +158,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l } int sof_sdw_rt711_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index 202edab95000..1b415708500e 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -281,7 +281,6 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_ } int sof_sdw_rt_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 006771485486..85c09513bc35 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -191,7 +191,6 @@ int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link } int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) From 36f307d296ad15e3d679d6567112b9ec4c30babc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:27 -0500 Subject: [PATCH 32/34] ASoC: Intel: sof_sdw: Remove redundant initialisations Unspecified fields are by default initialised to zero, remove redundant init pointer initialisations. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-33-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index f3167e3498e0..5a7014d82d6c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1026,7 +1026,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1040,7 +1039,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1054,7 +1052,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_AMP, .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1068,7 +1065,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {false, true}, .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, From 9c09bef69fe9376953348bb367c869f3d16c758c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:28 -0500 Subject: [PATCH 33/34] ASoC: Intel: sof_sdw: Add quirk for optional codec speakers Some codecs have speaker drivers that may or may not be used in a given system. Add a quirk (SOF_CODEC_SPKR) that defines if a system uses the codec speaker, this is kept generic such that any codec with such a speaker DAI can reuse the quirk. For implementation of this, add a quirk field into the sof_sdw_dai_info structure. This field is not used to specify if a system uses a particular quirk, that is still done through the sof_sdw_quirk variable, this field is used to flag a DAI as conditional on a certain quirk. This means the DAI will only be included in the card if sof_sdw_quirk and the DAI quirk field have a matching set bit. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-34-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 +++++ sound/soc/intel/boards/sof_sdw_common.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5a7014d82d6c..4fc15f597e28 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -37,6 +37,8 @@ static void log_quirks(struct device *dev) SOF_SSP_GET_PORT(sof_sdw_quirk)); if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); + if (sof_sdw_quirk & SOF_CODEC_SPKR) + dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -1382,6 +1384,9 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, dai_info = &codec_info->dais[adr_end->num]; sof_dai = find_dailink(sof_dais, adr_end); + if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk)) + continue; + dev_dbg(dev, "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", ffs(adr_link->mask) - 1, adr_dev->adr, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 8d8c2ca68a7f..81181627b406 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -52,6 +52,8 @@ enum { #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) /* Deprecated and no longer supported by the code */ #define SOF_SDW_NO_AGGREGATION BIT(14) +/* If a CODEC has an optional speaker output, this quirk will enable it */ +#define SOF_CODEC_SPKR BIT(15) /* BT audio offload: reserve 3 bits for future */ #define SOF_BT_OFFLOAD_SSP_SHIFT 15 @@ -80,6 +82,7 @@ struct sof_sdw_dai_info { int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); int (*rtd_init)(struct snd_soc_pcm_runtime *rtd); bool rtd_init_done; /* Indicate that the rtd_init callback is done */ + unsigned long quirk; }; struct sof_sdw_codec_info { From 59ffeb15b2f7b44cf934fd778dc0d98a35aa6a84 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:29 -0500 Subject: [PATCH 34/34] ASoC: Intel: sof_sdw: Add support for cs42l43 optional speaker output Add support for the optional speaker output on the cs42l43, this uses the new SOF_CODEC_SPKR quirk to conditional include the speaker DAI link. It is worth noting that currently no systems are included that utilise this feature, but the feature is added as several systems are on the horizon. As part of this SOF_SDW_MAX_DAI_NUM must be increased, it is currently 3 but cs42l43 will now have 4 DAI links. This value is increased to 8 to give some head room for future devices. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-35-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++- sound/soc/intel/boards/sof_sdw_common.h | 9 +++- sound/soc/intel/boards/sof_sdw_cs42l43.c | 50 +++++++++++++++++++ .../intel/common/soc-acpi-intel-mtl-match.c | 6 +++ .../intel/common/soc-acpi-intel-tgl-match.c | 6 +++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 4fc15f597e28..b94835448b1b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1016,8 +1016,17 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID}, }, + { + .direction = {true, false}, + .dai_name = "cs42l43-dp6", + .dai_type = SOF_SDW_DAI_TYPE_AMP, + .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, + .init = sof_sdw_cs42l43_spk_init, + .rtd_init = cs42l43_spk_rtd_init, + .quirk = SOF_CODEC_SPKR, + }, }, - .dai_num = 3, + .dai_num = 4, }, { .part_id = 0xaaaa, /* generic codec mockup */ diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 81181627b406..8468487a6bd6 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -66,7 +66,7 @@ enum { #define SOF_SDW_DAI_TYPE_AMP 1 #define SOF_SDW_DAI_TYPE_MIC 2 -#define SOF_SDW_MAX_DAI_NUM 3 +#define SOF_SDW_MAX_DAI_NUM 8 struct sof_sdw_codec_info; @@ -162,6 +162,12 @@ int sof_sdw_maxim_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); +/* CS42L43 support */ +int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* CS AMP support */ int sof_sdw_cs_amp_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_links, @@ -172,6 +178,7 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card, int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd); +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index a9b6edac2ecd..5361249f0f53 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -30,6 +30,17 @@ static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" }, }; +static const struct snd_soc_dapm_widget cs42l43_spk_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route cs42l43_spk_map[] = { + { "Speaker", NULL, "cs42l43 AMP1_OUT_P", }, + { "Speaker", NULL, "cs42l43 AMP1_OUT_N", }, + { "Speaker", NULL, "cs42l43 AMP2_OUT_P", }, + { "Speaker", NULL, "cs42l43 AMP2_OUT_N", }, +}; + static const struct snd_soc_dapm_widget cs42l43_dmic_widgets[] = { SND_SOC_DAPM_MIC("DMIC", NULL), }; @@ -108,6 +119,45 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets, + ARRAY_SIZE(cs42l43_spk_widgets)); + if (ret) { + dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, + ARRAY_SIZE(cs42l43_spk_map)); + if (ret) + dev_err(card->dev, "cs42l43 speaker map addition failed: %d\n", ret); + + return ret; +} + +int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* Do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + + return 0; +} + int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 7e53266d831d..27d1313e6686 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -357,6 +357,12 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { .group_position = 0, .group_id = 0, }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, }; static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 0cef3d788a5b..77226d1eb1cf 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -433,6 +433,12 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { .group_position = 0, .group_id = 0, }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, }; static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = {