aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/sgtl5000.c
diff options
context:
space:
mode:
authorAlexander Stein <alexander.stein@systec-electronic.com>2015-04-16 08:51:57 -0400
committerMark Brown <broonie@kernel.org>2015-04-27 10:42:20 -0400
commit1f39d9397f8a27becd2b72009865610a71c64b0f (patch)
treedd736e870b699c31af2a2ce4a4e7f499dd070785 /sound/soc/codecs/sgtl5000.c
parentd2b7c2aaf7b565532c7d9937519b199fbca4a779 (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>
Diffstat (limited to 'sound/soc/codecs/sgtl5000.c')
-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 bab2b5e5b312..1b883437dcbe 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1092,6 +1092,19 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg)
1092} 1092}
1093 1093
1094/* 1094/*
1095 * This precalculated table contains all (vag_val * 100 / lo_calcntrl) results
1096 * to select an appropriate lo_vol_* in SGTL5000_CHIP_LINE_OUT_VOL
1097 * The calculatation was done for all possible register values which
1098 * is the array index and the following formula: 10^((idx−15)/40) * 100
1099 */
1100static const u8 vol_quot_table[] = {
1101 42, 45, 47, 50, 53, 56, 60, 63,
1102 67, 71, 75, 79, 84, 89, 94, 100,
1103 106, 112, 119, 126, 133, 141, 150, 158,
1104 168, 178, 188, 200, 211, 224, 237, 251
1105};
1106
1107/*
1095 * sgtl5000 has 3 internal power supplies: 1108 * sgtl5000 has 3 internal power supplies:
1096 * 1. VAG, normally set to vdda/2 1109 * 1. VAG, normally set to vdda/2
1097 * 2. charge pump, set to different value 1110 * 2. charge pump, set to different value
@@ -1112,6 +1125,9 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
1112 u16 lreg_ctrl; 1125 u16 lreg_ctrl;
1113 int vag; 1126 int vag;
1114 int lo_vag; 1127 int lo_vag;
1128 int vol_quot;
1129 int lo_vol;
1130 size_t i;
1115 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); 1131 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
1116 1132
1117 vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); 1133 vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer);
@@ -1216,6 +1232,28 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
1216 SGTL5000_LINE_OUT_CURRENT_360u << 1232 SGTL5000_LINE_OUT_CURRENT_360u <<
1217 SGTL5000_LINE_OUT_CURRENT_SHIFT); 1233 SGTL5000_LINE_OUT_CURRENT_SHIFT);
1218 1234
1235 /*
1236 * Set lineout output level in range (0..31)
1237 * the same value is used for right and left channel
1238 *
1239 * Searching for a suitable index solving this formula:
1240 * idx = 40 * log10(vag_val / lo_cagcntrl) + 15
1241 */
1242 vol_quot = (vag * 100) / lo_vag;
1243 lo_vol = 0;
1244 for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) {
1245 if (vol_quot >= vol_quot_table[i])
1246 lo_vol = i;
1247 else
1248 break;
1249 }
1250
1251 snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_VOL,
1252 SGTL5000_LINE_OUT_VOL_RIGHT_MASK |
1253 SGTL5000_LINE_OUT_VOL_LEFT_MASK,
1254 lo_vol << SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT |
1255 lo_vol << SGTL5000_LINE_OUT_VOL_LEFT_SHIFT);
1256
1219 return 0; 1257 return 0;
1220} 1258}
1221 1259