X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=sound%2Fpci%2Fhda%2Fhda_generic.c;h=3d2597b7037bbc9c5a74faeeae035f5c5bd70f76;hb=24fef9022a83d789ee372a393ea4782dc22b9b51;hp=f7ccef5559deac7e77d5f5bc7fe1b155d5f17d30;hpb=a551d91473e5e3a591f6fe86ac5a5fb460c3f96a;p=firefly-linux-kernel-4.4.55.git diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index f7ccef5559de..3d2597b7037b 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -832,6 +832,8 @@ static hda_nid_t path_power_update(struct hda_codec *codec, for (i = 0; i < path->depth; i++) { nid = path->path[i]; + if (!(get_wcaps(codec, nid) & AC_WCAP_POWER)) + continue; if (nid == codec->core.afg) continue; if (!allow_powerdown || is_active_nid_for_any(codec, nid)) @@ -842,10 +844,8 @@ static hda_nid_t path_power_update(struct hda_codec *codec, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, state); changed = nid; - /* here we assume that widget attributes (e.g. amp, - * pinctl connection) don't change with local power - * state change. If not, need to sync the cache. - */ + if (state == AC_PWRST_D0) + snd_hdac_regmap_sync_node(&codec->core, nid); } } return changed; @@ -3959,6 +3959,14 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid, return changed; } +/* check the jack status for power control */ +static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin) +{ + if (!is_jack_detectable(codec, pin)) + return true; + return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT; +} + /* power up/down the paths of the given pin according to the jack state; * power = 0/1 : only power up/down if it matches with the jack state, * < 0 : force power up/down to follow the jack sate @@ -3973,7 +3981,8 @@ static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin, if (!codec->power_save_node) return 0; - on = snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT; + on = detect_pin_state(codec, pin); + if (power >= 0 && on != power) return 0; return set_path_power(codec, pin, on, -1); @@ -4225,8 +4234,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, if (codec->power_save_node) { bool on = !mute; if (on) - on = snd_hda_jack_detect_state(codec, nid) - != HDA_JACK_NOT_PRESENT; + on = detect_pin_state(codec, nid); set_path_power(codec, nid, on, -1); } } @@ -4695,6 +4703,10 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, hda_nid_t nid, unsigned int power_state) { + struct hda_gen_spec *spec = codec->spec; + + if (!spec->power_down_unused && !codec->power_save_node) + return power_state; if (power_state != AC_PWRST_D0 || nid == codec->core.afg) return power_state; if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER) @@ -4906,7 +4918,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, parse_digital(codec); if (spec->power_down_unused || codec->power_save_node) - codec->power_filter = snd_hda_gen_path_power_filter; + if (!codec->power_filter) + codec->power_filter = snd_hda_gen_path_power_filter; if (!spec->no_analog && spec->beep_nid) { err = snd_hda_attach_beep_device(codec, spec->beep_nid);