summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShuming Fan <shumingf@realtek.com>2021-07-27 11:48:46 +0300
committerMark Brown <broonie@kernel.org>2021-07-27 15:14:52 +0300
commit89d751d8f9dcfb69d1153070d5e5a86d36ac1b45 (patch)
treed76e1f234a369b4e2b25e26da8f548d1dd55abba
parentbc1c8e4eee79646b9ae10ededed06a569c7c2bc9 (diff)
downloadlinux-89d751d8f9dcfb69d1153070d5e5a86d36ac1b45.tar.xz
ASoC: rt5682: enable SAR ADC power saving mode during suspend
The SAR ADC power saving mode could reduce power consumption on MICVDD rail. Therefore, this patch saves power consumption during suspend state if the headset was connected. Signed-off-by: Shuming Fan <shumingf@realtek.com> Link: https://lore.kernel.org/r/20210727084846.9867-1-shumingf@realtek.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/rt5682.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index e4c91571abae..f50c0c8133d4 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -2911,10 +2911,46 @@ static void rt5682_remove(struct snd_soc_component *component)
static int rt5682_suspend(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ unsigned int val;
if (rt5682->is_sdw)
return 0;
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+ cancel_delayed_work_sync(&rt5682->jd_check_work);
+ if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+ RT5682_CTRL_MB1_REG | RT5682_CTRL_MB2_REG);
+ val = snd_soc_component_read(component,
+ RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK;
+
+ switch (val) {
+ case 0x1:
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+ RT5682_SAR_SEL_MB1_NOSEL | RT5682_SAR_SEL_MB2_SEL);
+ break;
+ case 0x2:
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+ RT5682_SAR_SEL_MB1_SEL | RT5682_SAR_SEL_MB2_NOSEL);
+ break;
+ default:
+ break;
+ }
+
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+ RT5682_PWR_CBJ, 0);
+
+ /* enter SAR ADC power saving mode */
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK, 0);
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK,
+ RT5682_SAR_BUTT_DET_EN | RT5682_SAR_BUTDET_POW_SAV | RT5682_SAR_BUTDET_RST_NORMAL);
+ }
+
regcache_cache_only(rt5682->regmap, true);
regcache_mark_dirty(rt5682->regmap);
return 0;
@@ -2930,6 +2966,14 @@ static int rt5682_resume(struct snd_soc_component *component)
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
+ if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+ RT5682_CTRL_MB1_FSM | RT5682_CTRL_MB2_FSM);
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+ RT5682_PWR_CBJ, RT5682_PWR_CBJ);
+ }
+
mod_delayed_work(system_power_efficient_wq,
&rt5682->jack_detect_work, msecs_to_jiffies(250));