2222#include <sound/sdca_function.h>
2323#include <sound/soc.h>
2424#include <sound/soc-component.h>
25+ #include <sound/soc-dai.h>
2526#include <sound/soc-dapm.h>
2627#include <sound/tlv.h>
2728
@@ -99,6 +100,8 @@ static bool readonly_control(struct sdca_control *control)
99100 * required number of DAPM routes for the Function.
100101 * @num_controls: Output integer pointer, will be filled with the
101102 * required number of ALSA controls for the Function.
103+ * @num_dais: Output integer pointer, will be filled with the
104+ * required number of ASoC DAIs for the Function.
102105 *
103106 * This function counts various things within the SDCA Function such
104107 * that the calling driver can allocate appropriate space before
@@ -107,13 +110,15 @@ static bool readonly_control(struct sdca_control *control)
107110 * Return: Returns zero on success, and a negative error code on failure.
108111 */
109112int sdca_asoc_count_component (struct device * dev , struct sdca_function_data * function ,
110- int * num_widgets , int * num_routes , int * num_controls )
113+ int * num_widgets , int * num_routes , int * num_controls ,
114+ int * num_dais )
111115{
112116 int i , j ;
113117
114118 * num_widgets = function -> num_entities - 1 ;
115119 * num_routes = 0 ;
116120 * num_controls = 0 ;
121+ * num_dais = 0 ;
117122
118123 for (i = 0 ; i < function -> num_entities - 1 ; i ++ ) {
119124 struct sdca_entity * entity = & function -> entities [i ];
@@ -125,6 +130,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
125130 * num_routes += !!entity -> iot .clock ;
126131 * num_routes += !!entity -> iot .is_dataport ;
127132 * num_controls += !entity -> iot .is_dataport ;
133+ * num_dais += !!entity -> iot .is_dataport ;
128134 break ;
129135 case SDCA_ENTITY_TYPE_PDE :
130136 * num_routes += entity -> pde .num_managed ;
@@ -1033,6 +1039,205 @@ int sdca_asoc_populate_controls(struct device *dev,
10331039}
10341040EXPORT_SYMBOL_NS (sdca_asoc_populate_controls , "SND_SOC_SDCA" );
10351041
1042+ static unsigned int rate_find_mask (unsigned int rate )
1043+ {
1044+ switch (rate ) {
1045+ case 0 :
1046+ return SNDRV_PCM_RATE_8000_768000 ;
1047+ case 5512 :
1048+ return SNDRV_PCM_RATE_5512 ;
1049+ case 8000 :
1050+ return SNDRV_PCM_RATE_8000 ;
1051+ case 11025 :
1052+ return SNDRV_PCM_RATE_11025 ;
1053+ case 16000 :
1054+ return SNDRV_PCM_RATE_16000 ;
1055+ case 22050 :
1056+ return SNDRV_PCM_RATE_22050 ;
1057+ case 32000 :
1058+ return SNDRV_PCM_RATE_32000 ;
1059+ case 44100 :
1060+ return SNDRV_PCM_RATE_44100 ;
1061+ case 48000 :
1062+ return SNDRV_PCM_RATE_48000 ;
1063+ case 64000 :
1064+ return SNDRV_PCM_RATE_64000 ;
1065+ case 88200 :
1066+ return SNDRV_PCM_RATE_88200 ;
1067+ case 96000 :
1068+ return SNDRV_PCM_RATE_96000 ;
1069+ case 176400 :
1070+ return SNDRV_PCM_RATE_176400 ;
1071+ case 192000 :
1072+ return SNDRV_PCM_RATE_192000 ;
1073+ case 352800 :
1074+ return SNDRV_PCM_RATE_352800 ;
1075+ case 384000 :
1076+ return SNDRV_PCM_RATE_384000 ;
1077+ case 705600 :
1078+ return SNDRV_PCM_RATE_705600 ;
1079+ case 768000 :
1080+ return SNDRV_PCM_RATE_768000 ;
1081+ case 12000 :
1082+ return SNDRV_PCM_RATE_12000 ;
1083+ case 24000 :
1084+ return SNDRV_PCM_RATE_24000 ;
1085+ case 128000 :
1086+ return SNDRV_PCM_RATE_128000 ;
1087+ default :
1088+ return 0 ;
1089+ }
1090+ }
1091+
1092+ static u64 width_find_mask (unsigned int bits )
1093+ {
1094+ switch (bits ) {
1095+ case 0 :
1096+ return SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
1097+ SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE |
1098+ SNDRV_PCM_FMTBIT_S32_LE ;
1099+ case 8 :
1100+ return SNDRV_PCM_FMTBIT_S8 ;
1101+ case 16 :
1102+ return SNDRV_PCM_FMTBIT_S16_LE ;
1103+ case 20 :
1104+ return SNDRV_PCM_FMTBIT_S20_LE ;
1105+ case 24 :
1106+ return SNDRV_PCM_FMTBIT_S24_LE ;
1107+ case 32 :
1108+ return SNDRV_PCM_FMTBIT_S32_LE ;
1109+ default :
1110+ return 0 ;
1111+ }
1112+ }
1113+
1114+ static int populate_rate_format (struct device * dev ,
1115+ struct sdca_function_data * function ,
1116+ struct sdca_entity * entity ,
1117+ struct snd_soc_pcm_stream * stream )
1118+ {
1119+ struct sdca_control_range * range ;
1120+ unsigned int sample_rate , sample_width ;
1121+ unsigned int clock_rates = 0 ;
1122+ unsigned int rates = 0 ;
1123+ u64 formats = 0 ;
1124+ int sel , i ;
1125+
1126+ switch (entity -> type ) {
1127+ case SDCA_ENTITY_TYPE_IT :
1128+ sel = SDCA_CTL_IT_USAGE ;
1129+ break ;
1130+ case SDCA_ENTITY_TYPE_OT :
1131+ sel = SDCA_CTL_OT_USAGE ;
1132+ break ;
1133+ default :
1134+ dev_err (dev , "%s: entity type has no usage control\n" ,
1135+ entity -> label );
1136+ return - EINVAL ;
1137+ }
1138+
1139+ if (entity -> iot .clock ) {
1140+ range = selector_find_range (dev , entity -> iot .clock ,
1141+ SDCA_CTL_CS_SAMPLERATEINDEX ,
1142+ SDCA_SAMPLERATEINDEX_NCOLS , 0 );
1143+ if (!range )
1144+ return - EINVAL ;
1145+
1146+ for (i = 0 ; i < range -> rows ; i ++ ) {
1147+ sample_rate = sdca_range (range , SDCA_SAMPLERATEINDEX_RATE , i );
1148+ clock_rates |= rate_find_mask (sample_rate );
1149+ }
1150+ } else {
1151+ clock_rates = UINT_MAX ;
1152+ }
1153+
1154+ range = selector_find_range (dev , entity , sel , SDCA_USAGE_NCOLS , 0 );
1155+ if (!range )
1156+ return - EINVAL ;
1157+
1158+ for (i = 0 ; i < range -> rows ; i ++ ) {
1159+ sample_rate = sdca_range (range , SDCA_USAGE_SAMPLE_RATE , i );
1160+ sample_rate = rate_find_mask (sample_rate );
1161+
1162+ if (sample_rate & clock_rates ) {
1163+ rates |= sample_rate ;
1164+
1165+ sample_width = sdca_range (range , SDCA_USAGE_SAMPLE_WIDTH , i );
1166+ formats |= width_find_mask (sample_width );
1167+ }
1168+ }
1169+
1170+ stream -> formats = formats ;
1171+ stream -> rates = rates ;
1172+
1173+ return 0 ;
1174+ }
1175+
1176+ /**
1177+ * sdca_asoc_populate_dais - fill in an array of DAI drivers for a Function
1178+ * @dev: Pointer to the device against which allocations will be done.
1179+ * @function: Pointer to the Function information.
1180+ * @dais: Array of DAI drivers to be populated.
1181+ * @ops: DAI ops to be attached to each of the created DAI drivers.
1182+ *
1183+ * This function populates an array of ASoC DAI drivers from the DisCo
1184+ * information for a particular SDCA Function. Typically,
1185+ * snd_soc_asoc_count_component will be used to allocate an
1186+ * appropriately sized array before calling this function.
1187+ *
1188+ * Return: Returns zero on success, and a negative error code on failure.
1189+ */
1190+ int sdca_asoc_populate_dais (struct device * dev , struct sdca_function_data * function ,
1191+ struct snd_soc_dai_driver * dais ,
1192+ const struct snd_soc_dai_ops * ops )
1193+ {
1194+ int i , j ;
1195+ int ret ;
1196+
1197+ for (i = 0 , j = 0 ; i < function -> num_entities - 1 ; i ++ ) {
1198+ struct sdca_entity * entity = & function -> entities [i ];
1199+ struct snd_soc_pcm_stream * stream ;
1200+ const char * stream_suffix ;
1201+
1202+ switch (entity -> type ) {
1203+ case SDCA_ENTITY_TYPE_IT :
1204+ stream = & dais [j ].playback ;
1205+ stream_suffix = "Playback" ;
1206+ break ;
1207+ case SDCA_ENTITY_TYPE_OT :
1208+ stream = & dais [j ].capture ;
1209+ stream_suffix = "Capture" ;
1210+ break ;
1211+ default :
1212+ continue ;
1213+ }
1214+
1215+ /* Can't check earlier as only terminals have an iot member. */
1216+ if (!entity -> iot .is_dataport )
1217+ continue ;
1218+
1219+ stream -> stream_name = devm_kasprintf (dev , GFP_KERNEL , "%s %s" ,
1220+ entity -> label , stream_suffix );
1221+ if (!stream -> stream_name )
1222+ return - ENOMEM ;
1223+ /* Channels will be further limited by constraints */
1224+ stream -> channels_min = 1 ;
1225+ stream -> channels_max = SDCA_MAX_CHANNEL_COUNT ;
1226+
1227+ ret = populate_rate_format (dev , function , entity , stream );
1228+ if (ret )
1229+ return ret ;
1230+
1231+ dais [j ].id = i ;
1232+ dais [j ].name = entity -> label ;
1233+ dais [j ].ops = ops ;
1234+ j ++ ;
1235+ }
1236+
1237+ return 0 ;
1238+ }
1239+ EXPORT_SYMBOL_NS (sdca_asoc_populate_dais , "SND_SOC_SDCA" );
1240+
10361241/**
10371242 * sdca_asoc_populate_component - fill in a component driver for a Function
10381243 * @dev: Pointer to the device against which allocations will be done.
@@ -1047,16 +1252,19 @@ EXPORT_SYMBOL_NS(sdca_asoc_populate_controls, "SND_SOC_SDCA");
10471252 */
10481253int sdca_asoc_populate_component (struct device * dev ,
10491254 struct sdca_function_data * function ,
1050- struct snd_soc_component_driver * component_drv )
1255+ struct snd_soc_component_driver * component_drv ,
1256+ struct snd_soc_dai_driver * * dai_drv , int * num_dai_drv ,
1257+ const struct snd_soc_dai_ops * ops )
10511258{
10521259 struct snd_soc_dapm_widget * widgets ;
10531260 struct snd_soc_dapm_route * routes ;
10541261 struct snd_kcontrol_new * controls ;
1055- int num_widgets , num_routes , num_controls ;
1262+ struct snd_soc_dai_driver * dais ;
1263+ int num_widgets , num_routes , num_controls , num_dais ;
10561264 int ret ;
10571265
10581266 ret = sdca_asoc_count_component (dev , function , & num_widgets , & num_routes ,
1059- & num_controls );
1267+ & num_controls , & num_dais );
10601268 if (ret )
10611269 return ret ;
10621270
@@ -1072,6 +1280,10 @@ int sdca_asoc_populate_component(struct device *dev,
10721280 if (!controls )
10731281 return - ENOMEM ;
10741282
1283+ dais = devm_kcalloc (dev , num_dais , sizeof (* dais ), GFP_KERNEL );
1284+ if (!dais )
1285+ return - ENOMEM ;
1286+
10751287 ret = sdca_asoc_populate_dapm (dev , function , widgets , routes );
10761288 if (ret )
10771289 return ret ;
@@ -1080,13 +1292,20 @@ int sdca_asoc_populate_component(struct device *dev,
10801292 if (ret )
10811293 return ret ;
10821294
1295+ ret = sdca_asoc_populate_dais (dev , function , dais , ops );
1296+ if (ret )
1297+ return ret ;
1298+
10831299 component_drv -> dapm_widgets = widgets ;
10841300 component_drv -> num_dapm_widgets = num_widgets ;
10851301 component_drv -> dapm_routes = routes ;
10861302 component_drv -> num_dapm_routes = num_routes ;
10871303 component_drv -> controls = controls ;
10881304 component_drv -> num_controls = num_controls ;
10891305
1306+ * dai_drv = dais ;
1307+ * num_dai_drv = num_dais ;
1308+
10901309 return 0 ;
10911310}
10921311EXPORT_SYMBOL_NS (sdca_asoc_populate_component , "SND_SOC_SDCA" );
0 commit comments