forked from luck/tmp_suning_uos_patched
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: Lucas Stach <l.stach@pengutronix.de> Link: https://lore.kernel.org/r/20191118151207.28576-1-l.stach@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
653c28afa7
commit
e48fdb53bd
|
@ -29,6 +29,11 @@ Optional properties:
|
|||
3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
|
||||
If this node is not mentioned or if the value is unknown, then
|
||||
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:
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ struct aic31xx_priv {
|
|||
int rate_div_line;
|
||||
bool master_dapm_route_applied;
|
||||
int irq;
|
||||
u8 ocmv; /* output common-mode voltage */
|
||||
};
|
||||
|
||||
struct aic31xx_rate_divs {
|
||||
|
@ -1312,6 +1313,11 @@ static int aic31xx_codec_probe(struct snd_soc_component *component)
|
|||
if (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;
|
||||
}
|
||||
|
||||
|
@ -1501,6 +1507,43 @@ static irqreturn_t aic31xx_irq(int irq, void *data)
|
|||
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,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -1570,6 +1613,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
aic31xx_configure_ocmv(aic31xx);
|
||||
|
||||
if (aic31xx->irq > 0) {
|
||||
regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1,
|
||||
AIC31XX_GPIO1_FUNC_MASK,
|
||||
|
|
|
@ -232,6 +232,14 @@ struct aic31xx_pdata {
|
|||
#define AIC31XX_HSD_HP 0x01
|
||||
#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 */
|
||||
#define AIC31XX_MICBIAS_MASK GENMASK(1, 0)
|
||||
#define AIC31XX_MICBIAS_SHIFT 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user