Commit e48fdb53 authored by Lucas Stach's avatar Lucas Stach Committed by Mark Brown

ASoC: tlv320aic31xx: configure output common-mode voltage

The tlv320aic31xx devices allow to adjust the output common-mode voltage
for best analog performance. The datasheet states that the common mode
voltage should be set to be <= AVDD/2.

This changes allows to configure the output common-mode voltage via a DT
property. If the property is absent the voltage is automatically chosen
as the highest voltage below/equal to AVDD/2.
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
Link: https://lore.kernel.org/r/20191118151207.28576-1-l.stach@pengutronix.deSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 653c28af
...@@ -29,6 +29,11 @@ Optional properties: ...@@ -29,6 +29,11 @@ Optional properties:
3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
If this node is not mentioned or if the value is unknown, then If this node is not mentioned or if the value is unknown, then
micbias is set to 2.0V. micbias is set to 2.0V.
- ai31xx-ocmv - output common-mode voltage setting
0 - 1.35V,
1 - 1.5V,
2 - 1.65V,
3 - 1.8V
Deprecated properties: Deprecated properties:
......
...@@ -171,6 +171,7 @@ struct aic31xx_priv { ...@@ -171,6 +171,7 @@ struct aic31xx_priv {
int rate_div_line; int rate_div_line;
bool master_dapm_route_applied; bool master_dapm_route_applied;
int irq; int irq;
u8 ocmv; /* output common-mode voltage */
}; };
struct aic31xx_rate_divs { struct aic31xx_rate_divs {
...@@ -1312,6 +1313,11 @@ static int aic31xx_codec_probe(struct snd_soc_component *component) ...@@ -1312,6 +1313,11 @@ static int aic31xx_codec_probe(struct snd_soc_component *component)
if (ret) if (ret)
return ret; return ret;
/* set output common-mode voltage */
snd_soc_component_update_bits(component, AIC31XX_HPDRIVER,
AIC31XX_HPD_OCMV_MASK,
aic31xx->ocmv << AIC31XX_HPD_OCMV_SHIFT);
return 0; return 0;
} }
...@@ -1501,6 +1507,43 @@ static irqreturn_t aic31xx_irq(int irq, void *data) ...@@ -1501,6 +1507,43 @@ static irqreturn_t aic31xx_irq(int irq, void *data)
return IRQ_NONE; return IRQ_NONE;
} }
static void aic31xx_configure_ocmv(struct aic31xx_priv *priv)
{
struct device *dev = priv->dev;
int dvdd, avdd;
u32 value;
if (dev->fwnode &&
fwnode_property_read_u32(dev->fwnode, "ai31xx-ocmv", &value)) {
/* OCMV setting is forced by DT */
if (value <= 3) {
priv->ocmv = value;
return;
}
}
avdd = regulator_get_voltage(priv->supplies[3].consumer);
dvdd = regulator_get_voltage(priv->supplies[5].consumer);
if (avdd > 3600000 || dvdd > 1950000) {
dev_warn(dev,
"Too high supply voltage(s) AVDD: %d, DVDD: %d\n",
avdd, dvdd);
} else if (avdd == 3600000 && dvdd == 1950000) {
priv->ocmv = AIC31XX_HPD_OCMV_1_8V;
} else if (avdd >= 3300000 && dvdd >= 1800000) {
priv->ocmv = AIC31XX_HPD_OCMV_1_65V;
} else if (avdd >= 3000000 && dvdd >= 1650000) {
priv->ocmv = AIC31XX_HPD_OCMV_1_5V;
} else if (avdd >= 2700000 && dvdd >= 1525000) {
priv->ocmv = AIC31XX_HPD_OCMV_1_35V;
} else {
dev_warn(dev,
"Invalid supply voltage(s) AVDD: %d, DVDD: %d\n",
avdd, dvdd);
}
}
static int aic31xx_i2c_probe(struct i2c_client *i2c, static int aic31xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -1570,6 +1613,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, ...@@ -1570,6 +1613,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
aic31xx_configure_ocmv(aic31xx);
if (aic31xx->irq > 0) { if (aic31xx->irq > 0) {
regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1, regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1,
AIC31XX_GPIO1_FUNC_MASK, AIC31XX_GPIO1_FUNC_MASK,
......
...@@ -232,6 +232,14 @@ struct aic31xx_pdata { ...@@ -232,6 +232,14 @@ struct aic31xx_pdata {
#define AIC31XX_HSD_HP 0x01 #define AIC31XX_HSD_HP 0x01
#define AIC31XX_HSD_HS 0x03 #define AIC31XX_HSD_HS 0x03
/* AIC31XX_HPDRIVER */
#define AIC31XX_HPD_OCMV_MASK GENMASK(4, 3)
#define AIC31XX_HPD_OCMV_SHIFT 3
#define AIC31XX_HPD_OCMV_1_35V 0x0
#define AIC31XX_HPD_OCMV_1_5V 0x1
#define AIC31XX_HPD_OCMV_1_65V 0x2
#define AIC31XX_HPD_OCMV_1_8V 0x3
/* AIC31XX_MICBIAS */ /* AIC31XX_MICBIAS */
#define AIC31XX_MICBIAS_MASK GENMASK(1, 0) #define AIC31XX_MICBIAS_MASK GENMASK(1, 0)
#define AIC31XX_MICBIAS_SHIFT 0 #define AIC31XX_MICBIAS_SHIFT 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment