diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-10-21 12:08:42 -0700 |
---|---|---|
committer | Arve Hjønnevåg <arve@android.com> | 2011-11-17 17:51:26 -0800 |
commit | c54363c80b2b84a92bb1954017c2177df1343d06 (patch) | |
tree | 834c5c5cd007503890de85ecf8d6fd0bb1c8fa04 | |
parent | f285e2c3263b94563bde469328e7915929d62b73 (diff) | |
download | kernel_samsung_crespo-c54363c80b2b84a92bb1954017c2177df1343d06.zip kernel_samsung_crespo-c54363c80b2b84a92bb1954017c2177df1343d06.tar.gz kernel_samsung_crespo-c54363c80b2b84a92bb1954017c2177df1343d06.tar.bz2 |
ASoC: Save and restore DC servo state when unchanged
We only need to recalibrate the DC servo configuration when the analogue
configuration is changed, which in this system means whenver the analogue
volume is changed or whenever the path is changed. Use this to save the
~160ms taken by the recalibration by saving the value per-path
We still need to recalibrate after volume changes and the first time a given
path is used but these should be much less frequent events than headphone
enable.
Change-Id: I706fe161f5cc0709e58d7702b28796ed85c51384
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | sound/soc/codecs/wm8994_herring.c | 75 | ||||
-rwxr-xr-x | sound/soc/codecs/wm8994_samsung.c | 7 | ||||
-rwxr-xr-x | sound/soc/codecs/wm8994_samsung.h | 7 |
3 files changed, 64 insertions, 25 deletions
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c index e9ee4c4..f8c3d9a 100644 --- a/sound/soc/codecs/wm8994_herring.c +++ b/sound/soc/codecs/wm8994_herring.c @@ -1404,18 +1404,25 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec) WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA); wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); - wait_for_dc_servo(codec, - WM8994_DCS_TRIG_SERIES_0 | WM8994_DCS_TRIG_SERIES_1); + if (!wm8994->dc_servo[DCS_MEDIA]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); - testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); - testlow = (signed char)(testreturn1 & 0xff); - testhigh = (signed char)((testreturn1>>8) & 0xff); + testlow1 = ((signed short)(testlow-5)) & 0x00ff; + testhigh1 = (((signed short)(testhigh-5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_MEDIA]; + } - testlow1 = ((signed short)(testlow-5)) & 0x00ff; - testhigh1 = (((signed short)(testhigh-5)<<8) & 0xff00); - testreturn2 = testlow1|testhigh1; wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + wm8994->dc_servo[DCS_MEDIA] = testreturn2; wait_for_dc_servo(codec, WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); @@ -1691,17 +1698,27 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec) wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); /* DC Servo */ - wait_for_dc_servo(codec, - WM8994_DCS_TRIG_SERIES_0 | WM8994_DCS_TRIG_SERIES_1); - - nreadservo4val = wm8994_read(codec, WM8994_DC_SERVO_4); - nservo4low = (signed char)(nreadservo4val & 0xff); - nservo4high = (signed char)((nreadservo4val>>8) & 0xff); + if (!wm8994->dc_servo[DCS_SPK_HP]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + nreadservo4val = wm8994_read(codec, WM8994_DC_SERVO_4); + nservo4low = (signed char)(nreadservo4val & 0xff); + nservo4high = (signed char)((nreadservo4val>>8) & 0xff); + + ncompensationresultlow = ((signed short)nservo4low - 5) + & 0x00ff; + ncompensationresulthigh = ((signed short)(nservo4high - 5)<<8) + & 0xff00; + ncompensationresult = ncompensationresultlow | + ncompensationresulthigh; + } else { + ncompensationresult = wm8994->dc_servo[DCS_SPK_HP]; + } - ncompensationresultlow = ((signed short)nservo4low - 5) & 0x00ff; - ncompensationresulthigh = ((signed short)(nservo4high - 5)<<8) & 0xff00; - ncompensationresult = ncompensationresultlow|ncompensationresulthigh; wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationresult); + wm8994->dc_servo[DCS_SPK_HP] = ncompensationresult; wait_for_dc_servo(codec, WM8994_DCS_TRIG_DAC_WR_1 | WM8994_DCS_TRIG_DAC_WR_0 | @@ -2088,22 +2105,30 @@ void wm8994_set_voicecall_headset(struct snd_soc_codec *codec) wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); - wait_for_dc_servo(codec, - WM8994_DCS_TRIG_SERIES_0 | WM8994_DCS_TRIG_SERIES_1); + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); - testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); - testlow = (signed char)(testreturn1 & 0xff); - testhigh = (signed char)((testreturn1>>8) & 0xff); + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } - testlow1 = ((signed short)testlow - 5) & 0x00ff; - testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); - testreturn2 = testlow1|testhigh1; wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); wait_for_dc_servo(codec, WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + wm8994->dc_servo[DCS_VOICE] = testreturn2; + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_HP); diff --git a/sound/soc/codecs/wm8994_samsung.c b/sound/soc/codecs/wm8994_samsung.c index adfb009..e48348d 100755 --- a/sound/soc/codecs/wm8994_samsung.c +++ b/sound/soc/codecs/wm8994_samsung.c @@ -228,6 +228,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int reg = mc->reg; + struct wm8994_priv *wm8994 = codec->drvdata; DEBUG_LOG(""); @@ -235,6 +236,12 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, if (ret < 0) return ret; + /* Volume changes in the headphone path mean we need to + * recallibrate DC servo */ + if (strcmp(kcontrol->id.name, "Playback Spkr Volume") == 0 || + strcmp(kcontrol->id.name, "Playback Volume") == 0) + memset(wm8994->dc_servo, 0, sizeof(wm8994->dc_servo)); + val = wm8994_read(codec, reg); return wm8994_write(codec, reg, val | 0x0100); diff --git a/sound/soc/codecs/wm8994_samsung.h b/sound/soc/codecs/wm8994_samsung.h index fa0c4a8..5a0f1cb 100755 --- a/sound/soc/codecs/wm8994_samsung.h +++ b/sound/soc/codecs/wm8994_samsung.h @@ -98,6 +98,12 @@ struct wm8994_setup_data { unsigned short i2c_address; }; +enum wm8994_dc_servo_slots { + DCS_MEDIA = 0, + DCS_VOICE = 1, + DCS_SPK_HP = 2, +}; + struct wm8994_priv { struct snd_soc_codec codec; int master; @@ -121,6 +127,7 @@ struct wm8994_priv { struct wm8994_platform_data *pdata; struct clk *codec_clk; int gain_code; + u16 dc_servo[3]; }; struct gain_info_t { |