22
22
#include <sound/sdca_function.h>
23
23
#include <sound/soc.h>
24
24
#include <sound/soc-component.h>
25
+ #include <sound/soc-dai.h>
25
26
#include <sound/soc-dapm.h>
26
27
#include <sound/tlv.h>
27
28
@@ -99,6 +100,8 @@ static bool readonly_control(struct sdca_control *control)
99
100
* required number of DAPM routes for the Function.
100
101
* @num_controls: Output integer pointer, will be filled with the
101
102
* 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.
102
105
*
103
106
* This function counts various things within the SDCA Function such
104
107
* that the calling driver can allocate appropriate space before
@@ -107,13 +110,15 @@ static bool readonly_control(struct sdca_control *control)
107
110
* Return: Returns zero on success, and a negative error code on failure.
108
111
*/
109
112
int 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 )
111
115
{
112
116
int i , j ;
113
117
114
118
* num_widgets = function -> num_entities - 1 ;
115
119
* num_routes = 0 ;
116
120
* num_controls = 0 ;
121
+ * num_dais = 0 ;
117
122
118
123
for (i = 0 ; i < function -> num_entities - 1 ; i ++ ) {
119
124
struct sdca_entity * entity = & function -> entities [i ];
@@ -125,6 +130,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
125
130
* num_routes += !!entity -> iot .clock ;
126
131
* num_routes += !!entity -> iot .is_dataport ;
127
132
* num_controls += !entity -> iot .is_dataport ;
133
+ * num_dais += !!entity -> iot .is_dataport ;
128
134
break ;
129
135
case SDCA_ENTITY_TYPE_PDE :
130
136
* num_routes += entity -> pde .num_managed ;
@@ -1033,6 +1039,205 @@ int sdca_asoc_populate_controls(struct device *dev,
1033
1039
}
1034
1040
EXPORT_SYMBOL_NS (sdca_asoc_populate_controls , "SND_SOC_SDCA" );
1035
1041
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
+
1036
1241
/**
1037
1242
* sdca_asoc_populate_component - fill in a component driver for a Function
1038
1243
* @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");
1047
1252
*/
1048
1253
int sdca_asoc_populate_component (struct device * dev ,
1049
1254
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 )
1051
1258
{
1052
1259
struct snd_soc_dapm_widget * widgets ;
1053
1260
struct snd_soc_dapm_route * routes ;
1054
1261
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 ;
1056
1264
int ret ;
1057
1265
1058
1266
ret = sdca_asoc_count_component (dev , function , & num_widgets , & num_routes ,
1059
- & num_controls );
1267
+ & num_controls , & num_dais );
1060
1268
if (ret )
1061
1269
return ret ;
1062
1270
@@ -1072,6 +1280,10 @@ int sdca_asoc_populate_component(struct device *dev,
1072
1280
if (!controls )
1073
1281
return - ENOMEM ;
1074
1282
1283
+ dais = devm_kcalloc (dev , num_dais , sizeof (* dais ), GFP_KERNEL );
1284
+ if (!dais )
1285
+ return - ENOMEM ;
1286
+
1075
1287
ret = sdca_asoc_populate_dapm (dev , function , widgets , routes );
1076
1288
if (ret )
1077
1289
return ret ;
@@ -1080,13 +1292,20 @@ int sdca_asoc_populate_component(struct device *dev,
1080
1292
if (ret )
1081
1293
return ret ;
1082
1294
1295
+ ret = sdca_asoc_populate_dais (dev , function , dais , ops );
1296
+ if (ret )
1297
+ return ret ;
1298
+
1083
1299
component_drv -> dapm_widgets = widgets ;
1084
1300
component_drv -> num_dapm_widgets = num_widgets ;
1085
1301
component_drv -> dapm_routes = routes ;
1086
1302
component_drv -> num_dapm_routes = num_routes ;
1087
1303
component_drv -> controls = controls ;
1088
1304
component_drv -> num_controls = num_controls ;
1089
1305
1306
+ * dai_drv = dais ;
1307
+ * num_dai_drv = num_dais ;
1308
+
1090
1309
return 0 ;
1091
1310
}
1092
1311
EXPORT_SYMBOL_NS (sdca_asoc_populate_component , "SND_SOC_SDCA" );
0 commit comments