Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: Intel: boards: updates for 6.10 - part2

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

This second part provides SoundWire-related cleanups and extensions
required by Realtek RT722 and Cirrus Logic codecs.

Also included is a cleanup of the RT715-sdca DAI naming and new tables
for ACPI-based board detections.

+755 -771
+2 -2
sound/soc/codecs/rt715-sdca.c
··· 933 933 934 934 static struct snd_soc_dai_driver rt715_sdca_dai[] = { 935 935 { 936 - .name = "rt715-aif1", 936 + .name = "rt715-sdca-aif1", 937 937 .id = RT715_AIF1, 938 938 .capture = { 939 939 .stream_name = "DP6 Capture", ··· 945 945 .ops = &rt715_sdca_ops, 946 946 }, 947 947 { 948 - .name = "rt715-aif2", 948 + .name = "rt715-sdca-aif2", 949 949 .id = RT715_AIF2, 950 950 .capture = { 951 951 .stream_name = "DP4 Capture",
-1
sound/soc/intel/boards/Kconfig
··· 678 678 depends on MFD_INTEL_LPSS || COMPILE_TEST 679 679 depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST 680 680 depends on SOUNDWIRE 681 - select SND_SOC_INTEL_SOF_BOARD_HELPERS 682 681 select SND_SOC_MAX98363 683 682 select SND_SOC_MAX98373_I2C 684 683 select SND_SOC_MAX98373_SDW
+2 -2
sound/soc/intel/boards/Makefile
··· 40 40 sof_sdw_maxim.o sof_sdw_rt_amp.o \ 41 41 sof_sdw_rt5682.o sof_sdw_rt700.o \ 42 42 sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ 43 - sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ 44 - sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ 43 + sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \ 44 + sof_sdw_rt_dmic.o \ 45 45 sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ 46 46 sof_sdw_cs_amp.o \ 47 47 sof_sdw_dmic.o \
-18
sound/soc/intel/boards/sof_board_helpers.c
··· 630 630 } 631 631 EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); 632 632 633 - struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 634 - const char * const dai_name[], int num_dais) 635 - { 636 - struct snd_soc_dai *dai; 637 - int index; 638 - int i; 639 - 640 - for (index = 0; index < num_dais; index++) 641 - for_each_rtd_codec_dais(rtd, i, dai) 642 - if (strstr(dai->name, dai_name[index])) { 643 - dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); 644 - return dai; 645 - } 646 - 647 - return NULL; 648 - } 649 - EXPORT_SYMBOL_NS(get_codec_dai_by_name, SND_SOC_INTEL_SOF_BOARD_HELPERS); 650 - 651 633 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); 652 634 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 653 635 MODULE_LICENSE("GPL");
-3
sound/soc/intel/boards/sof_board_helpers.h
··· 167 167 struct sof_card_private * 168 168 sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk); 169 169 170 - struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 171 - const char * const dai_name[], int num_dais); 172 - 173 170 #endif /* __SOF_INTEL_BOARD_HELPERS_H */
+539 -583
sound/soc/intel/boards/sof_sdw.c
··· 5 5 * sof_sdw - ASOC Machine driver for Intel SoundWire platforms 6 6 */ 7 7 8 + #include <linux/bitmap.h> 8 9 #include <linux/device.h> 9 10 #include <linux/dmi.h> 10 11 #include <linux/module.h> ··· 36 35 dev_dbg(dev, "SSP port %ld\n", 37 36 SOF_SSP_GET_PORT(sof_sdw_quirk)); 38 37 if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) 39 - dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); 38 + dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); 39 + if (sof_sdw_quirk & SOF_CODEC_SPKR) 40 + dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n"); 40 41 } 41 42 42 43 static int sof_sdw_quirk_cb(const struct dmi_system_id *id) ··· 517 514 } 518 515 }; 519 516 517 + struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 518 + const char * const dai_name[], 519 + int num_dais) 520 + { 521 + struct snd_soc_dai *dai; 522 + int index; 523 + int i; 524 + 525 + for (index = 0; index < num_dais; index++) 526 + for_each_rtd_codec_dais(rtd, i, dai) 527 + if (strstr(dai->name, dai_name[index])) { 528 + dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); 529 + return dai; 530 + } 531 + 532 + return NULL; 533 + } 534 + 520 535 /* these wrappers are only needed to avoid typecast compilation errors */ 521 536 int sdw_startup(struct snd_pcm_substream *substream) 522 537 { ··· 751 730 .dai_name = "rt712-sdca-dmic-aif1", 752 731 .dai_type = SOF_SDW_DAI_TYPE_MIC, 753 732 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 754 - .rtd_init = rt712_sdca_dmic_rtd_init, 733 + .rtd_init = rt_dmic_rtd_init, 755 734 }, 756 735 }, 757 736 .dai_num = 1, ··· 781 760 .dai_name = "rt712-sdca-dmic-aif1", 782 761 .dai_type = SOF_SDW_DAI_TYPE_MIC, 783 762 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 784 - .rtd_init = rt712_sdca_dmic_rtd_init, 763 + .rtd_init = rt_dmic_rtd_init, 785 764 }, 786 765 }, 787 766 .dai_num = 1, ··· 840 819 .dais = { 841 820 { 842 821 .direction = {false, true}, 843 - .dai_name = "rt715-aif2", 822 + .dai_name = "rt715-sdca-aif2", 844 823 .dai_type = SOF_SDW_DAI_TYPE_MIC, 845 824 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 846 - .rtd_init = rt715_sdca_rtd_init, 825 + .rtd_init = rt_dmic_rtd_init, 847 826 }, 848 827 }, 849 828 .dai_num = 1, ··· 855 834 .dais = { 856 835 { 857 836 .direction = {false, true}, 858 - .dai_name = "rt715-aif2", 837 + .dai_name = "rt715-sdca-aif2", 859 838 .dai_type = SOF_SDW_DAI_TYPE_MIC, 860 839 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 861 - .rtd_init = rt715_sdca_rtd_init, 840 + .rtd_init = rt_dmic_rtd_init, 862 841 }, 863 842 }, 864 843 .dai_num = 1, ··· 873 852 .dai_name = "rt715-aif2", 874 853 .dai_type = SOF_SDW_DAI_TYPE_MIC, 875 854 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 876 - .rtd_init = rt715_rtd_init, 855 + .rtd_init = rt_dmic_rtd_init, 877 856 }, 878 857 }, 879 858 .dai_num = 1, ··· 888 867 .dai_name = "rt715-aif2", 889 868 .dai_type = SOF_SDW_DAI_TYPE_MIC, 890 869 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 891 - .rtd_init = rt715_rtd_init, 870 + .rtd_init = rt_dmic_rtd_init, 892 871 }, 893 872 }, 894 873 .dai_num = 1, ··· 904 883 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 905 884 .init = sof_sdw_rt_sdca_jack_init, 906 885 .exit = sof_sdw_rt_sdca_jack_exit, 886 + .rtd_init = rt_sdca_jack_rtd_init, 907 887 }, 908 888 { 909 889 .direction = {true, false}, ··· 912 890 .dai_type = SOF_SDW_DAI_TYPE_AMP, 913 891 /* No feedback capability is provided by rt722-sdca codec driver*/ 914 892 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 915 - .init = sof_sdw_rt722_spk_init, 893 + .rtd_init = rt722_spk_rtd_init, 916 894 }, 917 895 { 918 896 .direction = {false, true}, 919 897 .dai_name = "rt722-sdca-aif3", 920 898 .dai_type = SOF_SDW_DAI_TYPE_MIC, 921 899 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 922 - .init = sof_sdw_rt722_sdca_dmic_init, 900 + .rtd_init = rt_dmic_rtd_init, 923 901 }, 924 902 }, 925 903 .dai_num = 3, ··· 1016 994 .dai_type = SOF_SDW_DAI_TYPE_JACK, 1017 995 .dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID}, 1018 996 }, 997 + { 998 + .direction = {true, false}, 999 + .dai_name = "cs42l43-dp6", 1000 + .dai_type = SOF_SDW_DAI_TYPE_AMP, 1001 + .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 1002 + .init = sof_sdw_cs42l43_spk_init, 1003 + .rtd_init = cs42l43_spk_rtd_init, 1004 + .quirk = SOF_CODEC_SPKR, 1005 + }, 1019 1006 }, 1020 - .dai_num = 3, 1007 + .dai_num = 4, 1021 1008 }, 1022 1009 { 1023 1010 .part_id = 0xaaaa, /* generic codec mockup */ ··· 1037 1006 .dai_name = "sdw-mockup-aif1", 1038 1007 .dai_type = SOF_SDW_DAI_TYPE_JACK, 1039 1008 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 1040 - .init = NULL, 1041 1009 }, 1042 1010 }, 1043 1011 .dai_num = 1, ··· 1050 1020 .dai_name = "sdw-mockup-aif1", 1051 1021 .dai_type = SOF_SDW_DAI_TYPE_JACK, 1052 1022 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, 1053 - .init = NULL, 1054 1023 }, 1055 1024 }, 1056 1025 .dai_num = 1, ··· 1063 1034 .dai_name = "sdw-mockup-aif1", 1064 1035 .dai_type = SOF_SDW_DAI_TYPE_AMP, 1065 1036 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 1066 - .init = NULL, 1067 1037 }, 1068 1038 }, 1069 1039 .dai_num = 1, ··· 1076 1048 .direction = {false, true}, 1077 1049 .dai_type = SOF_SDW_DAI_TYPE_MIC, 1078 1050 .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, 1079 - .init = NULL, 1080 1051 }, 1081 1052 }, 1082 1053 .dai_num = 1, 1083 1054 }, 1084 1055 }; 1085 1056 1086 - static inline int find_codec_info_part(const u64 adr) 1057 + static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) 1087 1058 { 1088 1059 unsigned int part_id, sdw_version; 1089 1060 int i; ··· 1097 1070 if (part_id == codec_info_list[i].part_id && 1098 1071 (!codec_info_list[i].version_id || 1099 1072 sdw_version == codec_info_list[i].version_id)) 1100 - return i; 1073 + return &codec_info_list[i]; 1101 1074 1102 - return -EINVAL; 1075 + return NULL; 1103 1076 1104 1077 } 1105 1078 1106 - static inline int find_codec_info_acpi(const u8 *acpi_id) 1079 + static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) 1107 1080 { 1108 1081 int i; 1109 1082 1110 1083 if (!acpi_id[0]) 1111 - return -EINVAL; 1084 + return NULL; 1112 1085 1113 1086 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) 1114 1087 if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) 1115 - return i; 1088 + return &codec_info_list[i]; 1116 1089 1117 - return -EINVAL; 1090 + return NULL; 1118 1091 } 1119 1092 1120 - /* 1121 - * get BE dailink number and CPU DAI number based on sdw link adr. 1122 - * Since some sdw slaves may be aggregated, the CPU DAI number 1123 - * may be larger than the number of BE dailinks. 1124 - */ 1125 - static int get_dailink_info(struct device *dev, 1126 - const struct snd_soc_acpi_link_adr *adr_link, 1127 - int *sdw_be_num, int *codecs_num) 1093 + static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, 1094 + int *dai_index) 1128 1095 { 1129 - bool group_visited[SDW_MAX_GROUPS]; 1130 - bool no_aggregation; 1131 - int i; 1132 - int j; 1096 + int i, j; 1133 1097 1134 - no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1135 - *sdw_be_num = 0; 1136 - 1137 - if (!adr_link) 1138 - return -EINVAL; 1139 - 1140 - for (i = 0; i < SDW_MAX_GROUPS; i++) 1141 - group_visited[i] = false; 1142 - 1143 - for (; adr_link->num_adr; adr_link++) { 1144 - const struct snd_soc_acpi_endpoint *endpoint; 1145 - struct sof_sdw_codec_info *codec_info; 1146 - int codec_index; 1147 - int stream; 1148 - u64 adr; 1149 - 1150 - /* make sure the link mask has a single bit set */ 1151 - if (!is_power_of_2(adr_link->mask)) 1152 - return -EINVAL; 1153 - 1154 - for (i = 0; i < adr_link->num_adr; i++) { 1155 - adr = adr_link->adr_d[i].adr; 1156 - codec_index = find_codec_info_part(adr); 1157 - if (codec_index < 0) 1158 - return codec_index; 1159 - 1160 - codec_info = &codec_info_list[codec_index]; 1161 - 1162 - *codecs_num += codec_info->dai_num; 1163 - 1164 - if (!adr_link->adr_d[i].name_prefix) { 1165 - dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1166 - adr_link->adr_d[i].adr); 1167 - return -EINVAL; 1098 + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1099 + for (j = 0; j < codec_info_list[i].dai_num; j++) { 1100 + if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { 1101 + *dai_index = j; 1102 + return &codec_info_list[i]; 1168 1103 } 1169 - 1170 - endpoint = adr_link->adr_d[i].endpoints; 1171 - if (endpoint->aggregated && !endpoint->group_id) { 1172 - dev_err(dev, "invalid group id on link %x\n", 1173 - adr_link->mask); 1174 - return -EINVAL; 1175 - } 1176 - 1177 - for (j = 0; j < codec_info->dai_num; j++) { 1178 - /* count DAI number for playback and capture */ 1179 - for_each_pcm_streams(stream) { 1180 - if (!codec_info->dais[j].direction[stream]) 1181 - continue; 1182 - 1183 - /* count BE for each non-aggregated slave or group */ 1184 - if (!endpoint->aggregated || no_aggregation || 1185 - !group_visited[endpoint->group_id]) 1186 - (*sdw_be_num)++; 1187 - } 1188 - } 1189 - 1190 - if (endpoint->aggregated) 1191 - group_visited[endpoint->group_id] = true; 1192 1104 } 1193 1105 } 1194 1106 1195 - return 0; 1107 + return NULL; 1196 1108 } 1197 1109 1198 1110 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, ··· 1216 1250 return true; 1217 1251 } 1218 1252 1219 - static int fill_sdw_codec_dlc(struct device *dev, 1220 - const struct snd_soc_acpi_link_adr *adr_link, 1221 - struct snd_soc_dai_link_component *codec, 1222 - int adr_index, int dai_index) 1253 + static const char *get_codec_name(struct device *dev, 1254 + const struct sof_sdw_codec_info *codec_info, 1255 + const struct snd_soc_acpi_link_adr *adr_link, 1256 + int adr_index) 1223 1257 { 1224 - unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; 1225 1258 u64 adr = adr_link->adr_d[adr_index].adr; 1226 - int codec_index; 1259 + unsigned int sdw_version = SDW_VERSION(adr); 1260 + unsigned int link_id = SDW_DISCO_LINK_ID(adr); 1261 + unsigned int unique_id = SDW_UNIQUE_ID(adr); 1262 + unsigned int mfg_id = SDW_MFG_ID(adr); 1263 + unsigned int part_id = SDW_PART_ID(adr); 1264 + unsigned int class_id = SDW_CLASS_ID(adr); 1227 1265 1228 - codec_index = find_codec_info_part(adr); 1229 - if (codec_index < 0) 1230 - return codec_index; 1231 - 1232 - sdw_version = SDW_VERSION(adr); 1233 - link_id = SDW_DISCO_LINK_ID(adr); 1234 - unique_id = SDW_UNIQUE_ID(adr); 1235 - mfg_id = SDW_MFG_ID(adr); 1236 - part_id = SDW_PART_ID(adr); 1237 - class_id = SDW_CLASS_ID(adr); 1238 - 1239 - if (codec_info_list[codec_index].codec_name) 1240 - codec->name = devm_kstrdup(dev, 1241 - codec_info_list[codec_index].codec_name, 1242 - GFP_KERNEL); 1266 + if (codec_info->codec_name) 1267 + return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); 1243 1268 else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, 1244 1269 class_id, adr_index)) 1245 - codec->name = devm_kasprintf(dev, GFP_KERNEL, 1246 - "sdw:0:%01x:%04x:%04x:%02x", link_id, 1247 - mfg_id, part_id, class_id); 1270 + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x", 1271 + link_id, mfg_id, part_id, class_id); 1248 1272 else 1249 - codec->name = devm_kasprintf(dev, GFP_KERNEL, 1250 - "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id, 1251 - mfg_id, part_id, class_id, unique_id); 1273 + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x", 1274 + link_id, mfg_id, part_id, class_id, unique_id); 1252 1275 1253 - if (!codec->name) 1254 - return -ENOMEM; 1255 - 1256 - codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name; 1257 - 1258 - return 0; 1259 - } 1260 - 1261 - static int set_codec_init_func(struct snd_soc_card *card, 1262 - const struct snd_soc_acpi_link_adr *adr_link, 1263 - struct snd_soc_dai_link *dai_links, 1264 - bool playback, int group_id, int adr_index, int dai_index) 1265 - { 1266 - int i = adr_index; 1267 - 1268 - do { 1269 - /* 1270 - * Initialize the codec. If codec is part of an aggregated 1271 - * group (group_id>0), initialize all codecs belonging to 1272 - * same group. 1273 - * The first link should start with adr_link->adr_d[adr_index] 1274 - * because that is the device that we want to initialize and 1275 - * we should end immediately if it is not aggregated (group_id=0) 1276 - */ 1277 - for ( ; i < adr_link->num_adr; i++) { 1278 - int codec_index; 1279 - 1280 - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1281 - if (codec_index < 0) 1282 - return codec_index; 1283 - 1284 - /* The group_id is > 0 iff the codec is aggregated */ 1285 - if (adr_link->adr_d[i].endpoints->group_id != group_id) 1286 - continue; 1287 - 1288 - if (codec_info_list[codec_index].dais[dai_index].init) 1289 - codec_info_list[codec_index].dais[dai_index].init(card, 1290 - adr_link, 1291 - dai_links, 1292 - &codec_info_list[codec_index], 1293 - playback); 1294 - if (!group_id) 1295 - return 0; 1296 - } 1297 - 1298 - i = 0; 1299 - adr_link++; 1300 - } while (adr_link->mask); 1301 - 1302 - return 0; 1303 - } 1304 - 1305 - /* 1306 - * check endpoint status in slaves and gather link ID for all slaves in 1307 - * the same group to generate different CPU DAI. Now only support 1308 - * one sdw link with all slaves set with only single group id. 1309 - * 1310 - * one slave on one sdw link with aggregated = 0 1311 - * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI 1312 - * 1313 - * two or more slaves on one sdw link with aggregated = 0 1314 - * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs 1315 - * 1316 - * multiple links with multiple slaves with aggregated = 1 1317 - * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs 1318 - */ 1319 - static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, 1320 - struct device *dev, int *cpu_dai_id, int *cpu_dai_num, 1321 - int *codec_num, unsigned int *group_id, 1322 - int adr_index) 1323 - { 1324 - bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; 1325 - int i; 1326 - 1327 - if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) { 1328 - cpu_dai_id[0] = ffs(adr_link->mask) - 1; 1329 - *cpu_dai_num = 1; 1330 - *codec_num = 1; 1331 - *group_id = 0; 1332 - return 0; 1333 - } 1334 - 1335 - *codec_num = 0; 1336 - *cpu_dai_num = 0; 1337 - *group_id = adr_link->adr_d[adr_index].endpoints->group_id; 1338 - 1339 - /* Count endpoints with the same group_id in the adr_link */ 1340 - for (; adr_link && adr_link->num_adr; adr_link++) { 1341 - unsigned int link_codecs = 0; 1342 - 1343 - for (i = 0; i < adr_link->num_adr; i++) { 1344 - if (adr_link->adr_d[i].endpoints->aggregated && 1345 - adr_link->adr_d[i].endpoints->group_id == *group_id) 1346 - link_codecs++; 1347 - } 1348 - 1349 - if (link_codecs) { 1350 - *codec_num += link_codecs; 1351 - 1352 - if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) { 1353 - dev_err(dev, "cpu_dai_id array overflowed\n"); 1354 - return -EINVAL; 1355 - } 1356 - 1357 - cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; 1358 - } 1359 - } 1360 - 1361 - return 0; 1362 - } 1363 - 1364 - static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps, 1365 - int codec_num, int cpu_num) 1366 - { 1367 - int step; 1368 - int i; 1369 - 1370 - step = codec_num / cpu_num; 1371 - for (i = 0; i < codec_num; i++) { 1372 - sdw_codec_ch_maps[i].cpu = i / step; 1373 - sdw_codec_ch_maps[i].codec = i; 1374 - } 1375 - } 1376 - 1377 - static inline int find_codec_info_dai(const char *dai_name, int *dai_index) 1378 - { 1379 - int i, j; 1380 - 1381 - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { 1382 - for (j = 0; j < codec_info_list[i].dai_num; j++) { 1383 - if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { 1384 - *dai_index = j; 1385 - return i; 1386 - } 1387 - } 1388 - } 1389 - 1390 - return -EINVAL; 1276 + return NULL; 1391 1277 } 1392 1278 1393 1279 static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) 1394 1280 { 1395 1281 struct sof_sdw_codec_info *codec_info; 1396 1282 struct snd_soc_dai *dai; 1397 - int codec_index; 1398 1283 int dai_index; 1399 1284 int ret; 1400 1285 int i; 1401 1286 1402 1287 for_each_rtd_codec_dais(rtd, i, dai) { 1403 - codec_index = find_codec_info_dai(dai->name, &dai_index); 1404 - if (codec_index < 0) 1288 + codec_info = find_codec_info_dai(dai->name, &dai_index); 1289 + if (!codec_info) 1405 1290 return -EINVAL; 1406 1291 1407 - codec_info = &codec_info_list[codec_index]; 1408 1292 /* 1409 1293 * A codec dai can be connected to different dai links for capture and playback, 1410 1294 * but we only need to call the rtd_init function once. ··· 1274 1458 return 0; 1275 1459 } 1276 1460 1461 + struct sof_sdw_endpoint { 1462 + struct list_head list; 1463 + 1464 + u32 link_mask; 1465 + const char *codec_name; 1466 + 1467 + struct sof_sdw_codec_info *codec_info; 1468 + const struct sof_sdw_dai_info *dai_info; 1469 + }; 1470 + 1471 + struct sof_sdw_dailink { 1472 + bool initialised; 1473 + 1474 + u8 group_id; 1475 + u32 link_mask[SNDRV_PCM_STREAM_LAST + 1]; 1476 + int num_devs[SNDRV_PCM_STREAM_LAST + 1]; 1477 + struct list_head endpoints; 1478 + }; 1479 + 1277 1480 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 1278 1481 1279 - static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, 1280 - struct snd_soc_dai_link *dai_links, int sdw_be_num, 1281 - const struct snd_soc_acpi_link_adr *adr_link, 1282 - struct snd_soc_codec_conf *codec_conf, 1283 - int codec_count, int *be_id, 1284 - int *codec_conf_index, 1285 - bool *ignore_pch_dmic, 1286 - bool append_dai_type, 1287 - int adr_index, 1288 - int dai_index) 1482 + static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends) 1289 1483 { 1290 - struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1291 1484 struct device *dev = card->dev; 1292 - const struct snd_soc_acpi_link_adr *adr_link_next; 1293 - struct snd_soc_dai_link_component *codecs; 1294 - struct snd_soc_dai_link_component *cpus; 1295 - struct sof_sdw_codec_info *codec_info; 1296 - int cpu_dai_id[SDW_MAX_CPU_DAIS]; 1297 - int cpu_dai_num; 1298 - unsigned int group_id; 1299 - int codec_dlc_index = 0; 1300 - int codec_index; 1301 - int codec_num; 1302 - int stream; 1303 - int i = 0; 1304 - int j, k; 1305 - int ret; 1485 + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); 1486 + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1487 + const struct snd_soc_acpi_link_adr *adr_link; 1488 + int i; 1306 1489 1307 - ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, 1308 - &group_id, adr_index); 1309 - if (ret) 1310 - return ret; 1490 + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { 1491 + *num_devs += adr_link->num_adr; 1311 1492 1312 - codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); 1313 - if (!codecs) 1314 - return -ENOMEM; 1493 + for (i = 0; i < adr_link->num_adr; i++) 1494 + *num_ends += adr_link->adr_d[i].num_endpoints; 1495 + } 1315 1496 1316 - /* generate codec name on different links in the same group */ 1317 - j = adr_index; 1318 - for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && 1319 - i < cpu_dai_num; adr_link_next++) { 1320 - /* skip the link excluded by this processed group */ 1321 - if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) 1322 - continue; 1497 + dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends); 1323 1498 1324 - /* j reset after loop, adr_index only applies to first link */ 1325 - for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) { 1326 - const struct snd_soc_acpi_endpoint *endpoints; 1499 + return 0; 1500 + } 1327 1501 1328 - endpoints = adr_link_next->adr_d[j].endpoints; 1502 + static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks, 1503 + const struct snd_soc_acpi_endpoint *new) 1504 + { 1505 + while (dailinks->initialised) { 1506 + if (new->aggregated && dailinks->group_id == new->group_id) 1507 + return dailinks; 1329 1508 1330 - if (group_id && (!endpoints->aggregated || 1331 - endpoints->group_id != group_id)) 1332 - continue; 1509 + dailinks++; 1510 + } 1333 1511 1334 - /* sanity check */ 1335 - if (*codec_conf_index >= codec_count) { 1336 - dev_err(dev, "codec_conf array overflowed\n"); 1512 + INIT_LIST_HEAD(&dailinks->endpoints); 1513 + dailinks->group_id = new->group_id; 1514 + dailinks->initialised = true; 1515 + 1516 + return dailinks; 1517 + } 1518 + 1519 + static int parse_sdw_endpoints(struct snd_soc_card *card, 1520 + struct sof_sdw_dailink *sof_dais, 1521 + struct sof_sdw_endpoint *sof_ends) 1522 + { 1523 + struct device *dev = card->dev; 1524 + struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1525 + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); 1526 + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1527 + struct snd_soc_codec_conf *codec_conf = card->codec_conf; 1528 + const struct snd_soc_acpi_link_adr *adr_link; 1529 + struct sof_sdw_endpoint *sof_end = sof_ends; 1530 + int num_dais = 0; 1531 + int i, j; 1532 + 1533 + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { 1534 + int num_link_dailinks = 0; 1535 + 1536 + if (!is_power_of_2(adr_link->mask)) { 1537 + dev_err(dev, "link with multiple mask bits: 0x%x\n", 1538 + adr_link->mask); 1539 + return -EINVAL; 1540 + } 1541 + 1542 + for (i = 0; i < adr_link->num_adr; i++) { 1543 + const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i]; 1544 + struct sof_sdw_codec_info *codec_info; 1545 + const char *codec_name; 1546 + 1547 + if (!adr_dev->name_prefix) { 1548 + dev_err(dev, "codec 0x%llx does not have a name prefix\n", 1549 + adr_dev->adr); 1337 1550 return -EINVAL; 1338 1551 } 1339 1552 1340 - ret = fill_sdw_codec_dlc(dev, adr_link_next, 1341 - &codecs[codec_dlc_index], 1342 - j, dai_index); 1343 - if (ret) 1344 - return ret; 1553 + codec_info = find_codec_info_part(adr_dev->adr); 1554 + if (!codec_info) 1555 + return -EINVAL; 1345 1556 1346 - codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index]; 1347 - codec_conf[*codec_conf_index].name_prefix = 1348 - adr_link_next->adr_d[j].name_prefix; 1557 + ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; 1349 1558 1350 - codec_dlc_index++; 1351 - (*codec_conf_index)++; 1559 + codec_name = get_codec_name(dev, codec_info, adr_link, i); 1560 + if (!codec_name) 1561 + return -ENOMEM; 1562 + 1563 + codec_conf->dlc.name = codec_name; 1564 + codec_conf->name_prefix = adr_dev->name_prefix; 1565 + codec_conf++; 1566 + 1567 + dev_dbg(dev, "Adding prefix %s for %s\n", 1568 + adr_dev->name_prefix, codec_name); 1569 + 1570 + for (j = 0; j < adr_dev->num_endpoints; j++) { 1571 + const struct snd_soc_acpi_endpoint *adr_end; 1572 + const struct sof_sdw_dai_info *dai_info; 1573 + struct sof_sdw_dailink *sof_dai; 1574 + int stream; 1575 + 1576 + adr_end = &adr_dev->endpoints[j]; 1577 + dai_info = &codec_info->dais[adr_end->num]; 1578 + sof_dai = find_dailink(sof_dais, adr_end); 1579 + 1580 + if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk)) 1581 + continue; 1582 + 1583 + dev_dbg(dev, 1584 + "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", 1585 + ffs(adr_link->mask) - 1, adr_dev->adr, 1586 + adr_end->num, type_strings[dai_info->dai_type], 1587 + dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-', 1588 + dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-', 1589 + adr_end->aggregated ? "group" : "solo", 1590 + adr_end->group_id); 1591 + 1592 + if (adr_end->num >= codec_info->dai_num) { 1593 + dev_err(dev, 1594 + "%d is too many endpoints for codec: 0x%x\n", 1595 + adr_end->num, codec_info->part_id); 1596 + return -EINVAL; 1597 + } 1598 + 1599 + for_each_pcm_streams(stream) { 1600 + if (dai_info->direction[stream] && 1601 + dai_info->dailink[stream] < 0) { 1602 + dev_err(dev, 1603 + "Invalid dailink id %d for codec: 0x%x\n", 1604 + dai_info->dailink[stream], 1605 + codec_info->part_id); 1606 + return -EINVAL; 1607 + } 1608 + 1609 + if (dai_info->direction[stream]) { 1610 + num_dais += !sof_dai->num_devs[stream]; 1611 + sof_dai->num_devs[stream]++; 1612 + sof_dai->link_mask[stream] |= adr_link->mask; 1613 + } 1614 + } 1615 + 1616 + num_link_dailinks += !!list_empty(&sof_dai->endpoints); 1617 + list_add_tail(&sof_end->list, &sof_dai->endpoints); 1618 + 1619 + sof_end->link_mask = adr_link->mask; 1620 + sof_end->codec_name = codec_name; 1621 + sof_end->codec_info = codec_info; 1622 + sof_end->dai_info = dai_info; 1623 + sof_end++; 1624 + } 1352 1625 } 1353 - j = 0; 1354 1626 1355 - /* check next link to create codec dai in the processed group */ 1356 - i++; 1627 + ctx->append_dai_type |= (num_link_dailinks > 1); 1357 1628 } 1358 1629 1359 - /* find codec info to create BE DAI */ 1360 - codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr); 1361 - if (codec_index < 0) 1362 - return codec_index; 1363 - codec_info = &codec_info_list[codec_index]; 1630 + WARN_ON(codec_conf != card->codec_conf + card->num_configs); 1364 1631 1365 - if (codec_info->ignore_pch_dmic) 1366 - *ignore_pch_dmic = true; 1632 + return num_dais; 1633 + } 1634 + 1635 + static int create_sdw_dailink(struct snd_soc_card *card, 1636 + struct sof_sdw_dailink *sof_dai, 1637 + struct snd_soc_dai_link **dai_links, 1638 + int *be_id) 1639 + { 1640 + struct device *dev = card->dev; 1641 + struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1642 + struct sof_sdw_endpoint *sof_end; 1643 + int stream; 1367 1644 1368 1645 for_each_pcm_streams(stream) { 1369 - struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; 1370 - char *name, *cpu_name; 1371 - int playback, capture; 1372 1646 static const char * const sdw_stream_name[] = { 1373 1647 "SDW%d-Playback", 1374 1648 "SDW%d-Capture", 1375 1649 "SDW%d-Playback-%s", 1376 1650 "SDW%d-Capture-%s", 1377 1651 }; 1652 + struct snd_soc_dai_link_ch_map *codec_maps; 1653 + struct snd_soc_dai_link_component *codecs; 1654 + struct snd_soc_dai_link_component *cpus; 1655 + int num_cpus = hweight32(sof_dai->link_mask[stream]); 1656 + int num_codecs = sof_dai->num_devs[stream]; 1657 + int playback, capture; 1658 + int cur_link = 0; 1659 + int i = 0, j = 0; 1660 + char *name; 1378 1661 1379 - if (!codec_info->dais[dai_index].direction[stream]) 1662 + if (!sof_dai->num_devs[stream]) 1380 1663 continue; 1381 1664 1382 - *be_id = codec_info->dais[dai_index].dailink[stream]; 1665 + sof_end = list_first_entry(&sof_dai->endpoints, 1666 + struct sof_sdw_endpoint, list); 1667 + 1668 + *be_id = sof_end->dai_info->dailink[stream]; 1383 1669 if (*be_id < 0) { 1384 1670 dev_err(dev, "Invalid dailink id %d\n", *be_id); 1385 1671 return -EINVAL; 1386 1672 } 1387 1673 1388 - sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, 1389 - sizeof(*sdw_codec_ch_maps), GFP_KERNEL); 1390 - if (!sdw_codec_ch_maps) 1391 - return -ENOMEM; 1392 - 1393 1674 /* create stream name according to first link id */ 1394 - if (append_dai_type) { 1675 + if (ctx->append_dai_type) 1395 1676 name = devm_kasprintf(dev, GFP_KERNEL, 1396 - sdw_stream_name[stream + 2], cpu_dai_id[0], 1397 - type_strings[codec_info->dais[dai_index].dai_type]); 1398 - } else { 1677 + sdw_stream_name[stream + 2], 1678 + ffs(sof_end->link_mask) - 1, 1679 + type_strings[sof_end->dai_info->dai_type]); 1680 + else 1399 1681 name = devm_kasprintf(dev, GFP_KERNEL, 1400 - sdw_stream_name[stream], cpu_dai_id[0]); 1401 - } 1682 + sdw_stream_name[stream], 1683 + ffs(sof_end->link_mask) - 1); 1402 1684 if (!name) 1403 1685 return -ENOMEM; 1404 1686 1405 - cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL); 1687 + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); 1406 1688 if (!cpus) 1407 1689 return -ENOMEM; 1408 1690 1409 - /* 1410 - * generate CPU DAI name base on the sdw link ID and 1411 - * PIN ID with offset of 2 according to sdw dai driver. 1412 - */ 1413 - for (k = 0; k < cpu_dai_num; k++) { 1414 - cpu_name = devm_kasprintf(dev, GFP_KERNEL, 1415 - "SDW%d Pin%d", cpu_dai_id[k], 1416 - ctx->sdw_pin_index[cpu_dai_id[k]]++); 1417 - if (!cpu_name) 1418 - return -ENOMEM; 1691 + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); 1692 + if (!codecs) 1693 + return -ENOMEM; 1419 1694 1420 - cpus[k].dai_name = cpu_name; 1695 + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); 1696 + if (!codec_maps) 1697 + return -ENOMEM; 1698 + 1699 + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 1700 + if (!sof_end->dai_info->direction[stream]) 1701 + continue; 1702 + 1703 + if (cur_link != sof_end->link_mask) { 1704 + int link_num = ffs(sof_end->link_mask) - 1; 1705 + int pin_num = ctx->sdw_pin_index[link_num]++; 1706 + 1707 + cur_link = sof_end->link_mask; 1708 + 1709 + cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, 1710 + "SDW%d Pin%d", 1711 + link_num, pin_num); 1712 + if (!cpus[i].dai_name) 1713 + return -ENOMEM; 1714 + i++; 1715 + } 1716 + 1717 + codec_maps[j].cpu = i - 1; 1718 + codec_maps[j].codec = j; 1719 + 1720 + codecs[j].name = sof_end->codec_name; 1721 + codecs[j].dai_name = sof_end->dai_info->dai_name; 1722 + j++; 1421 1723 } 1422 1724 1423 - /* 1424 - * We create sdw dai links at first stage, so link index should 1425 - * not be larger than sdw_be_num 1426 - */ 1427 - if (*link_index >= sdw_be_num) { 1428 - dev_err(dev, "invalid dai link index %d\n", *link_index); 1429 - return -EINVAL; 1430 - } 1725 + WARN_ON(i != num_cpus || j != num_codecs); 1431 1726 1432 1727 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 1433 1728 capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 1434 1729 1435 - init_dai_link(dev, dai_links + *link_index, be_id, name, 1436 - playback, capture, cpus, cpu_dai_num, codecs, codec_num, 1730 + init_dai_link(dev, *dai_links, be_id, name, playback, capture, 1731 + cpus, num_cpus, codecs, num_codecs, 1437 1732 sof_sdw_rtd_init, &sdw_ops); 1438 1733 1439 1734 /* 1440 1735 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 1441 1736 * based on wait_for_completion(), tag them as 'nonatomic'. 1442 1737 */ 1443 - dai_links[*link_index].nonatomic = true; 1738 + (*dai_links)->nonatomic = true; 1739 + (*dai_links)->ch_maps = codec_maps; 1444 1740 1445 - set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num); 1446 - dai_links[*link_index].ch_maps = sdw_codec_ch_maps; 1447 - ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, 1448 - playback, group_id, adr_index, dai_index); 1449 - if (ret < 0) { 1450 - dev_err(dev, "failed to init codec %d\n", codec_index); 1451 - return ret; 1741 + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { 1742 + if (sof_end->dai_info->init) 1743 + sof_end->dai_info->init(card, *dai_links, 1744 + sof_end->codec_info, 1745 + playback); 1452 1746 } 1747 + 1748 + (*dai_links)++; 1453 1749 } 1750 + 1751 + return 0; 1752 + } 1753 + 1754 + static int create_sdw_dailinks(struct snd_soc_card *card, 1755 + struct snd_soc_dai_link **dai_links, int *be_id, 1756 + struct sof_sdw_dailink *sof_dais) 1757 + { 1758 + struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1759 + int ret, i; 1760 + 1761 + for (i = 0; i < SDW_MAX_LINKS; i++) 1762 + ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; 1763 + 1764 + /* generate DAI links by each sdw link */ 1765 + while (sof_dais->initialised) { 1766 + int current_be_id; 1767 + 1768 + ret = create_sdw_dailink(card, sof_dais, dai_links, &current_be_id); 1769 + if (ret) 1770 + return ret; 1771 + 1772 + /* Update the be_id to match the highest ID used for SDW link */ 1773 + if (*be_id < current_be_id) 1774 + *be_id = current_be_id; 1775 + 1776 + sof_dais++; 1777 + } 1778 + 1779 + return 0; 1780 + } 1781 + 1782 + static int create_ssp_dailinks(struct snd_soc_card *card, 1783 + struct snd_soc_dai_link **dai_links, int *be_id, 1784 + struct sof_sdw_codec_info *ssp_info, 1785 + unsigned long ssp_mask) 1786 + { 1787 + struct device *dev = card->dev; 1788 + int i, j = 0; 1789 + int ret; 1790 + 1791 + for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { 1792 + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); 1793 + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1794 + char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1795 + ssp_info->acpi_id, j++); 1796 + int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 1797 + int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 1798 + 1799 + ret = init_simple_dai_link(dev, *dai_links, be_id, name, 1800 + playback, capture, cpu_dai_name, 1801 + codec_name, ssp_info->dais[0].dai_name, 1802 + NULL, ssp_info->ops); 1803 + if (ret) 1804 + return ret; 1805 + 1806 + ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0); 1807 + if (ret < 0) 1808 + return ret; 1809 + 1810 + (*dai_links)++; 1811 + } 1812 + 1813 + return 0; 1814 + } 1815 + 1816 + static int create_dmic_dailinks(struct snd_soc_card *card, 1817 + struct snd_soc_dai_link **dai_links, int *be_id) 1818 + { 1819 + struct device *dev = card->dev; 1820 + int ret; 1821 + 1822 + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01", 1823 + 0, 1, // DMIC only supports capture 1824 + "DMIC01 Pin", "dmic-codec", "dmic-hifi", 1825 + sof_sdw_dmic_init, NULL); 1826 + if (ret) 1827 + return ret; 1828 + 1829 + (*dai_links)++; 1830 + 1831 + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", 1832 + 0, 1, // DMIC only supports capture 1833 + "DMIC16k Pin", "dmic-codec", "dmic-hifi", 1834 + /* don't call sof_sdw_dmic_init() twice */ 1835 + NULL, NULL); 1836 + if (ret) 1837 + return ret; 1838 + 1839 + (*dai_links)++; 1840 + 1841 + return 0; 1842 + } 1843 + 1844 + static int create_hdmi_dailinks(struct snd_soc_card *card, 1845 + struct snd_soc_dai_link **dai_links, int *be_id, 1846 + int hdmi_num) 1847 + { 1848 + struct device *dev = card->dev; 1849 + struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1850 + int i, ret; 1851 + 1852 + for (i = 0; i < hdmi_num; i++) { 1853 + char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); 1854 + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); 1855 + char *codec_name, *codec_dai_name; 1856 + 1857 + if (ctx->hdmi.idisp_codec) { 1858 + codec_name = "ehdaudio0D2"; 1859 + codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, 1860 + "intel-hdmi-hifi%d", i + 1); 1861 + } else { 1862 + codec_name = "snd-soc-dummy"; 1863 + codec_dai_name = "snd-soc-dummy-dai"; 1864 + } 1865 + 1866 + ret = init_simple_dai_link(dev, *dai_links, be_id, name, 1867 + 1, 0, // HDMI only supports playback 1868 + cpu_dai_name, codec_name, codec_dai_name, 1869 + i == 0 ? sof_sdw_hdmi_init : NULL, NULL); 1870 + if (ret) 1871 + return ret; 1872 + 1873 + (*dai_links)++; 1874 + } 1875 + 1876 + return 0; 1877 + } 1878 + 1879 + static int create_bt_dailinks(struct snd_soc_card *card, 1880 + struct snd_soc_dai_link **dai_links, int *be_id) 1881 + { 1882 + struct device *dev = card->dev; 1883 + int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1884 + SOF_BT_OFFLOAD_SSP_SHIFT; 1885 + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1886 + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1887 + int ret; 1888 + 1889 + ret = init_simple_dai_link(dev, *dai_links, be_id, name, 1890 + 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, 1891 + snd_soc_dummy_dlc.dai_name, NULL, NULL); 1892 + if (ret) 1893 + return ret; 1894 + 1895 + (*dai_links)++; 1454 1896 1455 1897 return 0; 1456 1898 } ··· 1720 1646 int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; 1721 1647 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1722 1648 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1723 - const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; 1724 - bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); 1725 1649 struct snd_soc_codec_conf *codec_conf; 1726 - bool append_dai_type = false; 1727 - bool ignore_pch_dmic = false; 1728 - int codec_conf_num = 0; 1729 - int codec_conf_index = 0; 1730 - bool group_generated[SDW_MAX_GROUPS] = { }; 1731 - int ssp_codec_index, ssp_mask; 1650 + struct sof_sdw_codec_info *ssp_info; 1651 + struct sof_sdw_endpoint *sof_ends; 1652 + struct sof_sdw_dailink *sof_dais; 1653 + int num_devs = 0; 1654 + int num_ends = 0; 1732 1655 struct snd_soc_dai_link *dai_links; 1733 - int num_links, link_index = 0; 1734 - char *name, *cpu_dai_name; 1735 - char *codec_name, *codec_dai_name; 1736 - int i, j, be_id = 0; 1737 - int codec_index; 1656 + int num_links; 1657 + int be_id = 0; 1738 1658 int hdmi_num; 1659 + unsigned long ssp_mask; 1739 1660 int ret; 1740 1661 1741 - ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); 1662 + ret = count_sdw_endpoints(card, &num_devs, &num_ends); 1742 1663 if (ret < 0) { 1743 - dev_err(dev, "failed to get sdw link info %d\n", ret); 1664 + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); 1744 1665 return ret; 1745 1666 } 1667 + 1668 + /* One per DAI link, worst case is a DAI link for every endpoint */ 1669 + sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); 1670 + if (!sof_dais) 1671 + return -ENOMEM; 1672 + 1673 + /* One per endpoint, ie. each DAI on each codec/amp */ 1674 + sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); 1675 + if (!sof_ends) { 1676 + ret = -ENOMEM; 1677 + goto err_dai; 1678 + } 1679 + 1680 + /* will be populated when acpi endpoints are parsed */ 1681 + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); 1682 + if (!codec_conf) { 1683 + ret = -ENOMEM; 1684 + goto err_end; 1685 + } 1686 + 1687 + card->codec_conf = codec_conf; 1688 + card->num_configs = num_devs; 1689 + 1690 + ret = parse_sdw_endpoints(card, sof_dais, sof_ends); 1691 + if (ret < 0) 1692 + goto err_end; 1693 + 1694 + sdw_be_num = ret; 1746 1695 1747 1696 /* 1748 1697 * on generic tgl platform, I2S or sdw mode is supported ··· 1773 1676 * system only when I2S mode is supported, not sdw mode. 1774 1677 * Here check ACPI ID to confirm I2S is supported. 1775 1678 */ 1776 - ssp_codec_index = find_codec_info_acpi(mach->id); 1777 - if (ssp_codec_index >= 0) { 1679 + ssp_info = find_codec_info_acpi(mach->id); 1680 + if (ssp_info) { 1778 1681 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); 1779 1682 ssp_num = hweight_long(ssp_mask); 1780 1683 } ··· 1801 1704 /* allocate BE dailinks */ 1802 1705 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; 1803 1706 dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 1804 - if (!dai_links) 1805 - return -ENOMEM; 1806 - 1807 - /* allocate codec conf, will be populated when dailinks are created */ 1808 - codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), 1809 - GFP_KERNEL); 1810 - if (!codec_conf) 1811 - return -ENOMEM; 1812 - 1813 - /* SDW */ 1814 - if (!sdw_be_num) 1815 - goto SSP; 1816 - 1817 - for (i = 0; i < SDW_MAX_LINKS; i++) 1818 - ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; 1819 - 1820 - for (; adr_link->num_adr; adr_link++) { 1821 - /* 1822 - * If there are two or more different devices on the same sdw link, we have to 1823 - * append the codec type to the dai link name to prevent duplicated dai link name. 1824 - * The same type devices on the same sdw link will be in the same 1825 - * snd_soc_acpi_adr_device array. They won't be described in different adr_links. 1826 - */ 1827 - for (i = 0; i < adr_link->num_adr; i++) { 1828 - /* find codec info to get dai_num */ 1829 - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1830 - if (codec_index < 0) 1831 - return codec_index; 1832 - if (codec_info_list[codec_index].dai_num > 1) { 1833 - append_dai_type = true; 1834 - goto out; 1835 - } 1836 - for (j = 0; j < i; j++) { 1837 - if ((SDW_PART_ID(adr_link->adr_d[i].adr) != 1838 - SDW_PART_ID(adr_link->adr_d[j].adr)) || 1839 - (SDW_MFG_ID(adr_link->adr_d[i].adr) != 1840 - SDW_MFG_ID(adr_link->adr_d[j].adr))) { 1841 - append_dai_type = true; 1842 - goto out; 1843 - } 1844 - } 1845 - } 1846 - } 1847 - out: 1848 - 1849 - /* generate DAI links by each sdw link */ 1850 - for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { 1851 - for (i = 0; i < adr_link->num_adr; i++) { 1852 - const struct snd_soc_acpi_endpoint *endpoint; 1853 - 1854 - endpoint = adr_link->adr_d[i].endpoints; 1855 - 1856 - /* this group has been generated */ 1857 - if (endpoint->aggregated && 1858 - group_generated[endpoint->group_id]) 1859 - continue; 1860 - 1861 - /* find codec info to get dai_num */ 1862 - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); 1863 - if (codec_index < 0) 1864 - return codec_index; 1865 - 1866 - for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) { 1867 - int current_be_id; 1868 - 1869 - ret = create_sdw_dailink(card, &link_index, dai_links, 1870 - sdw_be_num, adr_link, 1871 - codec_conf, codec_conf_num, 1872 - &current_be_id, &codec_conf_index, 1873 - &ignore_pch_dmic, append_dai_type, i, j); 1874 - if (ret < 0) { 1875 - dev_err(dev, "failed to create dai link %d\n", link_index); 1876 - return ret; 1877 - } 1878 - 1879 - /* Update the be_id to match the highest ID used for SDW link */ 1880 - if (be_id < current_be_id) 1881 - be_id = current_be_id; 1882 - } 1883 - 1884 - if (aggregation && endpoint->aggregated) 1885 - group_generated[endpoint->group_id] = true; 1886 - } 1887 - } 1888 - 1889 - SSP: 1890 - /* SSP */ 1891 - if (!ssp_num) 1892 - goto DMIC; 1893 - 1894 - for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { 1895 - struct sof_sdw_codec_info *info; 1896 - int playback, capture; 1897 - 1898 - if (!(ssp_mask & 0x1)) 1899 - continue; 1900 - 1901 - info = &codec_info_list[ssp_codec_index]; 1902 - 1903 - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); 1904 - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); 1905 - codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", 1906 - info->acpi_id, j++); 1907 - 1908 - playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; 1909 - capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; 1910 - 1911 - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1912 - playback, capture, cpu_dai_name, 1913 - codec_name, info->dais[0].dai_name, 1914 - NULL, info->ops); 1915 - if (ret) 1916 - return ret; 1917 - 1918 - ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0); 1919 - if (ret < 0) 1920 - return ret; 1921 - 1922 - link_index++; 1923 - } 1924 - 1925 - DMIC: 1926 - /* dmic */ 1927 - if (dmic_num > 0) { 1928 - if (ignore_pch_dmic) { 1929 - dev_warn(dev, "Ignoring PCH DMIC\n"); 1930 - goto HDMI; 1931 - } 1932 - 1933 - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic01", 1934 - 0, 1, // DMIC only supports capture 1935 - "DMIC01 Pin", "dmic-codec", "dmic-hifi", 1936 - sof_sdw_dmic_init, NULL); 1937 - if (ret) 1938 - return ret; 1939 - 1940 - link_index++; 1941 - 1942 - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic16k", 1943 - 0, 1, // DMIC only supports capture 1944 - "DMIC16k Pin", "dmic-codec", "dmic-hifi", 1945 - /* don't call sof_sdw_dmic_init() twice */ 1946 - NULL, NULL); 1947 - if (ret) 1948 - return ret; 1949 - 1950 - link_index++; 1951 - } 1952 - 1953 - HDMI: 1954 - /* HDMI */ 1955 - for (i = 0; i < hdmi_num; i++) { 1956 - name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); 1957 - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); 1958 - 1959 - if (ctx->hdmi.idisp_codec) { 1960 - codec_name = "ehdaudio0D2"; 1961 - codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, 1962 - "intel-hdmi-hifi%d", i + 1); 1963 - } else { 1964 - codec_name = "snd-soc-dummy"; 1965 - codec_dai_name = "snd-soc-dummy-dai"; 1966 - } 1967 - 1968 - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1969 - 1, 0, // HDMI only supports playback 1970 - cpu_dai_name, codec_name, codec_dai_name, 1971 - i == 0 ? sof_sdw_hdmi_init : NULL, NULL); 1972 - if (ret) 1973 - return ret; 1974 - 1975 - link_index++; 1976 - } 1977 - 1978 - if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1979 - int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> 1980 - SOF_BT_OFFLOAD_SSP_SHIFT; 1981 - 1982 - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); 1983 - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); 1984 - 1985 - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, 1986 - 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, 1987 - snd_soc_dummy_dlc.dai_name, NULL, NULL); 1988 - if (ret) 1989 - return ret; 1707 + if (!dai_links) { 1708 + ret = -ENOMEM; 1709 + goto err_end; 1990 1710 } 1991 1711 1992 1712 card->dai_link = dai_links; 1993 1713 card->num_links = num_links; 1994 1714 1995 - card->codec_conf = codec_conf; 1996 - card->num_configs = codec_conf_num; 1715 + /* SDW */ 1716 + if (sdw_be_num) { 1717 + ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais); 1718 + if (ret) 1719 + goto err_end; 1720 + } 1997 1721 1998 - return 0; 1722 + /* SSP */ 1723 + if (ssp_num) { 1724 + ret = create_ssp_dailinks(card, &dai_links, &be_id, 1725 + ssp_info, ssp_mask); 1726 + if (ret) 1727 + goto err_end; 1728 + } 1729 + 1730 + /* dmic */ 1731 + if (dmic_num > 0) { 1732 + if (ctx->ignore_pch_dmic) { 1733 + dev_warn(dev, "Ignoring PCH DMIC\n"); 1734 + } else { 1735 + ret = create_dmic_dailinks(card, &dai_links, &be_id); 1736 + if (ret) 1737 + goto err_end; 1738 + } 1739 + } 1740 + 1741 + /* HDMI */ 1742 + ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); 1743 + if (ret) 1744 + goto err_end; 1745 + 1746 + /* BT */ 1747 + if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { 1748 + ret = create_bt_dailinks(card, &dai_links, &be_id); 1749 + if (ret) 1750 + goto err_end; 1751 + } 1752 + 1753 + WARN_ON(dai_links != card->dai_link + card->num_links); 1754 + 1755 + err_end: 1756 + kfree(sof_ends); 1757 + err_dai: 1758 + kfree(sof_dais); 1759 + 1760 + return ret; 1999 1761 } 2000 1762 2001 1763 static int sof_sdw_card_late_probe(struct snd_soc_card *card)
+20 -22
sound/soc/intel/boards/sof_sdw_common.h
··· 50 50 #define SOF_SDW_PCH_DMIC BIT(6) 51 51 #define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7) 52 52 #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) 53 + /* Deprecated and no longer supported by the code */ 53 54 #define SOF_SDW_NO_AGGREGATION BIT(14) 55 + /* If a CODEC has an optional speaker output, this quirk will enable it */ 56 + #define SOF_CODEC_SPKR BIT(15) 54 57 55 58 /* BT audio offload: reserve 3 bits for future */ 56 59 #define SOF_BT_OFFLOAD_SSP_SHIFT 15 ··· 66 63 #define SOF_SDW_DAI_TYPE_AMP 1 67 64 #define SOF_SDW_DAI_TYPE_MIC 2 68 65 69 - #define SOF_SDW_MAX_DAI_NUM 3 66 + #define SOF_SDW_MAX_DAI_NUM 8 70 67 71 68 struct sof_sdw_codec_info; 72 69 ··· 76 73 const int dai_type; 77 74 const int dailink[2]; /* dailink id for each direction */ 78 75 int (*init)(struct snd_soc_card *card, 79 - const struct snd_soc_acpi_link_adr *link, 80 76 struct snd_soc_dai_link *dai_links, 81 77 struct sof_sdw_codec_info *info, 82 78 bool playback); 83 79 int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 84 80 int (*rtd_init)(struct snd_soc_pcm_runtime *rtd); 85 81 bool rtd_init_done; /* Indicate that the rtd_init callback is done */ 82 + unsigned long quirk; 86 83 }; 87 84 88 85 struct sof_sdw_codec_info { ··· 106 103 struct device *amp_dev1, *amp_dev2; 107 104 /* To store SDW Pin index for each SoundWire link */ 108 105 unsigned int sdw_pin_index[SDW_MAX_LINKS]; 106 + bool append_dai_type; 107 + bool ignore_pch_dmic; 109 108 }; 110 109 111 110 extern unsigned long sof_sdw_quirk; 111 + 112 + struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 113 + const char * const dai_name[], 114 + int num_dais); 112 115 113 116 int sdw_startup(struct snd_pcm_substream *substream); 114 117 int sdw_prepare(struct snd_pcm_substream *substream); ··· 134 125 135 126 /* RT711 support */ 136 127 int sof_sdw_rt711_init(struct snd_soc_card *card, 137 - const struct snd_soc_acpi_link_adr *link, 138 128 struct snd_soc_dai_link *dai_links, 139 129 struct sof_sdw_codec_info *info, 140 130 bool playback); ··· 141 133 142 134 /* RT711-SDCA support */ 143 135 int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, 144 - const struct snd_soc_acpi_link_adr *link, 145 136 struct snd_soc_dai_link *dai_links, 146 137 struct sof_sdw_codec_info *info, 147 138 bool playback); ··· 151 144 152 145 /* generic amp support */ 153 146 int sof_sdw_rt_amp_init(struct snd_soc_card *card, 154 - const struct snd_soc_acpi_link_adr *link, 155 147 struct snd_soc_dai_link *dai_links, 156 148 struct sof_sdw_codec_info *info, 157 149 bool playback); 158 150 int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 159 151 160 - /* RT722-SDCA support */ 161 - int sof_sdw_rt722_spk_init(struct snd_soc_card *card, 162 - const struct snd_soc_acpi_link_adr *link, 163 - struct snd_soc_dai_link *dai_links, 164 - struct sof_sdw_codec_info *info, 165 - bool playback); 166 - int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, 167 - const struct snd_soc_acpi_link_adr *link, 168 - struct snd_soc_dai_link *dai_links, 169 - struct sof_sdw_codec_info *info, 170 - bool playback); 171 - 172 152 /* MAXIM codec support */ 173 153 int sof_sdw_maxim_init(struct snd_soc_card *card, 174 - const struct snd_soc_acpi_link_adr *link, 175 154 struct snd_soc_dai_link *dai_links, 176 155 struct sof_sdw_codec_info *info, 177 156 bool playback); 178 157 158 + /* CS42L43 support */ 159 + int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, 160 + struct snd_soc_dai_link *dai_links, 161 + struct sof_sdw_codec_info *info, 162 + bool playback); 163 + 179 164 /* CS AMP support */ 180 165 int sof_sdw_cs_amp_init(struct snd_soc_card *card, 181 - const struct snd_soc_acpi_link_adr *link, 182 166 struct snd_soc_dai_link *dai_links, 183 167 struct sof_sdw_codec_info *info, 184 168 bool playback); ··· 178 180 179 181 int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd); 180 182 int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd); 183 + int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 181 184 int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); 182 185 int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 183 186 int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 184 187 int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); 185 188 int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); 186 189 int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); 187 - int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); 188 190 int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 189 - int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); 190 - int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); 191 + int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 192 + int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); 191 193 int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); 192 194 int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); 193 195
-1
sound/soc/intel/boards/sof_sdw_cs42l42.c
··· 15 15 #include <sound/soc-acpi.h> 16 16 #include <sound/soc-dapm.h> 17 17 #include <sound/jack.h> 18 - #include "sof_board_helpers.h" 19 18 #include "sof_sdw_common.h" 20 19 21 20 static const struct snd_soc_dapm_widget cs42l42_widgets[] = {
+50
sound/soc/intel/boards/sof_sdw_cs42l43.c
··· 30 30 { "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" }, 31 31 }; 32 32 33 + static const struct snd_soc_dapm_widget cs42l43_spk_widgets[] = { 34 + SND_SOC_DAPM_SPK("Speaker", NULL), 35 + }; 36 + 37 + static const struct snd_soc_dapm_route cs42l43_spk_map[] = { 38 + { "Speaker", NULL, "cs42l43 AMP1_OUT_P", }, 39 + { "Speaker", NULL, "cs42l43 AMP1_OUT_N", }, 40 + { "Speaker", NULL, "cs42l43 AMP2_OUT_P", }, 41 + { "Speaker", NULL, "cs42l43 AMP2_OUT_N", }, 42 + }; 43 + 33 44 static const struct snd_soc_dapm_widget cs42l43_dmic_widgets[] = { 34 45 SND_SOC_DAPM_MIC("DMIC", NULL), 35 46 }; ··· 117 106 dev_err(card->dev, "Failed to set sysclk: %d\n", ret); 118 107 119 108 return ret; 109 + } 110 + 111 + int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) 112 + { 113 + struct snd_soc_card *card = rtd->card; 114 + int ret; 115 + 116 + card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk", 117 + card->components); 118 + if (!card->components) 119 + return -ENOMEM; 120 + 121 + ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets, 122 + ARRAY_SIZE(cs42l43_spk_widgets)); 123 + if (ret) { 124 + dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret); 125 + return ret; 126 + } 127 + 128 + ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, 129 + ARRAY_SIZE(cs42l43_spk_map)); 130 + if (ret) 131 + dev_err(card->dev, "cs42l43 speaker map addition failed: %d\n", ret); 132 + 133 + return ret; 134 + } 135 + 136 + int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, 137 + struct snd_soc_dai_link *dai_links, 138 + struct sof_sdw_codec_info *info, 139 + bool playback) 140 + { 141 + /* Do init on playback link only. */ 142 + if (!playback) 143 + return 0; 144 + 145 + info->amp_num++; 146 + 147 + return 0; 120 148 } 121 149 122 150 int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
-1
sound/soc/intel/boards/sof_sdw_cs_amp.c
··· 57 57 } 58 58 59 59 int sof_sdw_cs_amp_init(struct snd_soc_card *card, 60 - const struct snd_soc_acpi_link_adr *link, 61 60 struct snd_soc_dai_link *dai_links, 62 61 struct sof_sdw_codec_info *info, 63 62 bool playback)
-1
sound/soc/intel/boards/sof_sdw_maxim.c
··· 139 139 } 140 140 141 141 int sof_sdw_maxim_init(struct snd_soc_card *card, 142 - const struct snd_soc_acpi_link_adr *link, 143 142 struct snd_soc_dai_link *dai_links, 144 143 struct sof_sdw_codec_info *info, 145 144 bool playback)
-1
sound/soc/intel/boards/sof_sdw_rt5682.c
··· 15 15 #include <sound/soc-acpi.h> 16 16 #include <sound/soc-dapm.h> 17 17 #include <sound/jack.h> 18 - #include "sof_board_helpers.h" 19 18 #include "sof_sdw_common.h" 20 19 21 20 static const struct snd_soc_dapm_widget rt5682_widgets[] = {
-1
sound/soc/intel/boards/sof_sdw_rt700.c
··· 13 13 #include <sound/soc-acpi.h> 14 14 #include <sound/soc-dapm.h> 15 15 #include <sound/jack.h> 16 - #include "sof_board_helpers.h" 17 16 #include "sof_sdw_common.h" 18 17 19 18 static const struct snd_soc_dapm_widget rt700_widgets[] = {
-2
sound/soc/intel/boards/sof_sdw_rt711.c
··· 15 15 #include <sound/soc-acpi.h> 16 16 #include <sound/soc-dapm.h> 17 17 #include <sound/jack.h> 18 - #include "sof_board_helpers.h" 19 18 #include "sof_sdw_common.h" 20 19 21 20 /* ··· 158 159 } 159 160 160 161 int sof_sdw_rt711_init(struct snd_soc_card *card, 161 - const struct snd_soc_acpi_link_adr *link, 162 162 struct snd_soc_dai_link *dai_links, 163 163 struct sof_sdw_codec_info *info, 164 164 bool playback)
-25
sound/soc/intel/boards/sof_sdw_rt712_sdca.c
··· 13 13 #include <sound/soc.h> 14 14 #include <sound/soc-acpi.h> 15 15 #include <sound/soc-dapm.h> 16 - #include "sof_board_helpers.h" 17 16 #include "sof_sdw_common.h" 18 17 19 18 static const struct snd_soc_dapm_widget rt712_spk_widgets[] = { ··· 66 67 return ret; 67 68 } 68 69 69 - static const char * const dmics[] = { 70 - "rt712-sdca-dmic" 71 - }; 72 - 73 - int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) 74 - { 75 - struct snd_soc_card *card = rtd->card; 76 - struct snd_soc_dai *codec_dai; 77 - struct snd_soc_component *component; 78 - 79 - codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); 80 - if (!codec_dai) 81 - return -EINVAL; 82 - 83 - component = codec_dai->component; 84 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 85 - "%s mic:%s", 86 - card->components, component->name_prefix); 87 - if (!card->components) 88 - return -ENOMEM; 89 - 90 - return 0; 91 - } 92 - MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-26
sound/soc/intel/boards/sof_sdw_rt715.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (c) 2020 Intel Corporation 3 - 4 - /* 5 - * sof_sdw_rt715 - Helpers to handle RT715 from generic machine driver 6 - */ 7 - 8 - #include <linux/device.h> 9 - #include <linux/errno.h> 10 - #include <sound/soc.h> 11 - #include <sound/soc-acpi.h> 12 - #include "sof_sdw_common.h" 13 - 14 - int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd) 15 - { 16 - struct snd_soc_card *card = rtd->card; 17 - 18 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 19 - "%s mic:rt715", 20 - card->components); 21 - if (!card->components) 22 - return -ENOMEM; 23 - 24 - return 0; 25 - } 26 -
-26
sound/soc/intel/boards/sof_sdw_rt715_sdca.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (c) 2020 Intel Corporation 3 - 4 - /* 5 - * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA from generic machine driver 6 - */ 7 - 8 - #include <linux/device.h> 9 - #include <linux/errno.h> 10 - #include <sound/soc.h> 11 - #include <sound/soc-acpi.h> 12 - #include "sof_sdw_common.h" 13 - 14 - int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) 15 - { 16 - struct snd_soc_card *card = rtd->card; 17 - 18 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 19 - "%s mic:rt715-sdca", 20 - card->components); 21 - if (!card->components) 22 - return -ENOMEM; 23 - 24 - return 0; 25 - } 26 -
+1 -37
sound/soc/intel/boards/sof_sdw_rt722_sdca.c
··· 27 27 SOC_DAPM_PIN_SWITCH("Speaker"), 28 28 }; 29 29 30 - static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd) 30 + int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) 31 31 { 32 32 struct snd_soc_card *card = rtd->card; 33 33 int ret; ··· 59 59 return ret; 60 60 } 61 61 62 - int sof_sdw_rt722_spk_init(struct snd_soc_card *card, 63 - const struct snd_soc_acpi_link_adr *link, 64 - struct snd_soc_dai_link *dai_links, 65 - struct sof_sdw_codec_info *info, 66 - bool playback) 67 - { 68 - dai_links->init = rt722_spk_init; 69 - 70 - return 0; 71 - } 72 - 73 - static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) 74 - { 75 - struct snd_soc_card *card = rtd->card; 76 - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 77 - struct snd_soc_component *component = codec_dai->component; 78 - 79 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 80 - "%s mic:%s", 81 - card->components, component->name_prefix); 82 - if (!card->components) 83 - return -ENOMEM; 84 - 85 - return 0; 86 - } 87 - 88 - int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, 89 - const struct snd_soc_acpi_link_adr *link, 90 - struct snd_soc_dai_link *dai_links, 91 - struct sof_sdw_codec_info *info, 92 - bool playback) 93 - { 94 - dai_links->init = rt722_sdca_dmic_rtd_init; 95 - 96 - return 0; 97 - }
-1
sound/soc/intel/boards/sof_sdw_rt_amp.c
··· 281 281 } 282 282 283 283 int sof_sdw_rt_amp_init(struct snd_soc_card *card, 284 - const struct snd_soc_acpi_link_adr *link, 285 284 struct snd_soc_dai_link *dai_links, 286 285 struct sof_sdw_codec_info *info, 287 286 bool playback)
+54
sound/soc/intel/boards/sof_sdw_rt_dmic.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (c) 2024 Intel Corporation 3 + 4 + /* 5 + * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver 6 + */ 7 + 8 + #include <linux/device.h> 9 + #include <linux/errno.h> 10 + #include <sound/soc.h> 11 + #include <sound/soc-acpi.h> 12 + #include "sof_board_helpers.h" 13 + #include "sof_sdw_common.h" 14 + 15 + static const char * const dmics[] = { 16 + "rt715", 17 + "rt715-sdca", 18 + "rt712-sdca-dmic", 19 + "rt722-sdca", 20 + }; 21 + 22 + int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) 23 + { 24 + struct snd_soc_card *card = rtd->card; 25 + struct snd_soc_component *component; 26 + struct snd_soc_dai *codec_dai; 27 + char *mic_name; 28 + 29 + codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); 30 + if (!codec_dai) 31 + return -EINVAL; 32 + 33 + component = codec_dai->component; 34 + 35 + /* 36 + * rt715-sdca (aka rt714) is a special case that uses different name in card->components 37 + * and component->name_prefix. 38 + */ 39 + if (!strcmp(component->name_prefix, "rt714")) 40 + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca"); 41 + else 42 + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix); 43 + 44 + card->components = devm_kasprintf(card->dev, GFP_KERNEL, 45 + "%s mic:%s", card->components, 46 + mic_name); 47 + if (!card->components) 48 + return -ENOMEM; 49 + 50 + dev_dbg(card->dev, "card->components: %s\n", card->components); 51 + 52 + return 0; 53 + } 54 + MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
+1 -3
sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
··· 15 15 #include <sound/soc-acpi.h> 16 16 #include <sound/soc-dapm.h> 17 17 #include <sound/jack.h> 18 - #include "sof_board_helpers.h" 19 18 #include "sof_sdw_common.h" 20 19 21 20 /* ··· 85 86 }; 86 87 87 88 static const char * const jack_codecs[] = { 88 - "rt711", "rt712", "rt713" 89 + "rt711", "rt712", "rt713", "rt722" 89 90 }; 90 91 91 92 int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) ··· 191 192 } 192 193 193 194 int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, 194 - const struct snd_soc_acpi_link_adr *link, 195 195 struct snd_soc_dai_link *dai_links, 196 196 struct sof_sdw_codec_info *info, 197 197 bool playback)
-7
sound/soc/intel/boards/sof_ssp_common.h
··· 68 68 enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); 69 69 enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); 70 70 71 - #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) 72 71 const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); 73 - #else 74 - static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) 75 - { 76 - return NULL; 77 - } 78 - #endif 79 72 80 73 #endif /* __SOF_SSP_COMMON_H */
+24
sound/soc/intel/common/soc-acpi-intel-arl-match.c
··· 24 24 } 25 25 }; 26 26 27 + static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { 28 + { 29 + .adr = 0x000030025D071101ull, 30 + .num_endpoints = 1, 31 + .endpoints = &single_endpoint, 32 + .name_prefix = "rt711" 33 + } 34 + }; 35 + 27 36 static const struct snd_soc_acpi_link_adr arl_rvp[] = { 28 37 { 29 38 .mask = BIT(0), 30 39 .num_adr = ARRAY_SIZE(rt711_0_adr), 31 40 .adr_d = rt711_0_adr, 41 + }, 42 + {} 43 + }; 44 + 45 + static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = { 46 + { 47 + .mask = BIT(0), 48 + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), 49 + .adr_d = rt711_sdca_0_adr, 32 50 }, 33 51 {} 34 52 }; ··· 63 45 .links = arl_rvp, 64 46 .drv_name = "sof_sdw", 65 47 .sof_tplg_filename = "sof-arl-rt711.tplg", 48 + }, 49 + { 50 + .link_mask = 0x1, /* link0 required */ 51 + .links = arl_sdca_rvp, 52 + .drv_name = "sof_sdw", 53 + .sof_tplg_filename = "sof-arl-rt711-l0.tplg", 66 54 }, 67 55 {}, 68 56 };
+31 -4
sound/soc/intel/common/soc-acpi-intel-mtl-match.c
··· 338 338 {} 339 339 }; 340 340 341 + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { 342 + { /* Jack Playback Endpoint */ 343 + .num = 0, 344 + .aggregated = 0, 345 + .group_position = 0, 346 + .group_id = 0, 347 + }, 348 + { /* DMIC Capture Endpoint */ 349 + .num = 1, 350 + .aggregated = 0, 351 + .group_position = 0, 352 + .group_id = 0, 353 + }, 354 + { /* Jack Capture Endpoint */ 355 + .num = 2, 356 + .aggregated = 0, 357 + .group_position = 0, 358 + .group_id = 0, 359 + }, 360 + { /* Speaker Playback Endpoint */ 361 + .num = 3, 362 + .aggregated = 0, 363 + .group_position = 0, 364 + .group_id = 0, 365 + }, 366 + }; 367 + 341 368 static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { 342 369 { 343 370 .adr = 0x00003001FA424301ull, 344 - .num_endpoints = 1, 345 - .endpoints = &single_endpoint, 371 + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), 372 + .endpoints = cs42l43_endpoints, 346 373 .name_prefix = "cs42l43" 347 374 } 348 375 }; ··· 379 352 .adr = 0x00013701FA355601ull, 380 353 .num_endpoints = 1, 381 354 .endpoints = &spk_r_endpoint, 382 - .name_prefix = "AMP8" 355 + .name_prefix = "AMP3" 383 356 }, 384 357 { 385 358 .adr = 0x00013601FA355601ull, 386 359 .num_endpoints = 1, 387 360 .endpoints = &spk_3_endpoint, 388 - .name_prefix = "AMP7" 361 + .name_prefix = "AMP4" 389 362 } 390 363 }; 391 364
+31 -4
sound/soc/intel/common/soc-acpi-intel-tgl-match.c
··· 414 414 {} 415 415 }; 416 416 417 + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { 418 + { /* Jack Playback Endpoint */ 419 + .num = 0, 420 + .aggregated = 0, 421 + .group_position = 0, 422 + .group_id = 0, 423 + }, 424 + { /* DMIC Capture Endpoint */ 425 + .num = 1, 426 + .aggregated = 0, 427 + .group_position = 0, 428 + .group_id = 0, 429 + }, 430 + { /* Jack Capture Endpoint */ 431 + .num = 2, 432 + .aggregated = 0, 433 + .group_position = 0, 434 + .group_id = 0, 435 + }, 436 + { /* Speaker Playback Endpoint */ 437 + .num = 3, 438 + .aggregated = 0, 439 + .group_position = 0, 440 + .group_id = 0, 441 + }, 442 + }; 443 + 417 444 static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = { 418 445 { 419 446 .adr = 0x00033001FA424301ull, 420 - .num_endpoints = 1, 421 - .endpoints = &single_endpoint, 447 + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), 448 + .endpoints = cs42l43_endpoints, 422 449 .name_prefix = "cs42l43" 423 450 } 424 451 }; ··· 470 443 .adr = 0x00013701FA355601ull, 471 444 .num_endpoints = 1, 472 445 .endpoints = &spk_l_endpoint, 473 - .name_prefix = "AMP8" 446 + .name_prefix = "AMP3" 474 447 }, 475 448 { 476 449 .adr = 0x00013601FA355601ull, 477 450 .num_endpoints = 1, 478 451 .endpoints = &spk_2_endpoint, 479 - .name_prefix = "AMP7" 452 + .name_prefix = "AMP4" 480 453 } 481 454 }; 482 455