summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 29bf8c81ae02..06f92571eba4 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -93,6 +93,8 @@ struct aic3x_priv {
/* Selects the micbias voltage */
enum aic3x_micbias_voltage micbias_vg;
+ /* Output Common-Mode Voltage */
+ u8 ocmv;
};
static const struct reg_default aic3x_reg[] = {
@@ -1572,6 +1574,10 @@ static int aic3x_init(struct snd_soc_codec *codec)
break;
}
+ /* Output common-mode voltage = 1.5 V */
+ snd_soc_update_bits(codec, HPOUT_SC, HPOUT_SC_OCMV_MASK,
+ aic3x->ocmv << HPOUT_SC_OCMV_SHIFT);
+
return 0;
}
@@ -1684,7 +1690,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
+static const struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
.idle_bias_off = true,
.probe = aic3x_probe,
@@ -1699,6 +1705,43 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
},
};
+static void aic3x_configure_ocmv(struct i2c_client *client)
+{
+ struct device_node *np = client->dev.of_node;
+ struct aic3x_priv *aic3x = i2c_get_clientdata(client);
+ u32 value;
+ int dvdd, avdd;
+
+ if (np && !of_property_read_u32(np, "ai3x-ocmv", &value)) {
+ /* OCMV setting is forced by DT */
+ if (value <= 3) {
+ aic3x->ocmv = value;
+ return;
+ }
+ }
+
+ dvdd = regulator_get_voltage(aic3x->supplies[1].consumer);
+ avdd = regulator_get_voltage(aic3x->supplies[2].consumer);
+
+ if (avdd > 3600000 || dvdd > 1950000) {
+ dev_warn(&client->dev,
+ "Too high supply voltage(s) AVDD: %d, DVDD: %d\n",
+ avdd, dvdd);
+ } else if (avdd == 3600000 && dvdd == 1950000) {
+ aic3x->ocmv = HPOUT_SC_OCMV_1_8V;
+ } else if (avdd > 3300000 && dvdd > 1800000) {
+ aic3x->ocmv = HPOUT_SC_OCMV_1_65V;
+ } else if (avdd > 3000000 && dvdd > 1650000) {
+ aic3x->ocmv = HPOUT_SC_OCMV_1_5V;
+ } else if (avdd >= 2700000 && dvdd >= 1525000) {
+ aic3x->ocmv = HPOUT_SC_OCMV_1_35V;
+ } else {
+ dev_warn(&client->dev,
+ "Invalid supply voltage(s) AVDD: %d, DVDD: %d\n",
+ avdd, dvdd);
+ }
+}
+
/*
* AIC3X 2 wire address can be up to 4 devices with device addresses
* 0x18, 0x19, 0x1A, 0x1B
@@ -1816,6 +1859,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
goto err_gpio;
}
+ aic3x_configure_ocmv(i2c);
+
if (aic3x->model == AIC3X_MODEL_3007) {
ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
ARRAY_SIZE(aic3007_class_d));