Commit 6b275b14 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Fix power of pins used for mute LED with vrefs

Some pins are used for controlling the LED with the VREF value.
This patch changes the power behavior of such pins to be constantly
up.  A new state, pin_fixed, is introduced to nid_path to indicate
that the path contains the fixed pin.  This improves also the
readability a bit for other static routes, too.

Then a helper function snd_hda_gen_fix_pin_power() is called from the
codec driver for such fixed pins, and it will create fake paths
containing only these pins with pin_fixed=1 flag.
Reported-by: default avatarDavid Henningsson <david.henningsson@canonical.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent fc0daafe
...@@ -665,7 +665,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid, ...@@ -665,7 +665,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
if (!path->stream_enabled) if (!path->stream_enabled)
continue; continue;
/* ignore unplugged paths except for DAC/ADC */ /* ignore unplugged paths except for DAC/ADC */
if (!path->pin_enabled && if (!(path->pin_enabled || path->pin_fixed) &&
type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN) type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
continue; continue;
} }
...@@ -1607,7 +1607,7 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx) ...@@ -1607,7 +1607,7 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
return 0; return 0;
/* print_nid_path(codec, "output-aamix", path); */ /* print_nid_path(codec, "output-aamix", path); */
path->active = false; /* unused as default */ path->active = false; /* unused as default */
path->pin_enabled = true; /* static route */ path->pin_fixed = true; /* static route */
return snd_hda_get_path_idx(codec, path); return snd_hda_get_path_idx(codec, path);
} }
...@@ -3044,7 +3044,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, ...@@ -3044,7 +3044,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
if (path) { if (path) {
print_nid_path(codec, "loopback-merge", path); print_nid_path(codec, "loopback-merge", path);
path->active = true; path->active = true;
path->pin_enabled = true; /* static route */ path->pin_fixed = true; /* static route */
path->stream_enabled = true; /* no DAC/ADC involved */ path->stream_enabled = true; /* no DAC/ADC involved */
spec->loopback_merge_path = spec->loopback_merge_path =
snd_hda_get_path_idx(codec, path); snd_hda_get_path_idx(codec, path);
...@@ -3847,7 +3847,7 @@ static void parse_digital(struct hda_codec *codec) ...@@ -3847,7 +3847,7 @@ static void parse_digital(struct hda_codec *codec)
continue; continue;
print_nid_path(codec, "digout", path); print_nid_path(codec, "digout", path);
path->active = true; path->active = true;
path->pin_enabled = true; /* no jack detection */ path->pin_fixed = true; /* no jack detection */
spec->digout_paths[i] = snd_hda_get_path_idx(codec, path); spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
set_pin_target(codec, pin, PIN_OUT, false); set_pin_target(codec, pin, PIN_OUT, false);
if (!nums) { if (!nums) {
...@@ -3875,7 +3875,7 @@ static void parse_digital(struct hda_codec *codec) ...@@ -3875,7 +3875,7 @@ static void parse_digital(struct hda_codec *codec)
if (path) { if (path) {
print_nid_path(codec, "digin", path); print_nid_path(codec, "digin", path);
path->active = true; path->active = true;
path->pin_enabled = true; /* no jack */ path->pin_fixed = true; /* no jack */
spec->dig_in_nid = dig_nid; spec->dig_in_nid = dig_nid;
spec->digin_path = snd_hda_get_path_idx(codec, path); spec->digin_path = snd_hda_get_path_idx(codec, path);
set_pin_target(codec, pin, PIN_IN, false); set_pin_target(codec, pin, PIN_IN, false);
...@@ -3959,8 +3959,8 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid, ...@@ -3959,8 +3959,8 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
path->pin_enabled = pin_state; path->pin_enabled = pin_state;
if (stream_state >= 0) if (stream_state >= 0)
path->stream_enabled = stream_state; path->stream_enabled = stream_state;
if (path->pin_enabled != pin_old || if ((!path->pin_fixed && path->pin_enabled != pin_old)
path->stream_enabled != stream_old) { || path->stream_enabled != stream_old) {
last = path_power_update(codec, path, true); last = path_power_update(codec, path, true);
if (last) if (last)
changed = last; changed = last;
...@@ -4136,6 +4136,29 @@ static void beep_power_hook(struct hda_beep *beep, bool on) ...@@ -4136,6 +4136,29 @@ static void beep_power_hook(struct hda_beep *beep, bool on)
set_path_power(beep->codec, beep->nid, -1, on); set_path_power(beep->codec, beep->nid, -1, on);
} }
/**
* snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
* @codec: the HDA codec
* @pin: NID of pin to fix
*/
int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
{
struct hda_gen_spec *spec = codec->spec;
struct nid_path *path;
path = snd_array_new(&spec->paths);
if (!path)
return -ENOMEM;
memset(path, 0, sizeof(*path));
path->depth = 1;
path->path[0] = pin;
path->active = true;
path->pin_fixed = true;
path->stream_enabled = true;
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
/* /*
* Jack detections for HP auto-mute and mic-switch * Jack detections for HP auto-mute and mic-switch
*/ */
......
...@@ -48,6 +48,7 @@ struct nid_path { ...@@ -48,6 +48,7 @@ struct nid_path {
unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */ unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */
bool active:1; /* activated by driver */ bool active:1; /* activated by driver */
bool pin_enabled:1; /* pins are enabled */ bool pin_enabled:1; /* pins are enabled */
bool pin_fixed:1; /* path with fixed pin */
bool stream_enabled:1; /* stream is active */ bool stream_enabled:1; /* stream is active */
}; };
...@@ -343,5 +344,6 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, ...@@ -343,5 +344,6 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
hda_nid_t nid, hda_nid_t nid,
unsigned int power_state); unsigned int power_state);
void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on); void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
#endif /* __SOUND_HDA_GENERIC_H */ #endif /* __SOUND_HDA_GENERIC_H */
...@@ -4225,6 +4225,12 @@ static int stac_parse_auto_config(struct hda_codec *codec) ...@@ -4225,6 +4225,12 @@ static int stac_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
if (spec->vref_mute_led_nid) {
err = snd_hda_gen_fix_pin_power(codec, spec->vref_mute_led_nid);
if (err < 0)
return err;
}
/* setup analog beep controls */ /* setup analog beep controls */
if (spec->anabeep_nid > 0) { if (spec->anabeep_nid > 0) {
err = stac_auto_create_beep_ctls(codec, err = stac_auto_create_beep_ctls(codec,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment