summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorAlexander Stein <alexander.stein@systec-electronic.com>2015-04-16 14:51:57 +0200
committerStefan Agner <stefan.agner@toradex.com>2017-05-30 13:49:04 -0700
commitae56e9df89155df49346526e7000004dec84ebef (patch)
treec18781b2b1c9c1deba2a9e33991360a079f71a77 /sound
parent3db63e28b0eb01d0801a9ee6ba3ae7bfa4a1bfd8 (diff)
ASoC: sgtl5000: Calculate Lineout Channel Output Level
Currently LO_VOL_* stays at it's default (0x4 each) but this should be calculated after setting VAG_VAL and LO_VAGCNTRL. LO_VOL_* = 40 * log10(VAG_VAL / LO_VAGCNTRL) + 15 To avoid the log10 operation a table for all valid register values is precalculated which contains the corresponding value (VAG_VAL * 100 / LO_VAGCNTRL). Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com> Signed-off-by: Mark Brown <broonie@kernel.org> (cherry picked from commit 1f39d9397f8a27becd2b72009865610a71c64b0f)
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/sgtl5000.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index bf239c883ae7..fa307fe4e15e 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1100,6 +1100,19 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg)
}
/*
+ * This precalculated table contains all (vag_val * 100 / lo_calcntrl) results
+ * to select an appropriate lo_vol_* in SGTL5000_CHIP_LINE_OUT_VOL
+ * The calculatation was done for all possible register values which
+ * is the array index and the following formula: 10^((idx−15)/40) * 100
+ */
+static const u8 vol_quot_table[] = {
+ 42, 45, 47, 50, 53, 56, 60, 63,
+ 67, 71, 75, 79, 84, 89, 94, 100,
+ 106, 112, 119, 126, 133, 141, 150, 158,
+ 168, 178, 188, 200, 211, 224, 237, 251
+};
+
+/*
* sgtl5000 has 3 internal power supplies:
* 1. VAG, normally set to vdda/2
* 2. charge pump, set to different value
@@ -1120,6 +1133,9 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
u16 lreg_ctrl;
int vag;
int lo_vag;
+ int vol_quot;
+ int lo_vol;
+ size_t i;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer);
@@ -1224,6 +1240,28 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
SGTL5000_LINE_OUT_CURRENT_360u <<
SGTL5000_LINE_OUT_CURRENT_SHIFT);
+ /*
+ * Set lineout output level in range (0..31)
+ * the same value is used for right and left channel
+ *
+ * Searching for a suitable index solving this formula:
+ * idx = 40 * log10(vag_val / lo_cagcntrl) + 15
+ */
+ vol_quot = (vag * 100) / lo_vag;
+ lo_vol = 0;
+ for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) {
+ if (vol_quot >= vol_quot_table[i])
+ lo_vol = i;
+ else
+ break;
+ }
+
+ snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_VOL,
+ SGTL5000_LINE_OUT_VOL_RIGHT_MASK |
+ SGTL5000_LINE_OUT_VOL_LEFT_MASK,
+ lo_vol << SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT |
+ lo_vol << SGTL5000_LINE_OUT_VOL_LEFT_SHIFT);
+
return 0;
}