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>
This commit is contained in:
parent
d2b7c2aaf7
commit
1f39d9397f
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue