213
213
214
214
/* TODO sun6i DAP (Digital Audio Processing) bits */
215
215
216
+ /* FIFO counters moved on A23 */
217
+ #define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
218
+ #define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
219
+
216
220
struct sun4i_codec {
217
221
struct device * dev ;
218
222
struct regmap * regmap ;
@@ -1067,6 +1071,32 @@ static struct snd_soc_codec_driver sun6i_codec_codec = {
1067
1071
},
1068
1072
};
1069
1073
1074
+ /* sun8i A23 codec */
1075
+ static const struct snd_kcontrol_new sun8i_a23_codec_codec_controls [] = {
1076
+ SOC_SINGLE_TLV ("DAC Playback Volume" , SUN4I_CODEC_DAC_DPC ,
1077
+ SUN4I_CODEC_DAC_DPC_DVOL , 0x3f , 1 ,
1078
+ sun6i_codec_dvol_scale ),
1079
+ };
1080
+
1081
+ static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets [] = {
1082
+ /* Digital parts of the ADCs */
1083
+ SND_SOC_DAPM_SUPPLY ("ADC Enable" , SUN6I_CODEC_ADC_FIFOC ,
1084
+ SUN6I_CODEC_ADC_FIFOC_EN_AD , 0 , NULL , 0 ),
1085
+ /* Digital parts of the DACs */
1086
+ SND_SOC_DAPM_SUPPLY ("DAC Enable" , SUN4I_CODEC_DAC_DPC ,
1087
+ SUN4I_CODEC_DAC_DPC_EN_DA , 0 , NULL , 0 ),
1088
+
1089
+ };
1090
+
1091
+ static struct snd_soc_codec_driver sun8i_a23_codec_codec = {
1092
+ .component_driver = {
1093
+ .controls = sun8i_a23_codec_codec_controls ,
1094
+ .num_controls = ARRAY_SIZE (sun8i_a23_codec_codec_controls ),
1095
+ .dapm_widgets = sun8i_a23_codec_codec_widgets ,
1096
+ .num_dapm_widgets = ARRAY_SIZE (sun8i_a23_codec_codec_widgets ),
1097
+ },
1098
+ };
1099
+
1070
1100
static const struct snd_soc_component_driver sun4i_codec_component = {
1071
1101
.name = "sun4i-codec" ,
1072
1102
};
@@ -1206,6 +1236,63 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
1206
1236
return card ;
1207
1237
};
1208
1238
1239
+ /* Connect digital side enables to analog side widgets */
1240
+ static const struct snd_soc_dapm_route sun8i_codec_card_routes [] = {
1241
+ /* ADC Routes */
1242
+ { "Left ADC" , NULL , "ADC Enable" },
1243
+ { "Right ADC" , NULL , "ADC Enable" },
1244
+ { "Codec Capture" , NULL , "Left ADC" },
1245
+ { "Codec Capture" , NULL , "Right ADC" },
1246
+
1247
+ /* DAC Routes */
1248
+ { "Left DAC" , NULL , "DAC Enable" },
1249
+ { "Right DAC" , NULL , "DAC Enable" },
1250
+ { "Left DAC" , NULL , "Codec Playback" },
1251
+ { "Right DAC" , NULL , "Codec Playback" },
1252
+ };
1253
+
1254
+ static struct snd_soc_aux_dev aux_dev = {
1255
+ .name = "Codec Analog Controls" ,
1256
+ };
1257
+
1258
+ static struct snd_soc_card * sun8i_a23_codec_create_card (struct device * dev )
1259
+ {
1260
+ struct snd_soc_card * card ;
1261
+ int ret ;
1262
+
1263
+ card = devm_kzalloc (dev , sizeof (* card ), GFP_KERNEL );
1264
+ if (!card )
1265
+ return ERR_PTR (- ENOMEM );
1266
+
1267
+ aux_dev .codec_of_node = of_parse_phandle (dev -> of_node ,
1268
+ "allwinner,codec-analog-controls" ,
1269
+ 0 );
1270
+ if (!aux_dev .codec_of_node ) {
1271
+ dev_err (dev , "Can't find analog controls for codec.\n" );
1272
+ return ERR_PTR (- EINVAL );
1273
+ };
1274
+
1275
+ card -> dai_link = sun4i_codec_create_link (dev , & card -> num_links );
1276
+ if (!card -> dai_link )
1277
+ return ERR_PTR (- ENOMEM );
1278
+
1279
+ card -> dev = dev ;
1280
+ card -> name = "A23 Audio Codec" ;
1281
+ card -> dapm_widgets = sun6i_codec_card_dapm_widgets ;
1282
+ card -> num_dapm_widgets = ARRAY_SIZE (sun6i_codec_card_dapm_widgets );
1283
+ card -> dapm_routes = sun8i_codec_card_routes ;
1284
+ card -> num_dapm_routes = ARRAY_SIZE (sun8i_codec_card_routes );
1285
+ card -> aux_dev = & aux_dev ;
1286
+ card -> num_aux_devs = 1 ;
1287
+ card -> fully_routed = true;
1288
+
1289
+ ret = snd_soc_of_parse_audio_routing (card , "allwinner,audio-routing" );
1290
+ if (ret )
1291
+ dev_warn (dev , "failed to parse audio-routing: %d\n" , ret );
1292
+
1293
+ return card ;
1294
+ };
1295
+
1209
1296
static const struct regmap_config sun4i_codec_regmap_config = {
1210
1297
.reg_bits = 32 ,
1211
1298
.reg_stride = 4 ,
@@ -1227,6 +1314,13 @@ static const struct regmap_config sun7i_codec_regmap_config = {
1227
1314
.max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL ,
1228
1315
};
1229
1316
1317
+ static const struct regmap_config sun8i_a23_codec_regmap_config = {
1318
+ .reg_bits = 32 ,
1319
+ .reg_stride = 4 ,
1320
+ .val_bits = 32 ,
1321
+ .max_register = SUN8I_A23_CODEC_ADC_RXCNT ,
1322
+ };
1323
+
1230
1324
struct sun4i_codec_quirks {
1231
1325
const struct regmap_config * regmap_config ;
1232
1326
const struct snd_soc_codec_driver * codec ;
@@ -1265,6 +1359,16 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
1265
1359
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA ,
1266
1360
};
1267
1361
1362
+ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
1363
+ .regmap_config = & sun8i_a23_codec_regmap_config ,
1364
+ .codec = & sun8i_a23_codec_codec ,
1365
+ .create_card = sun8i_a23_codec_create_card ,
1366
+ .reg_adc_fifoc = REG_FIELD (SUN6I_CODEC_ADC_FIFOC , 0 , 31 ),
1367
+ .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA ,
1368
+ .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA ,
1369
+ .has_reset = true,
1370
+ };
1371
+
1268
1372
static const struct of_device_id sun4i_codec_of_match [] = {
1269
1373
{
1270
1374
.compatible = "allwinner,sun4i-a10-codec" ,
@@ -1278,6 +1382,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
1278
1382
.compatible = "allwinner,sun7i-a20-codec" ,
1279
1383
.data = & sun7i_codec_quirks ,
1280
1384
},
1385
+ {
1386
+ .compatible = "allwinner,sun8i-a23-codec" ,
1387
+ .data = & sun8i_a23_codec_quirks ,
1388
+ },
1281
1389
{}
1282
1390
};
1283
1391
MODULE_DEVICE_TABLE (of , sun4i_codec_of_match );
0 commit comments