aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-03-16 16:32:11 -0400
committerTakashi Iwai <tiwai@suse.de>2015-03-18 04:22:28 -0400
commite6feb5d08509be1af2ebc894dae35f32f7b92ab6 (patch)
treed5f993a6e71646577c2ec824a89500a386a39e07
parentfb83b6351052bf78686df2559f7ea6b10e596850 (diff)
ALSA: hda - Support advanced power state controls
This patch enables the finer power state control of each widget depending on the jack plug state and streaming state in addition to the existing power_down_unused power optimization. The new feature is enabled only when codec->power_mgmt flag is set. Two new flags, pin_enabled and stream_enabled, are introduced in nid_path struct for marking the two individual power states: the pin plug/unplug and DAC/ADC stream, respectively. They can be set statically in case they are static routes (e.g. some mixer paths), too. The power up and down events for each pin are triggered via the standard hda_jack table. The call order is hard-coded, relying on the current implementation of jack event chain (a la FILO/stack order). One point to be dealt carefully is that DAC/ADC cannot be powered on/off while streaming. They are pinned as long as the stream is running. For controlling the power of DAC/ADC, a new patch_ops is added. The generic parser provides the default callback for that. As of this patch, only IDT/Sigmatel codec driver enables the flag. The support on other codecs will follow. An assumption we made in this code is that the widget state (e.g. amp, pinctl, connections) remains after the widget power transition (not about FG power transition). This is true for IDT codecs, at least. But if the widget state is lost at widget power transition, we'd need to implement additional code to sync the cached amp/verbs for the specific NID. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_codec.c4
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_generic.c301
-rw-r--r--sound/pci/hda/hda_generic.h5
-rw-r--r--sound/pci/hda/patch_sigmatel.c5
5 files changed, 269 insertions, 48 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 3e4fb7a8fdcb..7e38d6f7314b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1502,6 +1502,8 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1502 if (!p) 1502 if (!p)
1503 return; 1503 return;
1504 1504
1505 if (codec->patch_ops.stream_pm)
1506 codec->patch_ops.stream_pm(codec, nid, true);
1505 if (codec->pcm_format_first) 1507 if (codec->pcm_format_first)
1506 update_pcm_format(codec, p, nid, format); 1508 update_pcm_format(codec, p, nid, format);
1507 update_pcm_stream_id(codec, p, nid, stream_tag, channel_id); 1509 update_pcm_stream_id(codec, p, nid, stream_tag, channel_id);
@@ -1570,6 +1572,8 @@ static void really_cleanup_stream(struct hda_codec *codec,
1570); 1572);
1571 memset(q, 0, sizeof(*q)); 1573 memset(q, 0, sizeof(*q));
1572 q->nid = nid; 1574 q->nid = nid;
1575 if (codec->patch_ops.stream_pm)
1576 codec->patch_ops.stream_pm(codec, nid, false);
1573} 1577}
1574 1578
1575/* clean up the all conflicting obsolete streams */ 1579/* clean up the all conflicting obsolete streams */
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 70851e6d5f10..148e84ce61cf 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -200,6 +200,7 @@ struct hda_codec_ops {
200 int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); 200 int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
201#endif 201#endif
202 void (*reboot_notify)(struct hda_codec *codec); 202 void (*reboot_notify)(struct hda_codec *codec);
203 void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on);
203}; 204};
204 205
205/* record for amp information cache */ 206/* record for amp information cache */
@@ -370,6 +371,7 @@ struct hda_codec {
370 unsigned int cached_write:1; /* write only to caches */ 371 unsigned int cached_write:1; /* write only to caches */
371 unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */ 372 unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */
372 unsigned int dump_coef:1; /* dump processing coefs in codec proc file */ 373 unsigned int dump_coef:1; /* dump processing coefs in codec proc file */
374 unsigned int power_mgmt:1; /* advanced PM for each widget */
373#ifdef CONFIG_PM 375#ifdef CONFIG_PM
374 unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ 376 unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
375 atomic_t in_pm; /* suspend/resume being performed */ 377 atomic_t in_pm; /* suspend/resume being performed */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 27ce54701f0f..8a5055d296f5 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -140,6 +140,9 @@ static void parse_user_hints(struct hda_codec *codec)
140 val = snd_hda_get_bool_hint(codec, "single_adc_amp"); 140 val = snd_hda_get_bool_hint(codec, "single_adc_amp");
141 if (val >= 0) 141 if (val >= 0)
142 codec->single_adc_amp = !!val; 142 codec->single_adc_amp = !!val;
143 val = snd_hda_get_bool_hint(codec, "power_mgmt");
144 if (val >= 0)
145 codec->power_mgmt = !!val;
143 146
144 val = snd_hda_get_bool_hint(codec, "auto_mute"); 147 val = snd_hda_get_bool_hint(codec, "auto_mute");
145 if (val >= 0) 148 if (val >= 0)
@@ -648,12 +651,21 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
648 unsigned int dir, unsigned int idx) 651 unsigned int dir, unsigned int idx)
649{ 652{
650 struct hda_gen_spec *spec = codec->spec; 653 struct hda_gen_spec *spec = codec->spec;
654 int type = get_wcaps_type(get_wcaps(codec, nid));
651 int i, n; 655 int i, n;
652 656
653 for (n = 0; n < spec->paths.used; n++) { 657 for (n = 0; n < spec->paths.used; n++) {
654 struct nid_path *path = snd_array_elem(&spec->paths, n); 658 struct nid_path *path = snd_array_elem(&spec->paths, n);
655 if (!path->active) 659 if (!path->active)
656 continue; 660 continue;
661 if (codec->power_mgmt) {
662 if (!path->stream_enabled)
663 continue;
664 /* ignore unplugged paths except for DAC/ADC */
665 if (!path->pin_enabled &&
666 type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
667 continue;
668 }
657 for (i = 0; i < path->depth; i++) { 669 for (i = 0; i < path->depth; i++) {
658 if (path->path[i] == nid) { 670 if (path->path[i] == nid) {
659 if (dir == HDA_OUTPUT || path->idx[i] == idx) 671 if (dir == HDA_OUTPUT || path->idx[i] == idx)
@@ -807,6 +819,42 @@ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
807 } 819 }
808} 820}
809 821
822/* sync power of each widget in the the given path */
823static hda_nid_t path_power_update(struct hda_codec *codec,
824 struct nid_path *path,
825 bool allow_powerdown)
826{
827 hda_nid_t nid, changed = 0;
828 int i, state;
829
830 for (i = 0; i < path->depth; i++) {
831 nid = path->path[i];
832 if (!allow_powerdown || is_active_nid_for_any(codec, nid))
833 state = AC_PWRST_D0;
834 else
835 state = AC_PWRST_D3;
836 if (!snd_hda_check_power_state(codec, nid, state)) {
837 snd_hda_codec_write(codec, nid, 0,
838 AC_VERB_SET_POWER_STATE, state);
839 changed = nid;
840 /* here we assume that widget attributes (e.g. amp,
841 * pinctl connection) don't change with local power
842 * state change. If not, need to sync the cache.
843 */
844 }
845 }
846 return changed;
847}
848
849/* do sync with the last power state change */
850static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
851{
852 if (nid) {
853 msleep(10);
854 snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
855 }
856}
857
810/** 858/**
811 * snd_hda_activate_path - activate or deactivate the given path 859 * snd_hda_activate_path - activate or deactivate the given path
812 * @codec: the HDA codec 860 * @codec: the HDA codec
@@ -825,15 +873,13 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
825 if (!enable) 873 if (!enable)
826 path->active = false; 874 path->active = false;
827 875
876 /* make sure the widget is powered up */
877 if (enable && (spec->power_down_unused || codec->power_mgmt))
878 path_power_update(codec, path, codec->power_mgmt);
879
828 for (i = path->depth - 1; i >= 0; i--) { 880 for (i = path->depth - 1; i >= 0; i--) {
829 hda_nid_t nid = path->path[i]; 881 hda_nid_t nid = path->path[i];
830 if (enable && spec->power_down_unused) { 882
831 /* make sure the widget is powered up */
832 if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
833 snd_hda_codec_write(codec, nid, 0,
834 AC_VERB_SET_POWER_STATE,
835 AC_PWRST_D0);
836 }
837 if (enable && path->multi[i]) 883 if (enable && path->multi[i])
838 snd_hda_codec_update_cache(codec, nid, 0, 884 snd_hda_codec_update_cache(codec, nid, 0,
839 AC_VERB_SET_CONNECT_SEL, 885 AC_VERB_SET_CONNECT_SEL,
@@ -853,28 +899,10 @@ EXPORT_SYMBOL_GPL(snd_hda_activate_path);
853static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path) 899static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
854{ 900{
855 struct hda_gen_spec *spec = codec->spec; 901 struct hda_gen_spec *spec = codec->spec;
856 bool changed = false;
857 int i;
858 902
859 if (!spec->power_down_unused || path->active) 903 if (!(spec->power_down_unused || codec->power_mgmt) || path->active)
860 return; 904 return;
861 905 sync_power_state_change(codec, path_power_update(codec, path, true));
862 for (i = 0; i < path->depth; i++) {
863 hda_nid_t nid = path->path[i];
864 if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
865 !is_active_nid_for_any(codec, nid)) {
866 snd_hda_codec_write(codec, nid, 0,
867 AC_VERB_SET_POWER_STATE,
868 AC_PWRST_D3);
869 changed = true;
870 }
871 }
872
873 if (changed) {
874 msleep(10);
875 snd_hda_codec_read(codec, path->path[0], 0,
876 AC_VERB_GET_POWER_STATE, 0);
877 }
878} 906}
879 907
880/* turn on/off EAPD on the given pin */ 908/* turn on/off EAPD on the given pin */
@@ -1574,6 +1602,7 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1574 return 0; 1602 return 0;
1575 /* print_nid_path(codec, "output-aamix", path); */ 1603 /* print_nid_path(codec, "output-aamix", path); */
1576 path->active = false; /* unused as default */ 1604 path->active = false; /* unused as default */
1605 path->pin_enabled = true; /* static route */
1577 return snd_hda_get_path_idx(codec, path); 1606 return snd_hda_get_path_idx(codec, path);
1578} 1607}
1579 1608
@@ -2998,6 +3027,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
2998 } 3027 }
2999 3028
3000 path->active = true; 3029 path->active = true;
3030 path->stream_enabled = true; /* no DAC/ADC involved */
3001 err = add_loopback_list(spec, mix_nid, idx); 3031 err = add_loopback_list(spec, mix_nid, idx);
3002 if (err < 0) 3032 if (err < 0)
3003 return err; 3033 return err;
@@ -3009,6 +3039,8 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
3009 if (path) { 3039 if (path) {
3010 print_nid_path(codec, "loopback-merge", path); 3040 print_nid_path(codec, "loopback-merge", path);
3011 path->active = true; 3041 path->active = true;
3042 path->pin_enabled = true; /* static route */
3043 path->stream_enabled = true; /* no DAC/ADC involved */
3012 spec->loopback_merge_path = 3044 spec->loopback_merge_path =
3013 snd_hda_get_path_idx(codec, path); 3045 snd_hda_get_path_idx(codec, path);
3014 } 3046 }
@@ -3810,6 +3842,7 @@ static void parse_digital(struct hda_codec *codec)
3810 continue; 3842 continue;
3811 print_nid_path(codec, "digout", path); 3843 print_nid_path(codec, "digout", path);
3812 path->active = true; 3844 path->active = true;
3845 path->pin_enabled = true; /* no jack detection */
3813 spec->digout_paths[i] = snd_hda_get_path_idx(codec, path); 3846 spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
3814 set_pin_target(codec, pin, PIN_OUT, false); 3847 set_pin_target(codec, pin, PIN_OUT, false);
3815 if (!nums) { 3848 if (!nums) {
@@ -3837,6 +3870,7 @@ static void parse_digital(struct hda_codec *codec)
3837 if (path) { 3870 if (path) {
3838 print_nid_path(codec, "digin", path); 3871 print_nid_path(codec, "digin", path);
3839 path->active = true; 3872 path->active = true;
3873 path->pin_enabled = true; /* no jack */
3840 spec->dig_in_nid = dig_nid; 3874 spec->dig_in_nid = dig_nid;
3841 spec->digin_path = snd_hda_get_path_idx(codec, path); 3875 spec->digin_path = snd_hda_get_path_idx(codec, path);
3842 set_pin_target(codec, pin, PIN_IN, false); 3876 set_pin_target(codec, pin, PIN_IN, false);
@@ -3896,6 +3930,148 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3896 return 1; 3930 return 1;
3897} 3931}
3898 3932
3933/* power up/down widgets in the all paths that match with the given NID
3934 * as terminals (either start- or endpoint)
3935 *
3936 * returns the last changed NID, or zero if unchanged.
3937 */
3938static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
3939 int pin_state, int stream_state)
3940{
3941 struct hda_gen_spec *spec = codec->spec;
3942 hda_nid_t last, changed = 0;
3943 struct nid_path *path;
3944 int n;
3945
3946 for (n = 0; n < spec->paths.used; n++) {
3947 path = snd_array_elem(&spec->paths, n);
3948 if (path->path[0] == nid ||
3949 path->path[path->depth - 1] == nid) {
3950 bool pin_old = path->pin_enabled;
3951 bool stream_old = path->stream_enabled;
3952
3953 if (pin_state >= 0)
3954 path->pin_enabled = pin_state;
3955 if (stream_state >= 0)
3956 path->stream_enabled = stream_state;
3957 if (path->pin_enabled != pin_old ||
3958 path->stream_enabled != stream_old) {
3959 last = path_power_update(codec, path, true);
3960 if (last)
3961 changed = last;
3962 }
3963 }
3964 }
3965 return changed;
3966}
3967
3968/* power up/down the paths of the given pin according to the jack state;
3969 * power = 0/1 : only power up/down if it matches with the jack state,
3970 * < 0 : force power up/down to follow the jack sate
3971 *
3972 * returns the last changed NID, or zero if unchanged.
3973 */
3974static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
3975 int power)
3976{
3977 bool on;
3978
3979 if (!codec->power_mgmt)
3980 return 0;
3981
3982 on = snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
3983 if (power >= 0 && on != power)
3984 return 0;
3985 return set_path_power(codec, pin, on, -1);
3986}
3987
3988static void pin_power_callback(struct hda_codec *codec,
3989 struct hda_jack_callback *jack,
3990 bool on)
3991{
3992 if (jack && jack->tbl->nid)
3993 sync_power_state_change(codec,
3994 set_pin_power_jack(codec, jack->tbl->nid, on));
3995}
3996
3997/* callback only doing power up -- called at first */
3998static void pin_power_up_callback(struct hda_codec *codec,
3999 struct hda_jack_callback *jack)
4000{
4001 pin_power_callback(codec, jack, true);
4002}
4003
4004/* callback only doing power down -- called at last */
4005static void pin_power_down_callback(struct hda_codec *codec,
4006 struct hda_jack_callback *jack)
4007{
4008 pin_power_callback(codec, jack, false);
4009}
4010
4011/* set up the power up/down callbacks */
4012static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4013 const hda_nid_t *pins, bool on)
4014{
4015 int i;
4016 hda_jack_callback_fn cb =
4017 on ? pin_power_up_callback : pin_power_down_callback;
4018
4019 for (i = 0; i < num_pins && pins[i]; i++) {
4020 if (is_jack_detectable(codec, pins[i]))
4021 snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4022 else
4023 set_path_power(codec, pins[i], true, -1);
4024 }
4025}
4026
4027/* enabled power callback to each available I/O pin with jack detections;
4028 * the digital I/O pins are excluded because of the unreliable detectsion
4029 */
4030static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4031{
4032 struct hda_gen_spec *spec = codec->spec;
4033 struct auto_pin_cfg *cfg = &spec->autocfg;
4034 int i;
4035
4036 if (!codec->power_mgmt)
4037 return;
4038 add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4039 if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4040 add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4041 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4042 add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4043 for (i = 0; i < cfg->num_inputs; i++)
4044 add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4045}
4046
4047/* sync path power up/down with the jack states of given pins */
4048static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4049 const hda_nid_t *pins)
4050{
4051 int i;
4052
4053 for (i = 0; i < num_pins && pins[i]; i++)
4054 if (is_jack_detectable(codec, pins[i]))
4055 set_pin_power_jack(codec, pins[i], -1);
4056}
4057
4058/* sync path power up/down with pins; called at init and resume */
4059static void sync_all_pin_power_ctls(struct hda_codec *codec)
4060{
4061 struct hda_gen_spec *spec = codec->spec;
4062 struct auto_pin_cfg *cfg = &spec->autocfg;
4063 int i;
4064
4065 if (!codec->power_mgmt)
4066 return;
4067 sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4068 if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4069 sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4070 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4071 sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4072 for (i = 0; i < cfg->num_inputs; i++)
4073 sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4074}
3899 4075
3900/* 4076/*
3901 * Jack detections for HP auto-mute and mic-switch 4077 * Jack detections for HP auto-mute and mic-switch
@@ -3933,6 +4109,10 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3933 if (!nid) 4109 if (!nid)
3934 break; 4110 break;
3935 4111
4112 oldval = snd_hda_codec_get_pin_target(codec, nid);
4113 if (oldval & PIN_IN)
4114 continue; /* no mute for inputs */
4115
3936 if (spec->auto_mute_via_amp) { 4116 if (spec->auto_mute_via_amp) {
3937 struct nid_path *path; 4117 struct nid_path *path;
3938 hda_nid_t mute_nid; 4118 hda_nid_t mute_nid;
@@ -3947,29 +4127,33 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3947 spec->mute_bits |= (1ULL << mute_nid); 4127 spec->mute_bits |= (1ULL << mute_nid);
3948 else 4128 else
3949 spec->mute_bits &= ~(1ULL << mute_nid); 4129 spec->mute_bits &= ~(1ULL << mute_nid);
3950 set_pin_eapd(codec, nid, !mute);
3951 continue; 4130 continue;
4131 } else {
4132 /* don't reset VREF value in case it's controlling
4133 * the amp (see alc861_fixup_asus_amp_vref_0f())
4134 */
4135 if (spec->keep_vref_in_automute)
4136 val = oldval & ~PIN_HP;
4137 else
4138 val = 0;
4139 if (!mute)
4140 val |= oldval;
4141 /* here we call update_pin_ctl() so that the pinctl is
4142 * changed without changing the pinctl target value;
4143 * the original target value will be still referred at
4144 * the init / resume again
4145 */
4146 update_pin_ctl(codec, nid, val);
3952 } 4147 }
3953 4148
3954 oldval = snd_hda_codec_get_pin_target(codec, nid);
3955 if (oldval & PIN_IN)
3956 continue; /* no mute for inputs */
3957 /* don't reset VREF value in case it's controlling
3958 * the amp (see alc861_fixup_asus_amp_vref_0f())
3959 */
3960 if (spec->keep_vref_in_automute)
3961 val = oldval & ~PIN_HP;
3962 else
3963 val = 0;
3964 if (!mute)
3965 val |= oldval;
3966 /* here we call update_pin_ctl() so that the pinctl is changed
3967 * without changing the pinctl target value;
3968 * the original target value will be still referred at the
3969 * init / resume again
3970 */
3971 update_pin_ctl(codec, nid, val);
3972 set_pin_eapd(codec, nid, !mute); 4149 set_pin_eapd(codec, nid, !mute);
4150 if (codec->power_mgmt) {
4151 bool on = !mute;
4152 if (on)
4153 on = snd_hda_jack_detect_state(codec, nid)
4154 != HDA_JACK_NOT_PRESENT;
4155 set_path_power(codec, nid, on, -1);
4156 }
3973 } 4157 }
3974} 4158}
3975 4159
@@ -4466,6 +4650,21 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4466} 4650}
4467 4651
4468/** 4652/**
4653 * snd_hda_gen_stream_pm - Stream power management callback
4654 * @codec: the HDA codec
4655 * @nid: audio widget
4656 * @on: power on/off flag
4657 *
4658 * Set this in patch_ops.stream_pm. Only valid with power_mgmt flag.
4659 */
4660void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
4661{
4662 if (codec->power_mgmt)
4663 set_path_power(codec, nid, -1, on);
4664}
4665EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
4666
4667/**
4469 * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and 4668 * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
4470 * set up the hda_gen_spec 4669 * set up the hda_gen_spec
4471 * @codec: the HDA codec 4670 * @codec: the HDA codec
@@ -4549,6 +4748,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
4549 if (err < 0) 4748 if (err < 0)
4550 return err; 4749 return err;
4551 4750
4751 /* add power-down pin callbacks at first */
4752 add_all_pin_power_ctls(codec, false);
4753
4552 spec->const_channel_count = spec->ext_channel_count; 4754 spec->const_channel_count = spec->ext_channel_count;
4553 /* check the multiple speaker and headphone pins */ 4755 /* check the multiple speaker and headphone pins */
4554 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) 4756 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
@@ -4618,6 +4820,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
4618 } 4820 }
4619 } 4821 }
4620 4822
4823 /* add power-up pin callbacks at last */
4824 add_all_pin_power_ctls(codec, true);
4825
4621 /* mute all aamix input initially */ 4826 /* mute all aamix input initially */
4622 if (spec->mixer_nid) 4827 if (spec->mixer_nid)
4623 mute_all_mixer_nid(codec, spec->mixer_nid); 4828 mute_all_mixer_nid(codec, spec->mixer_nid);
@@ -4625,7 +4830,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
4625 dig_only: 4830 dig_only:
4626 parse_digital(codec); 4831 parse_digital(codec);
4627 4832
4628 if (spec->power_down_unused) 4833 if (spec->power_down_unused || codec->power_mgmt)
4629 codec->power_filter = snd_hda_gen_path_power_filter; 4834 codec->power_filter = snd_hda_gen_path_power_filter;
4630 4835
4631 if (!spec->no_analog && spec->beep_nid) { 4836 if (!spec->no_analog && spec->beep_nid) {
@@ -5478,6 +5683,8 @@ int snd_hda_gen_init(struct hda_codec *codec)
5478 5683
5479 clear_unsol_on_unused_pins(codec); 5684 clear_unsol_on_unused_pins(codec);
5480 5685
5686 sync_all_pin_power_ctls(codec);
5687
5481 /* call init functions of standard auto-mute helpers */ 5688 /* call init functions of standard auto-mute helpers */
5482 update_automute_all(codec); 5689 update_automute_all(codec);
5483 5690
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index b211f889b335..54659b51fe16 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -46,7 +46,9 @@ struct nid_path {
46 unsigned char idx[MAX_NID_PATH_DEPTH]; 46 unsigned char idx[MAX_NID_PATH_DEPTH];
47 unsigned char multi[MAX_NID_PATH_DEPTH]; 47 unsigned char multi[MAX_NID_PATH_DEPTH];
48 unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */ 48 unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */
49 bool active; 49 bool active:1; /* activated by driver */
50 bool pin_enabled:1; /* pins are enabled */
51 bool stream_enabled:1; /* stream is active */
50}; 52};
51 53
52/* mic/line-in auto switching entry */ 54/* mic/line-in auto switching entry */
@@ -340,5 +342,6 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
340unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, 342unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
341 hda_nid_t nid, 343 hda_nid_t nid,
342 unsigned int power_state); 344 unsigned int power_state);
345void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
343 346
344#endif /* __SOUND_HDA_GENERIC_H */ 347#endif /* __SOUND_HDA_GENERIC_H */
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 2956a6ba6bf0..86b944a6b0ed 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4394,6 +4394,7 @@ static const struct hda_codec_ops stac_patch_ops = {
4394#ifdef CONFIG_PM 4394#ifdef CONFIG_PM
4395 .suspend = stac_suspend, 4395 .suspend = stac_suspend,
4396#endif 4396#endif
4397 .stream_pm = snd_hda_gen_stream_pm,
4397 .reboot_notify = stac_shutup, 4398 .reboot_notify = stac_shutup,
4398}; 4399};
4399 4400
@@ -4487,6 +4488,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
4487 return err; 4488 return err;
4488 4489
4489 spec = codec->spec; 4490 spec = codec->spec;
4491 codec->power_mgmt = 1;
4490 spec->linear_tone_beep = 0; 4492 spec->linear_tone_beep = 0;
4491 spec->gen.mixer_nid = 0x1d; 4493 spec->gen.mixer_nid = 0x1d;
4492 spec->have_spdif_mux = 1; 4494 spec->have_spdif_mux = 1;
@@ -4592,6 +4594,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
4592 codec->epss = 0; /* longer delay needed for D3 */ 4594 codec->epss = 0; /* longer delay needed for D3 */
4593 4595
4594 spec = codec->spec; 4596 spec = codec->spec;
4597 codec->power_mgmt = 1;
4595 spec->linear_tone_beep = 0; 4598 spec->linear_tone_beep = 0;
4596 spec->gen.own_eapd_ctl = 1; 4599 spec->gen.own_eapd_ctl = 1;
4597 spec->gen.power_down_unused = 1; 4600 spec->gen.power_down_unused = 1;
@@ -4641,6 +4644,7 @@ static int patch_stac92hd95(struct hda_codec *codec)
4641 codec->epss = 0; /* longer delay needed for D3 */ 4644 codec->epss = 0; /* longer delay needed for D3 */
4642 4645
4643 spec = codec->spec; 4646 spec = codec->spec;
4647 codec->power_mgmt = 1;
4644 spec->linear_tone_beep = 0; 4648 spec->linear_tone_beep = 0;
4645 spec->gen.own_eapd_ctl = 1; 4649 spec->gen.own_eapd_ctl = 1;
4646 spec->gen.power_down_unused = 1; 4650 spec->gen.power_down_unused = 1;
@@ -4682,6 +4686,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
4682 return err; 4686 return err;
4683 4687
4684 spec = codec->spec; 4688 spec = codec->spec;
4689 codec->power_mgmt = 1;
4685 spec->linear_tone_beep = 0; 4690 spec->linear_tone_beep = 0;
4686 spec->gen.own_eapd_ctl = 1; 4691 spec->gen.own_eapd_ctl = 1;
4687 spec->gen.power_down_unused = 1; 4692 spec->gen.power_down_unused = 1;