Skip to content

Commit dac5f86

Browse files
wensbroonie
authored andcommitted
ASoC: sun4i-codec: Add support for A23 codec
The codec in the A23 is similar to the one found on the A31. One key difference is the analog path controls are routed through the PRCM block. This is supported by the sun8i-codec-analog driver, and tied into this codec driver with the audio card's aux_dev. In addition, the A23 does not have LINEOUT, and it does not support headset jack detection or buttons. Signed-off-by: Chen-Yu Tsai <[email protected]> Acked-by: Rob Herring <[email protected]> Acked-by: Maxime Ripard <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 999982e commit dac5f86

File tree

2 files changed

+117
-2
lines changed

2 files changed

+117
-2
lines changed

Documentation/devicetree/bindings/sound/sun4i-codec.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Required properties:
55
- "allwinner,sun4i-a10-codec"
66
- "allwinner,sun6i-a31-codec"
77
- "allwinner,sun7i-a20-codec"
8+
- "allwinner,sun8i-a23-codec"
89
- reg: must contain the registers location and length
910
- interrupts: must contain the codec interrupt
1011
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -21,6 +22,7 @@ Optional properties:
2122

2223
Required properties for the following compatibles:
2324
- "allwinner,sun6i-a31-codec"
25+
- "allwinner,sun8i-a23-codec"
2426
- resets: phandle to the reset control for this device
2527
- allwinner,audio-routing: A list of the connections between audio components.
2628
Each entry is a pair of strings, the first being the
@@ -31,10 +33,10 @@ Required properties for the following compatibles:
3133
"HP"
3234
"HPCOM"
3335
"LINEIN"
34-
"LINEOUT"
36+
"LINEOUT" (not on sun8i-a23)
3537
"MIC1"
3638
"MIC2"
37-
"MIC3"
39+
"MIC3" (sun6i-a31 only)
3840

3941
Microphone biases from the SoC:
4042
"HBIAS"
@@ -48,6 +50,11 @@ Required properties for the following compatibles:
4850
"Mic"
4951
"Speaker"
5052

53+
Required properties for the following compatibles:
54+
- "allwinner,sun8i-a23-codec"
55+
- allwinner,codec-analog-controls: A phandle to the codec analog controls
56+
block in the PRCM.
57+
5158
Example:
5259
codec: codec@01c22c00 {
5360
#sound-dai-cells = <0>;

sound/soc/sunxi/sun4i-codec.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@
213213

214214
/* TODO sun6i DAP (Digital Audio Processing) bits */
215215

216+
/* FIFO counters moved on A23 */
217+
#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
218+
#define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
219+
216220
struct sun4i_codec {
217221
struct device *dev;
218222
struct regmap *regmap;
@@ -1067,6 +1071,32 @@ static struct snd_soc_codec_driver sun6i_codec_codec = {
10671071
},
10681072
};
10691073

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+
10701100
static const struct snd_soc_component_driver sun4i_codec_component = {
10711101
.name = "sun4i-codec",
10721102
};
@@ -1206,6 +1236,63 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
12061236
return card;
12071237
};
12081238

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+
12091296
static const struct regmap_config sun4i_codec_regmap_config = {
12101297
.reg_bits = 32,
12111298
.reg_stride = 4,
@@ -1227,6 +1314,13 @@ static const struct regmap_config sun7i_codec_regmap_config = {
12271314
.max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
12281315
};
12291316

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+
12301324
struct sun4i_codec_quirks {
12311325
const struct regmap_config *regmap_config;
12321326
const struct snd_soc_codec_driver *codec;
@@ -1265,6 +1359,16 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
12651359
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
12661360
};
12671361

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+
12681372
static const struct of_device_id sun4i_codec_of_match[] = {
12691373
{
12701374
.compatible = "allwinner,sun4i-a10-codec",
@@ -1278,6 +1382,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
12781382
.compatible = "allwinner,sun7i-a20-codec",
12791383
.data = &sun7i_codec_quirks,
12801384
},
1385+
{
1386+
.compatible = "allwinner,sun8i-a23-codec",
1387+
.data = &sun8i_a23_codec_quirks,
1388+
},
12811389
{}
12821390
};
12831391
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);

0 commit comments

Comments
 (0)