ASoC: sun4i-codec: Add support for H3 codec

The codec on the H3 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 H3 has no HP (headphone) and HBIAS support, and no
MIC3 input. The FIFO related registers are slightly rearranged.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Chen-Yu Tsai 2016-11-25 20:34:40 +08:00 committed by Mark Brown
parent dac5f86bc9
commit 4a15b24a65
2 changed files with 74 additions and 0 deletions

View File

@ -6,6 +6,7 @@ Required properties:
- "allwinner,sun6i-a31-codec" - "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec" - "allwinner,sun7i-a20-codec"
- "allwinner,sun8i-a23-codec" - "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- reg: must contain the registers location and length - reg: must contain the registers location and length
- interrupts: must contain the codec interrupt - interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding, - dmas: DMA channels for tx and rx dma. See the DMA client binding,
@ -23,6 +24,7 @@ Optional properties:
Required properties for the following compatibles: Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec" - "allwinner,sun6i-a31-codec"
- "allwinner,sun8i-a23-codec" - "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- resets: phandle to the reset control for this device - resets: phandle to the reset control for this device
- allwinner,audio-routing: A list of the connections between audio components. - allwinner,audio-routing: A list of the connections between audio components.
Each entry is a pair of strings, the first being the Each entry is a pair of strings, the first being the
@ -52,6 +54,7 @@ Required properties for the following compatibles:
Required properties for the following compatibles: Required properties for the following compatibles:
- "allwinner,sun8i-a23-codec" - "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- allwinner,codec-analog-controls: A phandle to the codec analog controls - allwinner,codec-analog-controls: A phandle to the codec analog controls
block in the PRCM. block in the PRCM.

View File

@ -217,6 +217,13 @@
#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c) #define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
#define SUN8I_A23_CODEC_ADC_RXCNT (0x20) #define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
/* TX FIFO moved on H3 */
#define SUN8I_H3_CODEC_DAC_TXDATA (0x20)
#define SUN8I_H3_CODEC_DAC_DBG (0x48)
#define SUN8I_H3_CODEC_ADC_DBG (0x4c)
/* TODO H3 DAP (Digital Audio Processing) bits */
struct sun4i_codec { struct sun4i_codec {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
@ -1293,6 +1300,44 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
return card; return card;
}; };
static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
{
struct snd_soc_card *card;
int ret;
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
if (!card)
return ERR_PTR(-ENOMEM);
aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
"allwinner,codec-analog-controls",
0);
if (!aux_dev.codec_of_node) {
dev_err(dev, "Can't find analog controls for codec.\n");
return ERR_PTR(-EINVAL);
};
card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
if (!card->dai_link)
return ERR_PTR(-ENOMEM);
card->dev = dev;
card->name = "H3 Audio Codec";
card->dapm_widgets = sun6i_codec_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
card->dapm_routes = sun8i_codec_card_routes;
card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
card->aux_dev = &aux_dev;
card->num_aux_devs = 1;
card->fully_routed = true;
ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
if (ret)
dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
return card;
};
static const struct regmap_config sun4i_codec_regmap_config = { static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.reg_stride = 4, .reg_stride = 4,
@ -1321,6 +1366,13 @@ static const struct regmap_config sun8i_a23_codec_regmap_config = {
.max_register = SUN8I_A23_CODEC_ADC_RXCNT, .max_register = SUN8I_A23_CODEC_ADC_RXCNT,
}; };
static const struct regmap_config sun8i_h3_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = SUN8I_H3_CODEC_ADC_DBG,
};
struct sun4i_codec_quirks { struct sun4i_codec_quirks {
const struct regmap_config *regmap_config; const struct regmap_config *regmap_config;
const struct snd_soc_codec_driver *codec; const struct snd_soc_codec_driver *codec;
@ -1369,6 +1421,21 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
.has_reset = true, .has_reset = true,
}; };
static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
.regmap_config = &sun8i_h3_codec_regmap_config,
/*
* TODO Share the codec structure with A23 for now.
* This should be split out when adding digital audio
* processing support for the H3.
*/
.codec = &sun8i_a23_codec_codec,
.create_card = sun8i_h3_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
.reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
.has_reset = true,
};
static const struct of_device_id sun4i_codec_of_match[] = { static const struct of_device_id sun4i_codec_of_match[] = {
{ {
.compatible = "allwinner,sun4i-a10-codec", .compatible = "allwinner,sun4i-a10-codec",
@ -1386,6 +1453,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun8i-a23-codec", .compatible = "allwinner,sun8i-a23-codec",
.data = &sun8i_a23_codec_quirks, .data = &sun8i_a23_codec_quirks,
}, },
{
.compatible = "allwinner,sun8i-h3-codec",
.data = &sun8i_h3_codec_quirks,
},
{} {}
}; };
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);