diff options
author | Hector Martin <hector@marcansoft.com> | 2009-12-20 16:51:31 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-12-21 05:20:29 -0500 |
commit | f5de24b06aa46427500d0fdbe8616b73a71d8c28 (patch) | |
tree | 97ce905a10b013357df2abf716af2e3795efa55e | |
parent | 556eea9a926bff8f014b4f80522b4de97ae84213 (diff) |
ALSA: HDA: add powersaving hook for Realtek
The current Realtek code makes no specific provision for turning stuff
off. The codec chip is placed into low-power mode generically, but this
doesn't turn off any external hardware connected to it, in particular
external amplifiers.
This patch creates a hook function that is called by the codec
suspend/resume functions. It ought to disable any external hardware in a
device-specific way. I've implemented a generic ALC889 function that
sets the EAPD pin properly, and used it for the Acer Aspire 8930G which
can benefit from this feature.
On my laptop, this results in ~0.5W extra savings.
Signed-off-by: Hector Martin <hector@marcansoft.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index faeb74f28207..b3abe9ca826d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -337,6 +337,9 @@ struct alc_spec { | |||
337 | /* hooks */ | 337 | /* hooks */ |
338 | void (*init_hook)(struct hda_codec *codec); | 338 | void (*init_hook)(struct hda_codec *codec); |
339 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 339 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
340 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
341 | void (*power_hook)(struct hda_codec *codec, int power); | ||
342 | #endif | ||
340 | 343 | ||
341 | /* for pin sensing */ | 344 | /* for pin sensing */ |
342 | unsigned int sense_updated: 1; | 345 | unsigned int sense_updated: 1; |
@@ -388,6 +391,7 @@ struct alc_config_preset { | |||
388 | void (*init_hook)(struct hda_codec *); | 391 | void (*init_hook)(struct hda_codec *); |
389 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 392 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
390 | struct hda_amp_list *loopbacks; | 393 | struct hda_amp_list *loopbacks; |
394 | void (*power_hook)(struct hda_codec *codec, int power); | ||
391 | #endif | 395 | #endif |
392 | }; | 396 | }; |
393 | 397 | ||
@@ -900,6 +904,7 @@ static void setup_preset(struct hda_codec *codec, | |||
900 | spec->unsol_event = preset->unsol_event; | 904 | spec->unsol_event = preset->unsol_event; |
901 | spec->init_hook = preset->init_hook; | 905 | spec->init_hook = preset->init_hook; |
902 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 906 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
907 | spec->power_hook = preset->power_hook; | ||
903 | spec->loopback.amplist = preset->loopbacks; | 908 | spec->loopback.amplist = preset->loopbacks; |
904 | #endif | 909 | #endif |
905 | 910 | ||
@@ -1826,6 +1831,16 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) | |||
1826 | spec->autocfg.speaker_pins[2] = 0x1b; | 1831 | spec->autocfg.speaker_pins[2] = 0x1b; |
1827 | } | 1832 | } |
1828 | 1833 | ||
1834 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1835 | static void alc889_power_eapd(struct hda_codec *codec, int power) | ||
1836 | { | ||
1837 | snd_hda_codec_write(codec, 0x14, 0, | ||
1838 | AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); | ||
1839 | snd_hda_codec_write(codec, 0x15, 0, | ||
1840 | AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); | ||
1841 | } | ||
1842 | #endif | ||
1843 | |||
1829 | /* | 1844 | /* |
1830 | * ALC880 3-stack model | 1845 | * ALC880 3-stack model |
1831 | * | 1846 | * |
@@ -3619,12 +3634,29 @@ static void alc_free(struct hda_codec *codec) | |||
3619 | snd_hda_detach_beep_device(codec); | 3634 | snd_hda_detach_beep_device(codec); |
3620 | } | 3635 | } |
3621 | 3636 | ||
3637 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3638 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) | ||
3639 | { | ||
3640 | struct alc_spec *spec = codec->spec; | ||
3641 | if (spec && spec->power_hook) | ||
3642 | spec->power_hook(codec, 0); | ||
3643 | return 0; | ||
3644 | } | ||
3645 | #endif | ||
3646 | |||
3622 | #ifdef SND_HDA_NEEDS_RESUME | 3647 | #ifdef SND_HDA_NEEDS_RESUME |
3623 | static int alc_resume(struct hda_codec *codec) | 3648 | static int alc_resume(struct hda_codec *codec) |
3624 | { | 3649 | { |
3650 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3651 | struct alc_spec *spec = codec->spec; | ||
3652 | #endif | ||
3625 | codec->patch_ops.init(codec); | 3653 | codec->patch_ops.init(codec); |
3626 | snd_hda_codec_resume_amp(codec); | 3654 | snd_hda_codec_resume_amp(codec); |
3627 | snd_hda_codec_resume_cache(codec); | 3655 | snd_hda_codec_resume_cache(codec); |
3656 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3657 | if (spec && spec->power_hook) | ||
3658 | spec->power_hook(codec, 1); | ||
3659 | #endif | ||
3628 | return 0; | 3660 | return 0; |
3629 | } | 3661 | } |
3630 | #endif | 3662 | #endif |
@@ -3641,6 +3673,7 @@ static struct hda_codec_ops alc_patch_ops = { | |||
3641 | .resume = alc_resume, | 3673 | .resume = alc_resume, |
3642 | #endif | 3674 | #endif |
3643 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3675 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
3676 | .suspend = alc_suspend, | ||
3644 | .check_power_status = alc_check_power_status, | 3677 | .check_power_status = alc_check_power_status, |
3645 | #endif | 3678 | #endif |
3646 | }; | 3679 | }; |
@@ -9420,6 +9453,9 @@ static struct alc_config_preset alc882_presets[] = { | |||
9420 | .unsol_event = alc_automute_amp_unsol_event, | 9453 | .unsol_event = alc_automute_amp_unsol_event, |
9421 | .setup = alc889_acer_aspire_8930g_setup, | 9454 | .setup = alc889_acer_aspire_8930g_setup, |
9422 | .init_hook = alc_automute_amp, | 9455 | .init_hook = alc_automute_amp, |
9456 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
9457 | .power_hook = alc889_power_eapd, | ||
9458 | #endif | ||
9423 | }, | 9459 | }, |
9424 | [ALC888_ACER_ASPIRE_7730G] = { | 9460 | [ALC888_ACER_ASPIRE_7730G] = { |
9425 | .mixers = { alc883_3ST_6ch_mixer, | 9461 | .mixers = { alc883_3ST_6ch_mixer, |