Skip to content

Commit

Permalink
ASoC: sgtl5000: Calculate Lineout Channel Output Level
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Stein authored and Mark Brown committed Apr 27, 2015
1 parent d2b7c2a commit 1f39d93
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions sound/soc/codecs/sgtl5000.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 1f39d93

Please sign in to comment.