@@ -473,6 +473,19 @@ enum wsa_port_ids {
473
473
WSA883X_PORT_VISENSE ,
474
474
};
475
475
476
+ static const char * const wsa_dev_mode_text [] = {
477
+ "Speaker" , "Receiver" , "Ultrasound"
478
+ };
479
+
480
+ enum {
481
+ SPEAKER ,
482
+ RECEIVER ,
483
+ ULTRASOUND ,
484
+ };
485
+
486
+ static const struct soc_enum wsa_dev_mode_enum =
487
+ SOC_ENUM_SINGLE_EXT (ARRAY_SIZE (wsa_dev_mode_text ), wsa_dev_mode_text );
488
+
476
489
/* 4 ports */
477
490
static struct sdw_dpn_prop wsa_sink_dpn_prop [WSA883X_MAX_SWR_PORTS ] = {
478
491
{
@@ -1066,6 +1079,94 @@ static struct sdw_slave_ops wsa883x_slave_ops = {
1066
1079
.port_prep = wsa883x_port_prep ,
1067
1080
};
1068
1081
1082
+ static int wsa_dev_mode_get (struct snd_kcontrol * kcontrol ,
1083
+ struct snd_ctl_elem_value * ucontrol )
1084
+ {
1085
+ struct snd_soc_component * component = snd_soc_kcontrol_component (kcontrol );
1086
+ struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (component );
1087
+
1088
+ ucontrol -> value .enumerated .item [0 ] = wsa883x -> dev_mode ;
1089
+
1090
+ return 0 ;
1091
+ }
1092
+
1093
+ static int wsa_dev_mode_put (struct snd_kcontrol * kcontrol ,
1094
+ struct snd_ctl_elem_value * ucontrol )
1095
+ {
1096
+ struct snd_soc_component * component = snd_soc_kcontrol_component (kcontrol );
1097
+ struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (component );
1098
+
1099
+ if (wsa883x -> dev_mode == ucontrol -> value .enumerated .item [0 ])
1100
+ return 0 ;
1101
+
1102
+ wsa883x -> dev_mode = ucontrol -> value .enumerated .item [0 ];
1103
+
1104
+ return 1 ;
1105
+ }
1106
+
1107
+ static const DECLARE_TLV_DB_SCALE (pa_gain , -300 , 150 , -300 ) ;
1108
+
1109
+ static int wsa883x_get_swr_port (struct snd_kcontrol * kcontrol ,
1110
+ struct snd_ctl_elem_value * ucontrol )
1111
+ {
1112
+ struct snd_soc_component * comp = snd_soc_kcontrol_component (kcontrol );
1113
+ struct wsa883x_priv * data = snd_soc_component_get_drvdata (comp );
1114
+ struct soc_mixer_control * mixer = (struct soc_mixer_control * )kcontrol -> private_value ;
1115
+ int portidx = mixer -> reg ;
1116
+
1117
+ ucontrol -> value .integer .value [0 ] = data -> port_enable [portidx ];
1118
+
1119
+ return 0 ;
1120
+ }
1121
+
1122
+ static int wsa883x_set_swr_port (struct snd_kcontrol * kcontrol ,
1123
+ struct snd_ctl_elem_value * ucontrol )
1124
+ {
1125
+ struct snd_soc_component * comp = snd_soc_kcontrol_component (kcontrol );
1126
+ struct wsa883x_priv * data = snd_soc_component_get_drvdata (comp );
1127
+ struct soc_mixer_control * mixer = (struct soc_mixer_control * )kcontrol -> private_value ;
1128
+ int portidx = mixer -> reg ;
1129
+
1130
+ if (ucontrol -> value .integer .value [0 ]) {
1131
+ if (data -> port_enable [portidx ])
1132
+ return 0 ;
1133
+
1134
+ data -> port_enable [portidx ] = true;
1135
+ } else {
1136
+ if (!data -> port_enable [portidx ])
1137
+ return 0 ;
1138
+
1139
+ data -> port_enable [portidx ] = false;
1140
+ }
1141
+
1142
+ return 1 ;
1143
+ }
1144
+
1145
+ static int wsa883x_get_comp_offset (struct snd_kcontrol * kcontrol ,
1146
+ struct snd_ctl_elem_value * ucontrol )
1147
+ {
1148
+ struct snd_soc_component * component = snd_soc_kcontrol_component (kcontrol );
1149
+ struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (component );
1150
+
1151
+ ucontrol -> value .integer .value [0 ] = wsa883x -> comp_offset ;
1152
+
1153
+ return 0 ;
1154
+ }
1155
+
1156
+ static int wsa883x_set_comp_offset (struct snd_kcontrol * kcontrol ,
1157
+ struct snd_ctl_elem_value * ucontrol )
1158
+ {
1159
+ struct snd_soc_component * component = snd_soc_kcontrol_component (kcontrol );
1160
+ struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (component );
1161
+
1162
+ if (wsa883x -> comp_offset == ucontrol -> value .integer .value [0 ])
1163
+ return 0 ;
1164
+
1165
+ wsa883x -> comp_offset = ucontrol -> value .integer .value [0 ];
1166
+
1167
+ return 1 ;
1168
+ }
1169
+
1069
1170
static int wsa883x_codec_probe (struct snd_soc_component * comp )
1070
1171
{
1071
1172
struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (comp );
@@ -1075,9 +1176,108 @@ static int wsa883x_codec_probe(struct snd_soc_component *comp)
1075
1176
return 0 ;
1076
1177
}
1077
1178
1179
+ static int wsa883x_spkr_event (struct snd_soc_dapm_widget * w ,
1180
+ struct snd_kcontrol * kcontrol , int event )
1181
+ {
1182
+ struct snd_soc_component * component = snd_soc_dapm_to_component (w -> dapm );
1183
+ struct wsa883x_priv * wsa883x = snd_soc_component_get_drvdata (component );
1184
+
1185
+ switch (event ) {
1186
+ case SND_SOC_DAPM_POST_PMU :
1187
+ switch (wsa883x -> dev_mode ) {
1188
+ case RECEIVER :
1189
+ snd_soc_component_write_field (component , WSA883X_CDC_PATH_MODE ,
1190
+ WSA883X_RXD_MODE_MASK ,
1191
+ WSA883X_RXD_MODE_HIFI );
1192
+ snd_soc_component_write_field (component , WSA883X_SPKR_PWM_CLK_CTL ,
1193
+ WSA883X_SPKR_PWM_FREQ_SEL_MASK ,
1194
+ WSA883X_SPKR_PWM_FREQ_F600KHZ );
1195
+ snd_soc_component_write_field (component , WSA883X_DRE_CTL_0 ,
1196
+ WSA883X_DRE_PROG_DELAY_MASK , 0x0 );
1197
+ break ;
1198
+ case SPEAKER :
1199
+ snd_soc_component_write_field (component , WSA883X_CDC_PATH_MODE ,
1200
+ WSA883X_RXD_MODE_MASK ,
1201
+ WSA883X_RXD_MODE_NORMAL );
1202
+ snd_soc_component_write_field (component , WSA883X_SPKR_PWM_CLK_CTL ,
1203
+ WSA883X_SPKR_PWM_FREQ_SEL_MASK ,
1204
+ WSA883X_SPKR_PWM_FREQ_F300KHZ );
1205
+ snd_soc_component_write_field (component , WSA883X_DRE_CTL_0 ,
1206
+ WSA883X_DRE_PROG_DELAY_MASK , 0x9 );
1207
+ default :
1208
+ break ;
1209
+ }
1210
+
1211
+ snd_soc_component_write_field (component , WSA883X_DRE_CTL_1 ,
1212
+ WSA883X_DRE_GAIN_EN_MASK ,
1213
+ WSA883X_DRE_GAIN_FROM_CSR );
1214
+ if (wsa883x -> port_enable [WSA883X_PORT_COMP ])
1215
+ snd_soc_component_write_field (component , WSA883X_DRE_CTL_0 ,
1216
+ WSA883X_DRE_OFFSET_MASK ,
1217
+ wsa883x -> comp_offset );
1218
+ snd_soc_component_write_field (component , WSA883X_VBAT_ADC_FLT_CTL ,
1219
+ WSA883X_VBAT_ADC_COEF_SEL_MASK ,
1220
+ WSA883X_VBAT_ADC_COEF_F_1DIV16 );
1221
+ snd_soc_component_write_field (component , WSA883X_VBAT_ADC_FLT_CTL ,
1222
+ WSA883X_VBAT_ADC_FLT_EN_MASK , 0x1 );
1223
+ snd_soc_component_write_field (component , WSA883X_PDM_WD_CTL ,
1224
+ WSA883X_PDM_EN_MASK ,
1225
+ WSA883X_PDM_ENABLE );
1226
+ snd_soc_component_write_field (component , WSA883X_PA_FSM_CTL ,
1227
+ WSA883X_GLOBAL_PA_EN_MASK ,
1228
+ WSA883X_GLOBAL_PA_ENABLE );
1229
+
1230
+ break ;
1231
+ case SND_SOC_DAPM_PRE_PMD :
1232
+ snd_soc_component_write_field (component , WSA883X_VBAT_ADC_FLT_CTL ,
1233
+ WSA883X_VBAT_ADC_FLT_EN_MASK , 0x0 );
1234
+ snd_soc_component_write_field (component , WSA883X_VBAT_ADC_FLT_CTL ,
1235
+ WSA883X_VBAT_ADC_COEF_SEL_MASK ,
1236
+ WSA883X_VBAT_ADC_COEF_F_1DIV2 );
1237
+ snd_soc_component_write_field (component , WSA883X_PA_FSM_CTL ,
1238
+ WSA883X_GLOBAL_PA_EN_MASK , 0 );
1239
+ snd_soc_component_write_field (component , WSA883X_PDM_WD_CTL ,
1240
+ WSA883X_PDM_EN_MASK , 0 );
1241
+ break ;
1242
+ }
1243
+ return 0 ;
1244
+ }
1245
+
1246
+ static const struct snd_soc_dapm_widget wsa883x_dapm_widgets [] = {
1247
+ SND_SOC_DAPM_INPUT ("IN" ),
1248
+ SND_SOC_DAPM_SPK ("SPKR" , wsa883x_spkr_event ),
1249
+ };
1250
+
1251
+ static const struct snd_kcontrol_new wsa883x_snd_controls [] = {
1252
+ SOC_SINGLE_RANGE_TLV ("PA Volume" , WSA883X_DRE_CTL_1 , 1 ,
1253
+ 0x0 , 0x1f , 1 , pa_gain ),
1254
+ SOC_ENUM_EXT ("WSA MODE" , wsa_dev_mode_enum ,
1255
+ wsa_dev_mode_get , wsa_dev_mode_put ),
1256
+ SOC_SINGLE_EXT ("COMP Offset" , SND_SOC_NOPM , 0 , 4 , 0 ,
1257
+ wsa883x_get_comp_offset , wsa883x_set_comp_offset ),
1258
+ SOC_SINGLE_EXT ("DAC Switch" , WSA883X_PORT_DAC , 0 , 1 , 0 ,
1259
+ wsa883x_get_swr_port , wsa883x_set_swr_port ),
1260
+ SOC_SINGLE_EXT ("COMP Switch" , WSA883X_PORT_COMP , 0 , 1 , 0 ,
1261
+ wsa883x_get_swr_port , wsa883x_set_swr_port ),
1262
+ SOC_SINGLE_EXT ("BOOST Switch" , WSA883X_PORT_BOOST , 0 , 1 , 0 ,
1263
+ wsa883x_get_swr_port , wsa883x_set_swr_port ),
1264
+ SOC_SINGLE_EXT ("VISENSE Switch" , WSA883X_PORT_VISENSE , 0 , 1 , 0 ,
1265
+ wsa883x_get_swr_port , wsa883x_set_swr_port ),
1266
+ };
1267
+
1268
+ static const struct snd_soc_dapm_route wsa883x_audio_map [] = {
1269
+ {"SPKR" , NULL , "IN" },
1270
+ };
1271
+
1078
1272
static const struct snd_soc_component_driver wsa883x_component_drv = {
1079
1273
.name = "WSA883x" ,
1080
1274
.probe = wsa883x_codec_probe ,
1275
+ .controls = wsa883x_snd_controls ,
1276
+ .num_controls = ARRAY_SIZE (wsa883x_snd_controls ),
1277
+ .dapm_widgets = wsa883x_dapm_widgets ,
1278
+ .num_dapm_widgets = ARRAY_SIZE (wsa883x_dapm_widgets ),
1279
+ .dapm_routes = wsa883x_audio_map ,
1280
+ .num_dapm_routes = ARRAY_SIZE (wsa883x_audio_map ),
1081
1281
};
1082
1282
1083
1283
static int wsa883x_hw_params (struct snd_pcm_substream * substream ,
0 commit comments