Commit 1f39d939 authored by Alexander Stein's avatar Alexander Stein Committed by Mark Brown

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: default avatarAlexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d2b7c2aa
......@@ -1091,6 +1091,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
......@@ -1112,6 +1125,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);
......@@ -1216,6 +1232,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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment