Skip to content

Commit 76db426

Browse files
committed
ASoC: soc_sdw_utils: skip the endpoint that doesn't present
A codec endpoint may not be used. We could check the present SDCA functions to know if the endpoint is used or not. Skip the endpoint which is not used. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent b50fa21 commit 76db426

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

sound/soc/sdw_utils/soc_sdw_utils.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/module.h>
1111
#include <linux/soundwire/sdw.h>
1212
#include <linux/soundwire/sdw_type.h>
13+
#include <sound/sdca_function.h>
1314
#include <sound/soc_sdw_utils.h>
1415

1516
static const struct snd_soc_dapm_widget generic_dmic_widgets[] = {
@@ -1131,6 +1132,25 @@ struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks
11311132
}
11321133
EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, "SND_SOC_SDW_UTILS");
11331134

1135+
static int asoc_sdw_get_dai_type(u32 type)
1136+
{
1137+
switch (type) {
1138+
case SDCA_FUNCTION_TYPE_SMART_AMP:
1139+
case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
1140+
return SOC_SDW_DAI_TYPE_AMP;
1141+
case SDCA_FUNCTION_TYPE_SMART_MIC:
1142+
case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
1143+
case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
1144+
return SOC_SDW_DAI_TYPE_MIC;
1145+
case SDCA_FUNCTION_TYPE_UAJ:
1146+
case SDCA_FUNCTION_TYPE_RJ:
1147+
case SDCA_FUNCTION_TYPE_SIMPLE_JACK:
1148+
return SOC_SDW_DAI_TYPE_JACK;
1149+
default:
1150+
return -EINVAL;
1151+
}
1152+
}
1153+
11341154
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
11351155
struct asoc_sdw_dailink *soc_dais,
11361156
struct asoc_sdw_endpoint *soc_ends,
@@ -1142,8 +1162,10 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
11421162
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
11431163
const struct snd_soc_acpi_link_adr *adr_link;
11441164
struct asoc_sdw_endpoint *soc_end = soc_ends;
1165+
struct snd_soc_dai_link_component dlc;
1166+
struct snd_soc_dai *codec_dai;
11451167
int num_dais = 0;
1146-
int i, j;
1168+
int i, j, k;
11471169
int ret;
11481170

11491171
for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
@@ -1193,6 +1215,9 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
11931215
const struct snd_soc_acpi_endpoint *adr_end;
11941216
const struct asoc_sdw_dai_info *dai_info;
11951217
struct asoc_sdw_dailink *soc_dai;
1218+
const char *sdw_codec_name;
1219+
struct sdw_slave *slave;
1220+
struct device *sdw_dev;
11961221
int stream;
11971222

11981223
adr_end = &adr_dev->endpoints[j];
@@ -1203,6 +1228,67 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
12031228
!(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk)))
12041229
continue;
12051230

1231+
/*
1232+
* No need to check SDCA functions if there is only 1 endpoint
1233+
* present.
1234+
*/
1235+
if (adr_dev->num_endpoints == 1) {
1236+
dev_dbg(dev,
1237+
"%#llx: Only 1 endpoint with DAI type %d is found\n",
1238+
adr_dev->adr, dai_info->dai_type);
1239+
goto skip_sdca_function_check;
1240+
}
1241+
1242+
dlc.dai_name = dai_info->dai_name;
1243+
codec_dai = snd_soc_find_dai_with_mutex(&dlc);
1244+
if (!codec_dai) {
1245+
dev_warn(dev, "codec dai %s not registered yet\n",
1246+
dlc.dai_name);
1247+
return -EPROBE_DEFER;
1248+
}
1249+
1250+
sdw_codec_name = _asoc_sdw_get_codec_name(dev, codec_info,
1251+
adr_link, i);
1252+
if (!sdw_codec_name)
1253+
return -ENOMEM;
1254+
1255+
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
1256+
sdw_codec_name);
1257+
if (!sdw_dev) {
1258+
dev_err(dev, "codec %s not found\n", sdw_codec_name);
1259+
return -EINVAL;
1260+
}
1261+
1262+
slave = dev_to_sdw_dev(sdw_dev);
1263+
if (!slave)
1264+
return -EINVAL;
1265+
1266+
/* Make sure BIOS provides SDCA properties */
1267+
if (!slave->sdca_data.interface_revision) {
1268+
dev_warn(&slave->dev,
1269+
"SDCA properties not found in the BIOS\n");
1270+
goto skip_sdca_function_check;
1271+
}
1272+
1273+
for (k = 0; k < slave->sdca_data.num_functions; k++) {
1274+
int dai_type = asoc_sdw_get_dai_type(
1275+
slave->sdca_data.function[k].type);
1276+
1277+
if (dai_type == dai_info->dai_type) {
1278+
dev_dbg(&slave->dev,
1279+
"DAI type %d sdca function %s found\n",
1280+
dai_type,
1281+
slave->sdca_data.function[k].name);
1282+
break;
1283+
}
1284+
}
1285+
if (k == slave->sdca_data.num_functions) {
1286+
dev_dbg(&slave->dev,
1287+
"SDCA device function for DAI type %d not supported, skip endpoint\n",
1288+
dai_info->dai_type);
1289+
continue;
1290+
}
1291+
skip_sdca_function_check:
12061292
dev_dbg(dev,
12071293
"Add dev: %d, 0x%llx end: %d, dai: %d, %c/%c to %s: %d\n",
12081294
ffs(adr_link->mask) - 1, adr_dev->adr,

0 commit comments

Comments
 (0)