aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2017-08-31 04:49:47 -0400
committerMark Brown <broonie@kernel.org>2017-08-31 05:24:01 -0400
commit19b0fa11bb1c0c24296c9f670a37c091bd3c815d (patch)
treec2168c918eb3192ab2c53a49d2885bb30023c325
parent5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff)
ASoC: tlv320aic3x: Support for OCMV configuration
In aic3x class of devices Output Common-Mode Voltage can be configured for better analog performance. The OCMV value depends on the Analog and digital domain power supply voltage configuration. The default OCMV of 1.35V gives best performance when AVDD is around 2.7V and DVDD is 1.525V, but for higher AVDD/DVDD higher OCMV setting is recommended. The patch gives an automatic way of guessing the best OCMV which can be overwritten by a DT parameter if needed. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic3x.txt5
-rw-r--r--sound/soc/codecs/tlv320aic3x.c45
-rw-r--r--sound/soc/codecs/tlv320aic3x.h8
3 files changed, 58 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index 47a213c411ce..ba5b45c483f5 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -26,6 +26,11 @@ Optional properties:
26 3 - MICBIAS output is connected to AVDD, 26 3 - MICBIAS output is connected to AVDD,
27 If this node is not mentioned or if the value is incorrect, then MicBias 27 If this node is not mentioned or if the value is incorrect, then MicBias
28 is powered down. 28 is powered down.
29- ai3x-ocmv - Output Common-Mode Voltage selection:
30 0 - 1.35V,
31 1 - 1.5V,
32 2 - 1.65V,
33 3 - 1.8V
29- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the 34- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
30 device as covered in Documentation/devicetree/bindings/regulator/regulator.txt 35 device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
31 36
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 29bf8c81ae02..ca880859f0c3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -93,6 +93,8 @@ struct aic3x_priv {
93 93
94 /* Selects the micbias voltage */ 94 /* Selects the micbias voltage */
95 enum aic3x_micbias_voltage micbias_vg; 95 enum aic3x_micbias_voltage micbias_vg;
96 /* Output Common-Mode Voltage */
97 u8 ocmv;
96}; 98};
97 99
98static const struct reg_default aic3x_reg[] = { 100static const struct reg_default aic3x_reg[] = {
@@ -1572,6 +1574,10 @@ static int aic3x_init(struct snd_soc_codec *codec)
1572 break; 1574 break;
1573 } 1575 }
1574 1576
1577 /* Output common-mode voltage = 1.5 V */
1578 snd_soc_update_bits(codec, HPOUT_SC, HPOUT_SC_OCMV_MASK,
1579 aic3x->ocmv << HPOUT_SC_OCMV_SHIFT);
1580
1575 return 0; 1581 return 0;
1576} 1582}
1577 1583
@@ -1699,6 +1705,43 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
1699 }, 1705 },
1700}; 1706};
1701 1707
1708static void aic3x_configure_ocmv(struct i2c_client *client)
1709{
1710 struct device_node *np = client->dev.of_node;
1711 struct aic3x_priv *aic3x = i2c_get_clientdata(client);
1712 u32 value;
1713 int dvdd, avdd;
1714
1715 if (np && !of_property_read_u32(np, "ai3x-ocmv", &value)) {
1716 /* OCMV setting is forced by DT */
1717 if (value <= 3) {
1718 aic3x->ocmv = value;
1719 return;
1720 }
1721 }
1722
1723 dvdd = regulator_get_voltage(aic3x->supplies[1].consumer);
1724 avdd = regulator_get_voltage(aic3x->supplies[2].consumer);
1725
1726 if (avdd > 3600000 || dvdd > 1950000) {
1727 dev_warn(&client->dev,
1728 "Too high supply voltage(s) AVDD: %d, DVDD: %d\n",
1729 avdd, dvdd);
1730 } else if (avdd == 3600000 && dvdd == 1950000) {
1731 aic3x->ocmv = HPOUT_SC_OCMV_1_8V;
1732 } else if (avdd > 3300000 && dvdd > 1800000) {
1733 aic3x->ocmv = HPOUT_SC_OCMV_1_65V;
1734 } else if (avdd > 3000000 && dvdd > 1650000) {
1735 aic3x->ocmv = HPOUT_SC_OCMV_1_5V;
1736 } else if (avdd >= 2700000 && dvdd >= 1525000) {
1737 aic3x->ocmv = HPOUT_SC_OCMV_1_35V;
1738 } else {
1739 dev_warn(&client->dev,
1740 "Invalid supply voltage(s) AVDD: %d, DVDD: %d\n",
1741 avdd, dvdd);
1742 }
1743}
1744
1702/* 1745/*
1703 * AIC3X 2 wire address can be up to 4 devices with device addresses 1746 * AIC3X 2 wire address can be up to 4 devices with device addresses
1704 * 0x18, 0x19, 0x1A, 0x1B 1747 * 0x18, 0x19, 0x1A, 0x1B
@@ -1816,6 +1859,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1816 goto err_gpio; 1859 goto err_gpio;
1817 } 1860 }
1818 1861
1862 aic3x_configure_ocmv(i2c);
1863
1819 if (aic3x->model == AIC3X_MODEL_3007) { 1864 if (aic3x->model == AIC3X_MODEL_3007) {
1820 ret = regmap_register_patch(aic3x->regmap, aic3007_class_d, 1865 ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
1821 ARRAY_SIZE(aic3007_class_d)); 1866 ARRAY_SIZE(aic3007_class_d));
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 89fa692df206..34c35196aa0d 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -243,6 +243,14 @@
243#define MICBIAS_LEVEL_SHIFT (6) 243#define MICBIAS_LEVEL_SHIFT (6)
244#define MICBIAS_LEVEL_MASK (3 << 6) 244#define MICBIAS_LEVEL_MASK (3 << 6)
245 245
246/* HPOUT_SC */
247#define HPOUT_SC_OCMV_MASK (3 << 6)
248#define HPOUT_SC_OCMV_SHIFT (6)
249#define HPOUT_SC_OCMV_1_35V 0
250#define HPOUT_SC_OCMV_1_5V 1
251#define HPOUT_SC_OCMV_1_65V 2
252#define HPOUT_SC_OCMV_1_8V 3
253
246/* headset detection / button API */ 254/* headset detection / button API */
247 255
248/* The AIC3x supports detection of stereo headsets (GND + left + right signal) 256/* The AIC3x supports detection of stereo headsets (GND + left + right signal)